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