1 1.12 jmcneill /* $NetBSD: ti_sdhc.c,v 1.12 2022/02/06 15:52:20 jmcneill Exp $ */ 2 1.1 jmcneill /*- 3 1.1 jmcneill * Copyright (c) 2011 The NetBSD Foundation, Inc. 4 1.1 jmcneill * All rights reserved. 5 1.1 jmcneill * 6 1.1 jmcneill * This code is derived from software contributed to The NetBSD Foundation 7 1.1 jmcneill * by Matt Thomas of 3am Software Foundry. 8 1.1 jmcneill * 9 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 10 1.1 jmcneill * modification, are permitted provided that the following conditions 11 1.1 jmcneill * are met: 12 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 13 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 14 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 16 1.1 jmcneill * documentation and/or other materials provided with the distribution. 17 1.1 jmcneill * 18 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 1.1 jmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 1.1 jmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 1.1 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 1.1 jmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 1.1 jmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 1.1 jmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 1.1 jmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 1.1 jmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 1.1 jmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 1.1 jmcneill * POSSIBILITY OF SUCH DAMAGE. 29 1.1 jmcneill */ 30 1.1 jmcneill 31 1.1 jmcneill #include <sys/cdefs.h> 32 1.12 jmcneill __KERNEL_RCSID(0, "$NetBSD: ti_sdhc.c,v 1.12 2022/02/06 15:52:20 jmcneill Exp $"); 33 1.1 jmcneill 34 1.1 jmcneill #include <sys/param.h> 35 1.1 jmcneill #include <sys/systm.h> 36 1.1 jmcneill #include <sys/device.h> 37 1.1 jmcneill #include <sys/errno.h> 38 1.1 jmcneill #include <sys/kernel.h> 39 1.1 jmcneill #include <sys/proc.h> 40 1.1 jmcneill #include <sys/queue.h> 41 1.1 jmcneill #include <sys/mutex.h> 42 1.1 jmcneill #include <sys/condvar.h> 43 1.1 jmcneill #include <sys/bus.h> 44 1.1 jmcneill 45 1.1 jmcneill #include <arm/ti/ti_prcm.h> 46 1.1 jmcneill #include <arm/ti/ti_edma.h> 47 1.1 jmcneill #include <arm/ti/ti_sdhcreg.h> 48 1.1 jmcneill 49 1.1 jmcneill #include <dev/sdmmc/sdhcreg.h> 50 1.1 jmcneill #include <dev/sdmmc/sdhcvar.h> 51 1.1 jmcneill #include <dev/sdmmc/sdmmcvar.h> 52 1.1 jmcneill 53 1.1 jmcneill #include <dev/fdt/fdtvar.h> 54 1.1 jmcneill 55 1.1 jmcneill #define EDMA_MAX_PARAMS 32 56 1.1 jmcneill 57 1.1 jmcneill #ifdef TISDHC_DEBUG 58 1.1 jmcneill int tisdhcdebug = 1; 59 1.1 jmcneill #define DPRINTF(n,s) do { if ((n) <= tisdhcdebug) device_printf s; } while (0) 60 1.1 jmcneill #else 61 1.1 jmcneill #define DPRINTF(n,s) do {} while (0) 62 1.1 jmcneill #endif 63 1.1 jmcneill 64 1.1 jmcneill 65 1.1 jmcneill #define CLKD(kz) (sc->sc.sc_clkbase / (kz)) 66 1.1 jmcneill 67 1.1 jmcneill #define SDHC_READ(sc, reg) \ 68 1.1 jmcneill bus_space_read_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg)) 69 1.1 jmcneill #define SDHC_WRITE(sc, reg, val) \ 70 1.1 jmcneill bus_space_write_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg), (val)) 71 1.1 jmcneill 72 1.1 jmcneill struct ti_sdhc_config { 73 1.1 jmcneill bus_size_t regoff; 74 1.1 jmcneill uint32_t flags; 75 1.1 jmcneill }; 76 1.1 jmcneill 77 1.1 jmcneill static const struct ti_sdhc_config omap2_hsmmc_config = { 78 1.1 jmcneill }; 79 1.1 jmcneill 80 1.1 jmcneill static const struct ti_sdhc_config omap3_pre_es3_hsmmc_config = { 81 1.1 jmcneill .flags = SDHC_FLAG_SINGLE_ONLY 82 1.1 jmcneill }; 83 1.1 jmcneill 84 1.1 jmcneill static const struct ti_sdhc_config omap4_hsmmc_config = { 85 1.1 jmcneill .regoff = 0x100 86 1.1 jmcneill }; 87 1.1 jmcneill 88 1.11 jmcneill static const struct ti_sdhc_config am335_sdhci_config = { 89 1.11 jmcneill .regoff = 0x100 90 1.11 jmcneill }; 91 1.11 jmcneill 92 1.7 thorpej static const struct device_compatible_entry compat_data[] = { 93 1.7 thorpej { .compat = "ti,omap2-hsmmc", 94 1.7 thorpej .data = &omap2_hsmmc_config }, 95 1.7 thorpej { .compat = "ti,omap3-hsmmc", 96 1.7 thorpej .data = &omap2_hsmmc_config }, 97 1.7 thorpej { .compat = "ti,omap3-pre-es3-hsmmc", 98 1.7 thorpej .data = &omap3_pre_es3_hsmmc_config }, 99 1.7 thorpej { .compat = "ti,omap4-hsmmc", 100 1.7 thorpej .data = &omap4_hsmmc_config }, 101 1.11 jmcneill { .compat = "ti,am335-sdhci", 102 1.11 jmcneill .data = &am335_sdhci_config }, 103 1.7 thorpej 104 1.9 thorpej DEVICE_COMPAT_EOL 105 1.1 jmcneill }; 106 1.1 jmcneill 107 1.1 jmcneill enum { 108 1.1 jmcneill EDMA_CHAN_TX, 109 1.1 jmcneill EDMA_CHAN_RX, 110 1.1 jmcneill EDMA_NCHAN 111 1.1 jmcneill }; 112 1.1 jmcneill 113 1.1 jmcneill struct ti_sdhc_softc { 114 1.1 jmcneill struct sdhc_softc sc; 115 1.1 jmcneill int sc_phandle; 116 1.1 jmcneill bus_addr_t sc_addr; 117 1.1 jmcneill bus_space_tag_t sc_bst; 118 1.1 jmcneill bus_space_handle_t sc_bsh; 119 1.1 jmcneill bus_space_handle_t sc_hl_bsh; 120 1.1 jmcneill bus_space_handle_t sc_sdhc_bsh; 121 1.1 jmcneill struct sdhc_host *sc_hosts[1]; 122 1.1 jmcneill void *sc_ih; /* interrupt vectoring */ 123 1.1 jmcneill 124 1.1 jmcneill int sc_edma_chan[EDMA_NCHAN]; 125 1.1 jmcneill struct edma_channel *sc_edma_tx; 126 1.1 jmcneill struct edma_channel *sc_edma_rx; 127 1.1 jmcneill uint16_t sc_edma_param_tx[EDMA_MAX_PARAMS]; 128 1.1 jmcneill uint16_t sc_edma_param_rx[EDMA_MAX_PARAMS]; 129 1.1 jmcneill kcondvar_t sc_edma_cv; 130 1.1 jmcneill bus_addr_t sc_edma_fifo; 131 1.1 jmcneill bool sc_edma_pending; 132 1.1 jmcneill bus_dmamap_t sc_edma_dmamap; 133 1.1 jmcneill bus_dma_segment_t sc_edma_segs[1]; 134 1.1 jmcneill void *sc_edma_bbuf; 135 1.1 jmcneill }; 136 1.1 jmcneill 137 1.1 jmcneill static int ti_sdhc_match(device_t, cfdata_t, void *); 138 1.1 jmcneill static void ti_sdhc_attach(device_t, device_t, void *); 139 1.1 jmcneill 140 1.1 jmcneill static void ti_sdhc_init(struct ti_sdhc_softc *, const struct ti_sdhc_config *); 141 1.1 jmcneill 142 1.1 jmcneill static int ti_sdhc_bus_width(struct sdhc_softc *, int); 143 1.1 jmcneill static int ti_sdhc_rod(struct sdhc_softc *, int); 144 1.1 jmcneill static int ti_sdhc_write_protect(struct sdhc_softc *); 145 1.1 jmcneill static int ti_sdhc_card_detect(struct sdhc_softc *); 146 1.1 jmcneill 147 1.1 jmcneill static int ti_sdhc_edma_init(struct ti_sdhc_softc *, u_int, u_int); 148 1.1 jmcneill static int ti_sdhc_edma_xfer_data(struct sdhc_softc *, struct sdmmc_command *); 149 1.1 jmcneill static void ti_sdhc_edma_done(void *); 150 1.1 jmcneill static int ti_sdhc_edma_transfer(struct sdhc_softc *, struct sdmmc_command *); 151 1.1 jmcneill 152 1.1 jmcneill CFATTACH_DECL_NEW(ti_sdhc, sizeof(struct ti_sdhc_softc), 153 1.1 jmcneill ti_sdhc_match, ti_sdhc_attach, NULL, NULL); 154 1.1 jmcneill 155 1.1 jmcneill static int 156 1.1 jmcneill ti_sdhc_match(device_t parent, cfdata_t cf, void *aux) 157 1.1 jmcneill { 158 1.1 jmcneill struct fdt_attach_args * const faa = aux; 159 1.1 jmcneill 160 1.10 thorpej return of_compatible_match(faa->faa_phandle, compat_data); 161 1.1 jmcneill } 162 1.1 jmcneill 163 1.1 jmcneill static void 164 1.1 jmcneill ti_sdhc_attach(device_t parent, device_t self, void *aux) 165 1.1 jmcneill { 166 1.1 jmcneill struct ti_sdhc_softc * const sc = device_private(self); 167 1.1 jmcneill struct fdt_attach_args * const faa = aux; 168 1.1 jmcneill const int phandle = faa->faa_phandle; 169 1.1 jmcneill const struct ti_sdhc_config *conf; 170 1.1 jmcneill bus_addr_t addr; 171 1.1 jmcneill bus_size_t size; 172 1.1 jmcneill u_int bus_width; 173 1.1 jmcneill 174 1.10 thorpej conf = of_compatible_lookup(phandle, compat_data)->data; 175 1.1 jmcneill 176 1.3 jmcneill if (ti_prcm_enable_hwmod(phandle, 0) != 0) { 177 1.1 jmcneill aprint_error(": couldn't enable module\n"); 178 1.1 jmcneill return; 179 1.1 jmcneill } 180 1.1 jmcneill 181 1.1 jmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0 || size <= conf->regoff) { 182 1.1 jmcneill aprint_error(": couldn't get registers\n"); 183 1.1 jmcneill return; 184 1.1 jmcneill } 185 1.1 jmcneill addr += conf->regoff; 186 1.1 jmcneill size -= conf->regoff; 187 1.1 jmcneill 188 1.1 jmcneill sc->sc.sc_dmat = faa->faa_dmat; 189 1.1 jmcneill sc->sc.sc_dev = self; 190 1.1 jmcneill sc->sc_phandle = phandle; 191 1.1 jmcneill sc->sc_addr = addr; 192 1.1 jmcneill sc->sc_bst = faa->faa_bst; 193 1.1 jmcneill 194 1.1 jmcneill /* XXX use fdtbus_dma API */ 195 1.1 jmcneill int len; 196 1.1 jmcneill const u_int *dmas = fdtbus_get_prop(phandle, "dmas", &len); 197 1.1 jmcneill switch (len) { 198 1.1 jmcneill case 24: 199 1.1 jmcneill sc->sc_edma_chan[EDMA_CHAN_TX] = be32toh(dmas[1]); 200 1.1 jmcneill sc->sc_edma_chan[EDMA_CHAN_RX] = be32toh(dmas[4]); 201 1.1 jmcneill break; 202 1.1 jmcneill case 32: 203 1.1 jmcneill sc->sc_edma_chan[EDMA_CHAN_TX] = be32toh(dmas[1]); 204 1.1 jmcneill sc->sc_edma_chan[EDMA_CHAN_RX] = be32toh(dmas[5]); 205 1.1 jmcneill break; 206 1.1 jmcneill default: 207 1.1 jmcneill sc->sc_edma_chan[EDMA_CHAN_TX] = -1; 208 1.1 jmcneill sc->sc_edma_chan[EDMA_CHAN_RX] = -1; 209 1.1 jmcneill break; 210 1.1 jmcneill } 211 1.1 jmcneill 212 1.1 jmcneill if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 213 1.1 jmcneill aprint_error(": couldn't map registers\n"); 214 1.1 jmcneill return; 215 1.1 jmcneill } 216 1.1 jmcneill 217 1.1 jmcneill if (of_getprop_uint32(phandle, "bus-width", &bus_width) != 0) 218 1.1 jmcneill bus_width = 4; 219 1.1 jmcneill 220 1.1 jmcneill sc->sc.sc_flags |= conf->flags; 221 1.1 jmcneill sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS; 222 1.1 jmcneill sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON; 223 1.1 jmcneill sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC; 224 1.1 jmcneill if (bus_width == 8) 225 1.1 jmcneill sc->sc.sc_flags |= SDHC_FLAG_8BIT_MODE; 226 1.1 jmcneill if (of_hasprop(phandle, "ti,needs-special-reset")) 227 1.1 jmcneill sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET; 228 1.4 jmcneill if (!of_hasprop(phandle, "ti,needs-special-hs-handling")) 229 1.1 jmcneill sc->sc.sc_flags |= SDHC_FLAG_NO_HS_BIT; 230 1.1 jmcneill if (of_hasprop(phandle, "ti,dual-volt")) 231 1.1 jmcneill sc->sc.sc_caps = SDHC_VOLTAGE_SUPP_3_0V; 232 1.1 jmcneill 233 1.1 jmcneill sc->sc.sc_host = sc->sc_hosts; 234 1.1 jmcneill sc->sc.sc_clkbase = 96000; /* 96MHZ */ 235 1.1 jmcneill sc->sc.sc_clkmsk = 0x0000ffc0; 236 1.1 jmcneill sc->sc.sc_vendor_rod = ti_sdhc_rod; 237 1.1 jmcneill sc->sc.sc_vendor_write_protect = ti_sdhc_write_protect; 238 1.1 jmcneill sc->sc.sc_vendor_card_detect = ti_sdhc_card_detect; 239 1.1 jmcneill sc->sc.sc_vendor_bus_width = ti_sdhc_bus_width; 240 1.1 jmcneill 241 1.1 jmcneill if (bus_space_subregion(sc->sc_bst, sc->sc_bsh, 0x100, 0x100, 242 1.1 jmcneill &sc->sc_sdhc_bsh) != 0) { 243 1.1 jmcneill aprint_error(": couldn't map subregion\n"); 244 1.1 jmcneill return; 245 1.1 jmcneill } 246 1.1 jmcneill 247 1.1 jmcneill aprint_naive("\n"); 248 1.1 jmcneill aprint_normal(": MMCHS\n"); 249 1.1 jmcneill 250 1.1 jmcneill ti_sdhc_init(sc, conf); 251 1.1 jmcneill } 252 1.1 jmcneill 253 1.1 jmcneill static void 254 1.1 jmcneill ti_sdhc_init(struct ti_sdhc_softc *sc, const struct ti_sdhc_config *conf) 255 1.1 jmcneill { 256 1.1 jmcneill device_t dev = sc->sc.sc_dev; 257 1.1 jmcneill uint32_t clkd, stat; 258 1.1 jmcneill int error, timo, clksft, n; 259 1.1 jmcneill char intrstr[128]; 260 1.1 jmcneill 261 1.1 jmcneill const int tx_chan = sc->sc_edma_chan[EDMA_CHAN_TX]; 262 1.1 jmcneill const int rx_chan = sc->sc_edma_chan[EDMA_CHAN_RX]; 263 1.1 jmcneill 264 1.1 jmcneill if (tx_chan != -1 && rx_chan != -1) { 265 1.1 jmcneill aprint_normal_dev(dev, 266 1.1 jmcneill "EDMA tx channel %d, rx channel %d\n", 267 1.1 jmcneill tx_chan, rx_chan); 268 1.1 jmcneill 269 1.1 jmcneill if (ti_sdhc_edma_init(sc, tx_chan, rx_chan) != 0) { 270 1.1 jmcneill aprint_error_dev(dev, "EDMA disabled\n"); 271 1.1 jmcneill goto no_dma; 272 1.1 jmcneill } 273 1.1 jmcneill 274 1.1 jmcneill cv_init(&sc->sc_edma_cv, "sdhcedma"); 275 1.1 jmcneill sc->sc_edma_fifo = sc->sc_addr + 0x100 + SDHC_DATA; 276 1.1 jmcneill sc->sc.sc_flags |= SDHC_FLAG_USE_DMA; 277 1.1 jmcneill sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA; 278 1.1 jmcneill sc->sc.sc_flags |= SDHC_FLAG_EXTDMA_DMAEN; 279 1.1 jmcneill sc->sc.sc_vendor_transfer_data_dma = ti_sdhc_edma_xfer_data; 280 1.1 jmcneill } 281 1.1 jmcneill no_dma: 282 1.1 jmcneill 283 1.1 jmcneill /* XXXXXX: Turn-on regulator via I2C. */ 284 1.1 jmcneill /* XXXXXX: And enable ICLOCK/FCLOCK. */ 285 1.1 jmcneill 286 1.1 jmcneill SDHC_WRITE(sc, SDHC_CAPABILITIES, 287 1.1 jmcneill SDHC_READ(sc, SDHC_CAPABILITIES) | SDHC_VOLTAGE_SUPP_1_8V); 288 1.1 jmcneill if (sc->sc.sc_caps & SDHC_VOLTAGE_SUPP_3_0V) 289 1.1 jmcneill SDHC_WRITE(sc, SDHC_CAPABILITIES, 290 1.1 jmcneill SDHC_READ(sc, SDHC_CAPABILITIES) | SDHC_VOLTAGE_SUPP_3_0V); 291 1.1 jmcneill 292 1.1 jmcneill /* MMCHS Soft reset */ 293 1.1 jmcneill bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG, 294 1.1 jmcneill SYSCONFIG_SOFTRESET); 295 1.1 jmcneill timo = 3000000; /* XXXX 3 sec. */ 296 1.1 jmcneill while (timo--) { 297 1.1 jmcneill if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSSTATUS) & 298 1.1 jmcneill SYSSTATUS_RESETDONE) 299 1.1 jmcneill break; 300 1.1 jmcneill delay(1); 301 1.1 jmcneill } 302 1.1 jmcneill if (timo == 0) 303 1.1 jmcneill aprint_error_dev(dev, "Soft reset timeout\n"); 304 1.1 jmcneill bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG, 305 1.1 jmcneill SYSCONFIG_ENAWAKEUP | 306 1.2 jmcneill #if notyet 307 1.1 jmcneill SYSCONFIG_AUTOIDLE | 308 1.1 jmcneill SYSCONFIG_SIDLEMODE_AUTO | 309 1.2 jmcneill #else 310 1.2 jmcneill SYSCONFIG_SIDLEMODE_IGNORE | 311 1.2 jmcneill #endif 312 1.1 jmcneill SYSCONFIG_CLOCKACTIVITY_FCLK | 313 1.1 jmcneill SYSCONFIG_CLOCKACTIVITY_ICLK); 314 1.1 jmcneill 315 1.1 jmcneill if (!fdtbus_intr_str(sc->sc_phandle, 0, intrstr, sizeof(intrstr))) { 316 1.1 jmcneill aprint_error_dev(dev, "couldn't decode interrupt\n"); 317 1.1 jmcneill return; 318 1.1 jmcneill } 319 1.6 jmcneill sc->sc_ih = fdtbus_intr_establish_xname(sc->sc_phandle, 0, IPL_VM, 320 1.6 jmcneill 0, sdhc_intr, &sc->sc, device_xname(dev)); 321 1.1 jmcneill if (sc->sc_ih == NULL) { 322 1.1 jmcneill aprint_error_dev(dev, "couldn't establish interrupt\n"); 323 1.1 jmcneill return; 324 1.1 jmcneill } 325 1.1 jmcneill aprint_normal_dev(dev, "interrupting on %s\n", intrstr); 326 1.1 jmcneill 327 1.1 jmcneill error = sdhc_host_found(&sc->sc, sc->sc_bst, sc->sc_sdhc_bsh, 0x100); 328 1.1 jmcneill if (error != 0) { 329 1.1 jmcneill aprint_error_dev(dev, "couldn't initialize host, error=%d\n", 330 1.1 jmcneill error); 331 1.1 jmcneill fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih); 332 1.1 jmcneill return; 333 1.1 jmcneill } 334 1.1 jmcneill 335 1.1 jmcneill clksft = ffs(sc->sc.sc_clkmsk) - 1; 336 1.1 jmcneill 337 1.1 jmcneill /* Set SDVS 1.8v and DTW 1bit mode */ 338 1.1 jmcneill SDHC_WRITE(sc, SDHC_HOST_CTL, 339 1.1 jmcneill SDHC_VOLTAGE_1_8V << (SDHC_VOLTAGE_SHIFT + 8)); 340 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 341 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_INTCLK_ENABLE | 342 1.1 jmcneill SDHC_SDCLK_ENABLE); 343 1.1 jmcneill SDHC_WRITE(sc, SDHC_HOST_CTL, 344 1.1 jmcneill SDHC_READ(sc, SDHC_HOST_CTL) | SDHC_BUS_POWER << 8); 345 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 346 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft); 347 1.1 jmcneill 348 1.1 jmcneill /* 349 1.1 jmcneill * 22.6.1.3.1.5 MMCHS Controller INIT Procedure Start 350 1.1 jmcneill * from 'OMAP35x Applications Processor Technical Reference Manual'. 351 1.1 jmcneill * 352 1.1 jmcneill * During the INIT procedure, the MMCHS controller generates 80 clock 353 1.1 jmcneill * periods. In order to keep the 1ms gap, the MMCHS controller should 354 1.1 jmcneill * be configured to generate a clock whose frequency is smaller or 355 1.1 jmcneill * equal to 80 KHz. 356 1.1 jmcneill */ 357 1.1 jmcneill 358 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 359 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE); 360 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 361 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk); 362 1.1 jmcneill clkd = CLKD(80); 363 1.1 jmcneill n = 1; 364 1.1 jmcneill while (clkd & ~(sc->sc.sc_clkmsk >> clksft)) { 365 1.1 jmcneill clkd >>= 1; 366 1.1 jmcneill n <<= 1; 367 1.1 jmcneill } 368 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 369 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) | (clkd << clksft)); 370 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 371 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE); 372 1.1 jmcneill 373 1.1 jmcneill bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON, 374 1.1 jmcneill bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_INIT); 375 1.1 jmcneill SDHC_WRITE(sc, SDHC_TRANSFER_MODE, 0x00000000); 376 1.1 jmcneill delay(1000); 377 1.1 jmcneill stat = SDHC_READ(sc, SDHC_NINTR_STATUS); 378 1.1 jmcneill SDHC_WRITE(sc, SDHC_NINTR_STATUS, stat | SDHC_COMMAND_COMPLETE); 379 1.1 jmcneill bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON, 380 1.1 jmcneill bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) & ~CON_INIT); 381 1.1 jmcneill SDHC_WRITE(sc, SDHC_NINTR_STATUS, 0xffffffff); 382 1.1 jmcneill 383 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 384 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE); 385 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 386 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk); 387 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 388 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft); 389 1.1 jmcneill timo = 3000000; /* XXXX 3 sec. */ 390 1.1 jmcneill while (--timo) { 391 1.1 jmcneill if (SDHC_READ(sc, SDHC_CLOCK_CTL) & SDHC_INTCLK_STABLE) 392 1.1 jmcneill break; 393 1.1 jmcneill delay(1); 394 1.1 jmcneill } 395 1.1 jmcneill if (timo == 0) 396 1.1 jmcneill aprint_error_dev(dev, "ICS timeout\n"); 397 1.1 jmcneill SDHC_WRITE(sc, SDHC_CLOCK_CTL, 398 1.1 jmcneill SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE); 399 1.1 jmcneill 400 1.12 jmcneill #if notyet 401 1.12 jmcneill if (sc->sc_use_adma2) { 402 1.1 jmcneill bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON, 403 1.1 jmcneill bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | 404 1.1 jmcneill CON_MNS); 405 1.12 jmcneill } 406 1.12 jmcneill #endif 407 1.1 jmcneill } 408 1.1 jmcneill 409 1.1 jmcneill static int 410 1.1 jmcneill ti_sdhc_rod(struct sdhc_softc *sc, int on) 411 1.1 jmcneill { 412 1.1 jmcneill struct ti_sdhc_softc *hmsc = (struct ti_sdhc_softc *)sc; 413 1.1 jmcneill uint32_t con; 414 1.1 jmcneill 415 1.1 jmcneill con = bus_space_read_4(hmsc->sc_bst, hmsc->sc_bsh, MMCHS_CON); 416 1.1 jmcneill if (on) 417 1.1 jmcneill con |= CON_OD; 418 1.1 jmcneill else 419 1.1 jmcneill con &= ~CON_OD; 420 1.1 jmcneill bus_space_write_4(hmsc->sc_bst, hmsc->sc_bsh, MMCHS_CON, con); 421 1.1 jmcneill 422 1.1 jmcneill return 0; 423 1.1 jmcneill } 424 1.1 jmcneill 425 1.1 jmcneill static int 426 1.1 jmcneill ti_sdhc_write_protect(struct sdhc_softc *sc) 427 1.1 jmcneill { 428 1.1 jmcneill 429 1.1 jmcneill /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */ 430 1.1 jmcneill return 0; /* XXXXXXX */ 431 1.1 jmcneill } 432 1.1 jmcneill 433 1.1 jmcneill static int 434 1.1 jmcneill ti_sdhc_card_detect(struct sdhc_softc *sc) 435 1.1 jmcneill { 436 1.1 jmcneill 437 1.1 jmcneill /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */ 438 1.1 jmcneill return 1; /* XXXXXXXX */ 439 1.1 jmcneill } 440 1.1 jmcneill 441 1.1 jmcneill static int 442 1.1 jmcneill ti_sdhc_bus_width(struct sdhc_softc *sc, int width) 443 1.1 jmcneill { 444 1.1 jmcneill struct ti_sdhc_softc *hmsc = (struct ti_sdhc_softc *)sc; 445 1.5 jmcneill uint32_t con, hctl; 446 1.1 jmcneill 447 1.1 jmcneill con = bus_space_read_4(hmsc->sc_bst, hmsc->sc_bsh, MMCHS_CON); 448 1.5 jmcneill hctl = SDHC_READ(hmsc, SDHC_HOST_CTL); 449 1.1 jmcneill if (width == 8) { 450 1.1 jmcneill con |= CON_DW8; 451 1.5 jmcneill } else if (width == 4) { 452 1.5 jmcneill con &= ~CON_DW8; 453 1.5 jmcneill hctl |= SDHC_4BIT_MODE; 454 1.1 jmcneill } else { 455 1.1 jmcneill con &= ~CON_DW8; 456 1.5 jmcneill hctl &= ~SDHC_4BIT_MODE; 457 1.1 jmcneill } 458 1.1 jmcneill bus_space_write_4(hmsc->sc_bst, hmsc->sc_bsh, MMCHS_CON, con); 459 1.5 jmcneill SDHC_WRITE(hmsc, SDHC_HOST_CTL, hctl); 460 1.1 jmcneill 461 1.1 jmcneill return 0; 462 1.1 jmcneill } 463 1.1 jmcneill 464 1.1 jmcneill static int 465 1.1 jmcneill ti_sdhc_edma_init(struct ti_sdhc_softc *sc, u_int tx_chan, u_int rx_chan) 466 1.1 jmcneill { 467 1.1 jmcneill int i, error, rseg; 468 1.1 jmcneill 469 1.1 jmcneill /* Request tx and rx DMA channels */ 470 1.1 jmcneill sc->sc_edma_tx = edma_channel_alloc(EDMA_TYPE_DMA, tx_chan, 471 1.1 jmcneill ti_sdhc_edma_done, sc); 472 1.1 jmcneill KASSERT(sc->sc_edma_tx != NULL); 473 1.1 jmcneill sc->sc_edma_rx = edma_channel_alloc(EDMA_TYPE_DMA, rx_chan, 474 1.1 jmcneill ti_sdhc_edma_done, sc); 475 1.1 jmcneill KASSERT(sc->sc_edma_rx != NULL); 476 1.1 jmcneill 477 1.1 jmcneill /* Allocate some PaRAM pages */ 478 1.1 jmcneill for (i = 0; i < __arraycount(sc->sc_edma_param_tx); i++) { 479 1.1 jmcneill sc->sc_edma_param_tx[i] = edma_param_alloc(sc->sc_edma_tx); 480 1.1 jmcneill KASSERT(sc->sc_edma_param_tx[i] != 0xffff); 481 1.1 jmcneill } 482 1.1 jmcneill for (i = 0; i < __arraycount(sc->sc_edma_param_rx); i++) { 483 1.1 jmcneill sc->sc_edma_param_rx[i] = edma_param_alloc(sc->sc_edma_rx); 484 1.1 jmcneill KASSERT(sc->sc_edma_param_rx[i] != 0xffff); 485 1.1 jmcneill } 486 1.1 jmcneill 487 1.1 jmcneill /* Setup bounce buffer */ 488 1.1 jmcneill error = bus_dmamem_alloc(sc->sc.sc_dmat, MAXPHYS, 32, MAXPHYS, 489 1.1 jmcneill sc->sc_edma_segs, 1, &rseg, BUS_DMA_WAITOK); 490 1.1 jmcneill if (error) { 491 1.1 jmcneill aprint_error_dev(sc->sc.sc_dev, 492 1.1 jmcneill "couldn't allocate dmamem: %d\n", error); 493 1.1 jmcneill return error; 494 1.1 jmcneill } 495 1.1 jmcneill KASSERT(rseg == 1); 496 1.1 jmcneill error = bus_dmamem_map(sc->sc.sc_dmat, sc->sc_edma_segs, rseg, MAXPHYS, 497 1.1 jmcneill &sc->sc_edma_bbuf, BUS_DMA_WAITOK); 498 1.1 jmcneill if (error) { 499 1.1 jmcneill aprint_error_dev(sc->sc.sc_dev, "couldn't map dmamem: %d\n", 500 1.1 jmcneill error); 501 1.1 jmcneill return error; 502 1.1 jmcneill } 503 1.1 jmcneill error = bus_dmamap_create(sc->sc.sc_dmat, MAXPHYS, 1, MAXPHYS, 0, 504 1.1 jmcneill BUS_DMA_WAITOK, &sc->sc_edma_dmamap); 505 1.1 jmcneill if (error) { 506 1.1 jmcneill aprint_error_dev(sc->sc.sc_dev, "couldn't create dmamap: %d\n", 507 1.1 jmcneill error); 508 1.1 jmcneill return error; 509 1.1 jmcneill } 510 1.5 jmcneill error = bus_dmamap_load(sc->sc.sc_dmat, sc->sc_edma_dmamap, 511 1.5 jmcneill sc->sc_edma_bbuf, MAXPHYS, NULL, BUS_DMA_WAITOK); 512 1.5 jmcneill if (error) { 513 1.5 jmcneill device_printf(sc->sc.sc_dev, "couldn't load dmamap: %d\n", 514 1.5 jmcneill error); 515 1.5 jmcneill return error; 516 1.5 jmcneill } 517 1.1 jmcneill 518 1.1 jmcneill return error; 519 1.1 jmcneill } 520 1.1 jmcneill 521 1.1 jmcneill static int 522 1.1 jmcneill ti_sdhc_edma_xfer_data(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd) 523 1.1 jmcneill { 524 1.1 jmcneill struct ti_sdhc_softc *sc = device_private(sdhc_sc->sc_dev); 525 1.1 jmcneill const bus_dmamap_t map = cmd->c_dmamap; 526 1.1 jmcneill bool bounce; 527 1.5 jmcneill int error; 528 1.1 jmcneill 529 1.5 jmcneill #if notyet 530 1.5 jmcneill bounce = false; 531 1.5 jmcneill for (int seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) { 532 1.5 jmcneill if ((cmd->c_dmamap->dm_segs[seg].ds_addr & 0x1f) != 0 || 533 1.5 jmcneill (cmd->c_dmamap->dm_segs[seg].ds_len & 3) != 0) { 534 1.1 jmcneill bounce = true; 535 1.1 jmcneill break; 536 1.1 jmcneill } 537 1.1 jmcneill } 538 1.5 jmcneill #else 539 1.5 jmcneill bounce = true; 540 1.5 jmcneill #endif 541 1.1 jmcneill 542 1.1 jmcneill if (bounce) { 543 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 544 1.1 jmcneill bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0, 545 1.1 jmcneill MAXPHYS, BUS_DMASYNC_PREREAD); 546 1.1 jmcneill } else { 547 1.1 jmcneill memcpy(sc->sc_edma_bbuf, cmd->c_data, cmd->c_datalen); 548 1.1 jmcneill bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0, 549 1.1 jmcneill MAXPHYS, BUS_DMASYNC_PREWRITE); 550 1.1 jmcneill } 551 1.1 jmcneill 552 1.1 jmcneill cmd->c_dmamap = sc->sc_edma_dmamap; 553 1.1 jmcneill } 554 1.1 jmcneill 555 1.1 jmcneill error = ti_sdhc_edma_transfer(sdhc_sc, cmd); 556 1.1 jmcneill 557 1.1 jmcneill if (bounce) { 558 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 559 1.1 jmcneill bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0, 560 1.1 jmcneill MAXPHYS, BUS_DMASYNC_POSTREAD); 561 1.1 jmcneill } else { 562 1.1 jmcneill bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0, 563 1.1 jmcneill MAXPHYS, BUS_DMASYNC_POSTWRITE); 564 1.1 jmcneill } 565 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ) && error == 0) { 566 1.1 jmcneill memcpy(cmd->c_data, sc->sc_edma_bbuf, cmd->c_datalen); 567 1.1 jmcneill } 568 1.1 jmcneill 569 1.1 jmcneill cmd->c_dmamap = map; 570 1.1 jmcneill } 571 1.1 jmcneill 572 1.1 jmcneill return error; 573 1.1 jmcneill } 574 1.1 jmcneill 575 1.1 jmcneill static int 576 1.1 jmcneill ti_sdhc_edma_transfer(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd) 577 1.1 jmcneill { 578 1.1 jmcneill struct ti_sdhc_softc *sc = device_private(sdhc_sc->sc_dev); 579 1.1 jmcneill kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]); 580 1.1 jmcneill struct edma_channel *edma; 581 1.1 jmcneill uint16_t *edma_param; 582 1.1 jmcneill struct edma_param ep; 583 1.1 jmcneill size_t seg; 584 1.1 jmcneill int error, resid = cmd->c_datalen; 585 1.1 jmcneill int blksize = MIN(cmd->c_datalen, cmd->c_blklen); 586 1.1 jmcneill 587 1.1 jmcneill KASSERT(mutex_owned(plock)); 588 1.1 jmcneill 589 1.1 jmcneill edma = ISSET(cmd->c_flags, SCF_CMD_READ) ? 590 1.1 jmcneill sc->sc_edma_rx : sc->sc_edma_tx; 591 1.1 jmcneill edma_param = ISSET(cmd->c_flags, SCF_CMD_READ) ? 592 1.1 jmcneill sc->sc_edma_param_rx : sc->sc_edma_param_tx; 593 1.1 jmcneill 594 1.1 jmcneill DPRINTF(1, (sc->sc.sc_dev, "edma xfer: nsegs=%d ch# %d\n", 595 1.1 jmcneill cmd->c_dmamap->dm_nsegs, edma_channel_index(edma))); 596 1.1 jmcneill 597 1.1 jmcneill if (cmd->c_dmamap->dm_nsegs > EDMA_MAX_PARAMS) { 598 1.1 jmcneill return ENOMEM; 599 1.1 jmcneill } 600 1.1 jmcneill 601 1.1 jmcneill for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) { 602 1.1 jmcneill KASSERT(resid > 0); 603 1.1 jmcneill const int xferlen = uimin(resid, 604 1.1 jmcneill cmd->c_dmamap->dm_segs[seg].ds_len); 605 1.1 jmcneill KASSERT(xferlen == cmd->c_dmamap->dm_segs[seg].ds_len || 606 1.1 jmcneill seg == cmd->c_dmamap->dm_nsegs - 1); 607 1.1 jmcneill resid -= xferlen; 608 1.1 jmcneill KASSERT((xferlen & 0x3) == 0); 609 1.1 jmcneill ep.ep_opt = __SHIFTIN(2, EDMA_PARAM_OPT_FWID) /* 32-bit */; 610 1.1 jmcneill ep.ep_opt |= __SHIFTIN(edma_channel_index(edma), 611 1.1 jmcneill EDMA_PARAM_OPT_TCC); 612 1.1 jmcneill if (seg == cmd->c_dmamap->dm_nsegs - 1) { 613 1.1 jmcneill ep.ep_opt |= EDMA_PARAM_OPT_TCINTEN; 614 1.1 jmcneill ep.ep_link = 0xffff; 615 1.1 jmcneill } else { 616 1.1 jmcneill ep.ep_link = EDMA_PARAM_BASE(edma_param[seg+1]); 617 1.1 jmcneill } 618 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 619 1.1 jmcneill ep.ep_opt |= EDMA_PARAM_OPT_SAM; 620 1.1 jmcneill ep.ep_src = sc->sc_edma_fifo; 621 1.1 jmcneill ep.ep_dst = cmd->c_dmamap->dm_segs[seg].ds_addr; 622 1.1 jmcneill } else { 623 1.1 jmcneill ep.ep_opt |= EDMA_PARAM_OPT_DAM; 624 1.1 jmcneill ep.ep_src = cmd->c_dmamap->dm_segs[seg].ds_addr; 625 1.1 jmcneill ep.ep_dst = sc->sc_edma_fifo; 626 1.1 jmcneill } 627 1.1 jmcneill 628 1.1 jmcneill KASSERT(xferlen <= 65536 * 4); 629 1.1 jmcneill 630 1.1 jmcneill /* 631 1.1 jmcneill * In constant addressing mode, the address must be aligned 632 1.1 jmcneill * to 256-bits. 633 1.1 jmcneill */ 634 1.1 jmcneill KASSERT((cmd->c_dmamap->dm_segs[seg].ds_addr & 0x1f) == 0); 635 1.1 jmcneill 636 1.1 jmcneill /* 637 1.1 jmcneill * For unknown reason, the A-DMA transfers never completes for 638 1.1 jmcneill * transfers larger than 64 butes. So use a AB transfer, 639 1.1 jmcneill * with a 64 bytes A len 640 1.1 jmcneill */ 641 1.1 jmcneill ep.ep_bcntrld = 0; /* not used for AB-synchronous mode */ 642 1.1 jmcneill ep.ep_opt |= EDMA_PARAM_OPT_SYNCDIM; 643 1.1 jmcneill ep.ep_acnt = uimin(xferlen, 64); 644 1.1 jmcneill ep.ep_bcnt = uimin(xferlen, blksize) / ep.ep_acnt; 645 1.1 jmcneill ep.ep_ccnt = xferlen / (ep.ep_acnt * ep.ep_bcnt); 646 1.1 jmcneill ep.ep_srcbidx = ep.ep_dstbidx = 0; 647 1.1 jmcneill ep.ep_srccidx = ep.ep_dstcidx = 0; 648 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 649 1.1 jmcneill ep.ep_dstbidx = ep.ep_acnt; 650 1.1 jmcneill ep.ep_dstcidx = ep.ep_acnt * ep.ep_bcnt; 651 1.1 jmcneill } else { 652 1.1 jmcneill ep.ep_srcbidx = ep.ep_acnt; 653 1.1 jmcneill ep.ep_srccidx = ep.ep_acnt * ep.ep_bcnt; 654 1.1 jmcneill } 655 1.1 jmcneill 656 1.1 jmcneill edma_set_param(edma, edma_param[seg], &ep); 657 1.1 jmcneill #ifdef TISDHC_DEBUG 658 1.1 jmcneill if (tisdhcdebug >= 1) { 659 1.1 jmcneill printf("target OPT: %08x\n", ep.ep_opt); 660 1.1 jmcneill edma_dump_param(edma, edma_param[seg]); 661 1.1 jmcneill } 662 1.1 jmcneill #endif 663 1.1 jmcneill } 664 1.1 jmcneill 665 1.1 jmcneill error = 0; 666 1.1 jmcneill sc->sc_edma_pending = true; 667 1.1 jmcneill edma_transfer_enable(edma, edma_param[0]); 668 1.1 jmcneill while (sc->sc_edma_pending) { 669 1.1 jmcneill error = cv_timedwait(&sc->sc_edma_cv, plock, hz*10); 670 1.1 jmcneill if (error == EWOULDBLOCK) { 671 1.1 jmcneill device_printf(sc->sc.sc_dev, "transfer timeout!\n"); 672 1.1 jmcneill edma_dump(edma); 673 1.1 jmcneill edma_dump_param(edma, edma_param[0]); 674 1.1 jmcneill edma_halt(edma); 675 1.1 jmcneill sc->sc_edma_pending = false; 676 1.1 jmcneill error = ETIMEDOUT; 677 1.1 jmcneill break; 678 1.1 jmcneill } 679 1.1 jmcneill } 680 1.1 jmcneill edma_halt(edma); 681 1.1 jmcneill 682 1.1 jmcneill return error; 683 1.1 jmcneill } 684 1.1 jmcneill 685 1.1 jmcneill static void 686 1.1 jmcneill ti_sdhc_edma_done(void *priv) 687 1.1 jmcneill { 688 1.1 jmcneill struct ti_sdhc_softc *sc = priv; 689 1.1 jmcneill kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]); 690 1.1 jmcneill 691 1.1 jmcneill mutex_enter(plock); 692 1.1 jmcneill KASSERT(sc->sc_edma_pending == true); 693 1.1 jmcneill sc->sc_edma_pending = false; 694 1.1 jmcneill cv_broadcast(&sc->sc_edma_cv); 695 1.1 jmcneill mutex_exit(plock); 696 1.1 jmcneill } 697