Home | History | Annotate | Line # | Download | only in amlogic
meson_sdhc.c revision 1.3
      1  1.3   thorpej /* $NetBSD: meson_sdhc.c,v 1.3 2021/01/27 03:10:18 thorpej Exp $ */
      2  1.1  jmcneill 
      3  1.1  jmcneill /*-
      4  1.1  jmcneill  * Copyright (c) 2015-2019 Jared McNeill <jmcneill (at) invisible.ca>
      5  1.1  jmcneill  * All rights reserved.
      6  1.1  jmcneill  *
      7  1.1  jmcneill  * Redistribution and use in source and binary forms, with or without
      8  1.1  jmcneill  * modification, are permitted provided that the following conditions
      9  1.1  jmcneill  * are met:
     10  1.1  jmcneill  * 1. Redistributions of source code must retain the above copyright
     11  1.1  jmcneill  *    notice, this list of conditions and the following disclaimer.
     12  1.1  jmcneill  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  jmcneill  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  jmcneill  *    documentation and/or other materials provided with the distribution.
     15  1.1  jmcneill  *
     16  1.1  jmcneill  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  1.1  jmcneill  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  1.1  jmcneill  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  1.1  jmcneill  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  1.1  jmcneill  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  1.1  jmcneill  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  1.1  jmcneill  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  1.1  jmcneill  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  1.1  jmcneill  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  1.1  jmcneill  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  1.1  jmcneill  * SUCH DAMAGE.
     27  1.1  jmcneill  */
     28  1.1  jmcneill 
     29  1.1  jmcneill #include <sys/cdefs.h>
     30  1.3   thorpej __KERNEL_RCSID(0, "$NetBSD: meson_sdhc.c,v 1.3 2021/01/27 03:10:18 thorpej Exp $");
     31  1.1  jmcneill 
     32  1.1  jmcneill #include <sys/param.h>
     33  1.1  jmcneill #include <sys/bus.h>
     34  1.1  jmcneill #include <sys/device.h>
     35  1.1  jmcneill #include <sys/intr.h>
     36  1.1  jmcneill #include <sys/systm.h>
     37  1.1  jmcneill #include <sys/kernel.h>
     38  1.1  jmcneill #include <sys/gpio.h>
     39  1.1  jmcneill 
     40  1.1  jmcneill #include <dev/sdmmc/sdmmcvar.h>
     41  1.1  jmcneill #include <dev/sdmmc/sdmmcchip.h>
     42  1.1  jmcneill #include <dev/sdmmc/sdmmc_ioreg.h>
     43  1.1  jmcneill 
     44  1.1  jmcneill #include <dev/fdt/fdtvar.h>
     45  1.1  jmcneill 
     46  1.1  jmcneill #include <arm/amlogic/meson_sdhcreg.h>
     47  1.1  jmcneill 
     48  1.1  jmcneill enum {
     49  1.1  jmcneill 	SDHC_PORT_A = 0,
     50  1.1  jmcneill 	SDHC_PORT_B = 1,
     51  1.1  jmcneill 	SDHC_PORT_C = 2
     52  1.1  jmcneill };
     53  1.1  jmcneill 
     54  1.1  jmcneill static int	meson_sdhc_match(device_t, cfdata_t, void *);
     55  1.1  jmcneill static void	meson_sdhc_attach(device_t, device_t, void *);
     56  1.1  jmcneill static void	meson_sdhc_attach_i(device_t);
     57  1.1  jmcneill 
     58  1.1  jmcneill static int	meson_sdhc_intr(void *);
     59  1.1  jmcneill 
     60  1.1  jmcneill struct meson_sdhc_softc {
     61  1.1  jmcneill 	device_t		sc_dev;
     62  1.1  jmcneill 	bus_space_tag_t		sc_bst;
     63  1.1  jmcneill 	bus_space_handle_t	sc_bsh;
     64  1.1  jmcneill 	bus_dma_tag_t		sc_dmat;
     65  1.1  jmcneill 	void			*sc_ih;
     66  1.1  jmcneill 
     67  1.1  jmcneill 	device_t		sc_sdmmc_dev;
     68  1.1  jmcneill 	kmutex_t		sc_intr_lock;
     69  1.1  jmcneill 	kcondvar_t		sc_intr_cv;
     70  1.1  jmcneill 
     71  1.1  jmcneill 	uint32_t		sc_intr_ista;
     72  1.1  jmcneill 
     73  1.1  jmcneill 	bus_dmamap_t		sc_dmamap;
     74  1.1  jmcneill 	bus_dma_segment_t	sc_segs[1];
     75  1.1  jmcneill 	void			*sc_bbuf;
     76  1.1  jmcneill 
     77  1.1  jmcneill 	u_int			sc_bus_freq;
     78  1.1  jmcneill 
     79  1.1  jmcneill 	struct fdtbus_gpio_pin	*sc_gpio_cd;
     80  1.1  jmcneill 	int			sc_gpio_cd_inverted;
     81  1.1  jmcneill 	struct fdtbus_gpio_pin	*sc_gpio_wp;
     82  1.1  jmcneill 	int			sc_gpio_wp_inverted;
     83  1.1  jmcneill 
     84  1.1  jmcneill 	struct fdtbus_regulator	*sc_reg_vmmc;
     85  1.1  jmcneill 	struct fdtbus_regulator	*sc_reg_vqmmc;
     86  1.1  jmcneill 
     87  1.1  jmcneill 	bool			sc_non_removable;
     88  1.1  jmcneill 	bool			sc_broken_cd;
     89  1.1  jmcneill 
     90  1.1  jmcneill 	int			sc_port;
     91  1.1  jmcneill 	int			sc_slot_phandle;
     92  1.1  jmcneill 	int			sc_signal_voltage;
     93  1.1  jmcneill };
     94  1.1  jmcneill 
     95  1.1  jmcneill CFATTACH_DECL_NEW(meson_sdhc, sizeof(struct meson_sdhc_softc),
     96  1.1  jmcneill 	meson_sdhc_match, meson_sdhc_attach, NULL, NULL);
     97  1.1  jmcneill 
     98  1.1  jmcneill static int	meson_sdhc_host_reset(sdmmc_chipset_handle_t);
     99  1.1  jmcneill static uint32_t	meson_sdhc_host_ocr(sdmmc_chipset_handle_t);
    100  1.1  jmcneill static int	meson_sdhc_host_maxblklen(sdmmc_chipset_handle_t);
    101  1.1  jmcneill static int	meson_sdhc_card_detect(sdmmc_chipset_handle_t);
    102  1.1  jmcneill static int	meson_sdhc_write_protect(sdmmc_chipset_handle_t);
    103  1.1  jmcneill static int	meson_sdhc_bus_power(sdmmc_chipset_handle_t, uint32_t);
    104  1.1  jmcneill static int	meson_sdhc_bus_clock(sdmmc_chipset_handle_t, int);
    105  1.1  jmcneill static int	meson_sdhc_bus_width(sdmmc_chipset_handle_t, int);
    106  1.1  jmcneill static int	meson_sdhc_bus_rod(sdmmc_chipset_handle_t, int);
    107  1.1  jmcneill static void	meson_sdhc_exec_command(sdmmc_chipset_handle_t,
    108  1.1  jmcneill 				     struct sdmmc_command *);
    109  1.1  jmcneill static void	meson_sdhc_card_enable_intr(sdmmc_chipset_handle_t, int);
    110  1.1  jmcneill static void	meson_sdhc_card_intr_ack(sdmmc_chipset_handle_t);
    111  1.1  jmcneill static int	meson_sdhc_signal_voltage(sdmmc_chipset_handle_t, int);
    112  1.1  jmcneill static int	meson_sdhc_execute_tuning(sdmmc_chipset_handle_t, int);
    113  1.1  jmcneill 
    114  1.1  jmcneill static int	meson_sdhc_default_rx_phase(struct meson_sdhc_softc *);
    115  1.1  jmcneill static int	meson_sdhc_set_clock(struct meson_sdhc_softc *, u_int);
    116  1.1  jmcneill static int	meson_sdhc_wait_idle(struct meson_sdhc_softc *);
    117  1.1  jmcneill static int	meson_sdhc_wait_ista(struct meson_sdhc_softc *, uint32_t, int);
    118  1.1  jmcneill 
    119  1.1  jmcneill static void	meson_sdhc_dmainit(struct meson_sdhc_softc *);
    120  1.1  jmcneill 
    121  1.1  jmcneill static struct sdmmc_chip_functions meson_sdhc_chip_functions = {
    122  1.1  jmcneill 	.host_reset = meson_sdhc_host_reset,
    123  1.1  jmcneill 	.host_ocr = meson_sdhc_host_ocr,
    124  1.1  jmcneill 	.host_maxblklen = meson_sdhc_host_maxblklen,
    125  1.1  jmcneill 	.card_detect = meson_sdhc_card_detect,
    126  1.1  jmcneill 	.write_protect = meson_sdhc_write_protect,
    127  1.1  jmcneill 	.bus_power = meson_sdhc_bus_power,
    128  1.1  jmcneill 	.bus_clock = meson_sdhc_bus_clock,
    129  1.1  jmcneill 	.bus_width = meson_sdhc_bus_width,
    130  1.1  jmcneill 	.bus_rod = meson_sdhc_bus_rod,
    131  1.1  jmcneill 	.exec_command = meson_sdhc_exec_command,
    132  1.1  jmcneill 	.card_enable_intr = meson_sdhc_card_enable_intr,
    133  1.1  jmcneill 	.card_intr_ack = meson_sdhc_card_intr_ack,
    134  1.1  jmcneill 	.signal_voltage = meson_sdhc_signal_voltage,
    135  1.1  jmcneill 	.execute_tuning = meson_sdhc_execute_tuning,
    136  1.1  jmcneill };
    137  1.1  jmcneill 
    138  1.1  jmcneill #define SDHC_WRITE(sc, reg, val) \
    139  1.1  jmcneill 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
    140  1.1  jmcneill #define SDHC_READ(sc, reg) \
    141  1.1  jmcneill 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
    142  1.1  jmcneill #define	SDHC_SET_CLEAR meson_sdhc_set_clear
    143  1.1  jmcneill 
    144  1.1  jmcneill static inline void
    145  1.1  jmcneill meson_sdhc_set_clear(struct meson_sdhc_softc *sc, bus_addr_t reg, uint32_t set, uint32_t clr)
    146  1.1  jmcneill {
    147  1.1  jmcneill 	const uint32_t old = SDHC_READ(sc, reg);
    148  1.1  jmcneill 	const uint32_t new = set | (old & ~clr);
    149  1.1  jmcneill 	if (old != new)
    150  1.1  jmcneill 		SDHC_WRITE(sc, reg, new);
    151  1.1  jmcneill }
    152  1.1  jmcneill 
    153  1.3   thorpej static const struct device_compatible_entry compat_data[] = {
    154  1.3   thorpej 	{ .compat = "amlogic,meson8b-sdhc" },
    155  1.3   thorpej 	DEVICE_COMPAT_EOL
    156  1.1  jmcneill };
    157  1.1  jmcneill 
    158  1.3   thorpej static const struct device_compatible_entry slot_compat_data[] = {
    159  1.3   thorpej 	{ .compat = "mmc-slot" },
    160  1.3   thorpej 	DEVICE_COMPAT_EOL
    161  1.1  jmcneill };
    162  1.1  jmcneill 
    163  1.1  jmcneill static int
    164  1.1  jmcneill meson_sdhc_match(device_t parent, cfdata_t cf, void *aux)
    165  1.1  jmcneill {
    166  1.1  jmcneill 	struct fdt_attach_args * const faa = aux;
    167  1.1  jmcneill 
    168  1.3   thorpej 	return of_compatible_match(faa->faa_phandle, compat_data);
    169  1.1  jmcneill }
    170  1.1  jmcneill 
    171  1.1  jmcneill static void
    172  1.1  jmcneill meson_sdhc_attach(device_t parent, device_t self, void *aux)
    173  1.1  jmcneill {
    174  1.1  jmcneill 	struct meson_sdhc_softc * const sc = device_private(self);
    175  1.1  jmcneill 	struct fdt_attach_args * const faa = aux;
    176  1.1  jmcneill 	const int phandle = faa->faa_phandle;
    177  1.1  jmcneill 	char intrstr[128];
    178  1.1  jmcneill 	struct clk *clk_clkin, *clk_core;
    179  1.1  jmcneill 	bus_addr_t addr, port;
    180  1.1  jmcneill 	bus_size_t size;
    181  1.1  jmcneill 	int child;
    182  1.1  jmcneill 
    183  1.1  jmcneill 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
    184  1.1  jmcneill 		aprint_error(": couldn't get registers\n");
    185  1.1  jmcneill 		return;
    186  1.1  jmcneill 	}
    187  1.1  jmcneill 
    188  1.1  jmcneill 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
    189  1.1  jmcneill 		aprint_error(": failed to decode interrupt\n");
    190  1.1  jmcneill 		return;
    191  1.1  jmcneill 	}
    192  1.1  jmcneill 
    193  1.1  jmcneill 	clk_core = fdtbus_clock_get(phandle, "core");
    194  1.1  jmcneill 	if (clk_core == NULL || clk_enable(clk_core) != 0) {
    195  1.1  jmcneill 		aprint_error(": failed to enable core clock\n");
    196  1.1  jmcneill 		return;
    197  1.1  jmcneill 	}
    198  1.1  jmcneill 
    199  1.1  jmcneill 	clk_clkin = fdtbus_clock_get(phandle, "clkin");
    200  1.1  jmcneill 	if (clk_clkin == NULL || clk_enable(clk_clkin) != 0) {
    201  1.1  jmcneill 		aprint_error(": failed to get clkin clock\n");
    202  1.1  jmcneill 		return;
    203  1.1  jmcneill 	}
    204  1.1  jmcneill 
    205  1.1  jmcneill 	sc->sc_dev = self;
    206  1.1  jmcneill 	sc->sc_bst = faa->faa_bst;
    207  1.1  jmcneill 	sc->sc_dmat = faa->faa_dmat;
    208  1.1  jmcneill 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
    209  1.1  jmcneill 		aprint_error(": failed to map registers\n");
    210  1.1  jmcneill 		return;
    211  1.1  jmcneill 	}
    212  1.1  jmcneill 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
    213  1.1  jmcneill 	cv_init(&sc->sc_intr_cv, "sdhcintr");
    214  1.1  jmcneill 	sc->sc_signal_voltage = SDMMC_SIGNAL_VOLTAGE_330;
    215  1.1  jmcneill 
    216  1.1  jmcneill 	sc->sc_port = -1;
    217  1.1  jmcneill 	for (child = OF_child(phandle); child; child = OF_peer(child))
    218  1.3   thorpej 		if (of_compatible_match(child, slot_compat_data)) {
    219  1.1  jmcneill 			if (fdtbus_get_reg(child, 0, &port, NULL) == 0) {
    220  1.1  jmcneill 				sc->sc_slot_phandle = child;
    221  1.1  jmcneill 				sc->sc_port = port;
    222  1.1  jmcneill 			}
    223  1.1  jmcneill 			break;
    224  1.1  jmcneill 		}
    225  1.1  jmcneill 	if (sc->sc_port == -1) {
    226  1.1  jmcneill 		aprint_error(": couldn't get mmc slot\n");
    227  1.1  jmcneill 		return;
    228  1.1  jmcneill 	}
    229  1.1  jmcneill 
    230  1.1  jmcneill 	aprint_naive("\n");
    231  1.1  jmcneill 	aprint_normal(": SDHC controller (port %c)\n", sc->sc_port + 'A');
    232  1.1  jmcneill 
    233  1.1  jmcneill 	sc->sc_reg_vmmc = fdtbus_regulator_acquire(sc->sc_slot_phandle, "vmmc-supply");
    234  1.1  jmcneill 	sc->sc_reg_vqmmc = fdtbus_regulator_acquire(sc->sc_slot_phandle, "vqmmc-supply");
    235  1.1  jmcneill 
    236  1.1  jmcneill 	sc->sc_gpio_cd = fdtbus_gpio_acquire(sc->sc_slot_phandle, "cd-gpios",
    237  1.1  jmcneill 	    GPIO_PIN_INPUT);
    238  1.1  jmcneill 	sc->sc_gpio_wp = fdtbus_gpio_acquire(sc->sc_slot_phandle, "wp-gpios",
    239  1.1  jmcneill 	    GPIO_PIN_INPUT);
    240  1.1  jmcneill 
    241  1.1  jmcneill 	sc->sc_gpio_cd_inverted = of_hasprop(sc->sc_slot_phandle, "cd-inverted");
    242  1.1  jmcneill 	sc->sc_gpio_wp_inverted = of_hasprop(sc->sc_slot_phandle, "wp-inverted");
    243  1.1  jmcneill 
    244  1.1  jmcneill 	sc->sc_non_removable = of_hasprop(sc->sc_slot_phandle, "non-removable");
    245  1.1  jmcneill 	sc->sc_broken_cd = of_hasprop(sc->sc_slot_phandle, "broken-cd");
    246  1.1  jmcneill 
    247  1.2       ryo 	sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_BIO, 0,
    248  1.2       ryo 	    meson_sdhc_intr, sc, device_xname(self));
    249  1.1  jmcneill 	if (sc->sc_ih == NULL) {
    250  1.1  jmcneill 		aprint_error_dev(self, "couldn't establish interrupt on %s\n",
    251  1.1  jmcneill 		    intrstr);
    252  1.1  jmcneill 		return;
    253  1.1  jmcneill 	}
    254  1.1  jmcneill 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
    255  1.1  jmcneill 
    256  1.1  jmcneill 	sc->sc_bus_freq = clk_get_rate(clk_clkin);
    257  1.1  jmcneill 
    258  1.1  jmcneill 	aprint_normal_dev(self, "core %u Hz, clkin %u Hz\n", clk_get_rate(clk_core), clk_get_rate(clk_clkin));
    259  1.1  jmcneill 
    260  1.1  jmcneill 	meson_sdhc_dmainit(sc);
    261  1.1  jmcneill 
    262  1.1  jmcneill 	config_interrupts(self, meson_sdhc_attach_i);
    263  1.1  jmcneill }
    264  1.1  jmcneill 
    265  1.1  jmcneill static void
    266  1.1  jmcneill meson_sdhc_attach_i(device_t self)
    267  1.1  jmcneill {
    268  1.1  jmcneill 	struct meson_sdhc_softc *sc = device_private(self);
    269  1.1  jmcneill 	struct sdmmcbus_attach_args saa;
    270  1.1  jmcneill 	u_int pll_freq;
    271  1.1  jmcneill 
    272  1.1  jmcneill 	pll_freq = sc->sc_bus_freq / 1000;
    273  1.1  jmcneill 
    274  1.1  jmcneill 	meson_sdhc_host_reset(sc);
    275  1.1  jmcneill 	meson_sdhc_bus_width(sc, 1);
    276  1.1  jmcneill 
    277  1.1  jmcneill 	memset(&saa, 0, sizeof(saa));
    278  1.1  jmcneill 	saa.saa_busname = "sdmmc";
    279  1.1  jmcneill 	saa.saa_sct = &meson_sdhc_chip_functions;
    280  1.1  jmcneill 	saa.saa_dmat = sc->sc_dmat;
    281  1.1  jmcneill 	saa.saa_sch = sc;
    282  1.1  jmcneill 	saa.saa_clkmin = 400;
    283  1.1  jmcneill 	saa.saa_clkmax = pll_freq;
    284  1.1  jmcneill 	/* Do not advertise DMA capabilities, we handle DMA ourselves */
    285  1.1  jmcneill 	saa.saa_caps = SMC_CAPS_4BIT_MODE|
    286  1.1  jmcneill 		       SMC_CAPS_SD_HIGHSPEED|
    287  1.1  jmcneill 		       SMC_CAPS_MMC_HIGHSPEED|
    288  1.1  jmcneill 		       SMC_CAPS_UHS_SDR50|
    289  1.1  jmcneill 		       SMC_CAPS_UHS_SDR104|
    290  1.1  jmcneill 		       SMC_CAPS_AUTO_STOP;
    291  1.1  jmcneill 
    292  1.1  jmcneill 	if (sc->sc_port == SDHC_PORT_C) {
    293  1.1  jmcneill 		saa.saa_caps |= SMC_CAPS_MMC_HS200;
    294  1.1  jmcneill 		saa.saa_caps |= SMC_CAPS_8BIT_MODE;
    295  1.1  jmcneill 	}
    296  1.1  jmcneill 
    297  1.1  jmcneill 	sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
    298  1.1  jmcneill }
    299  1.1  jmcneill 
    300  1.1  jmcneill static int
    301  1.1  jmcneill meson_sdhc_intr(void *priv)
    302  1.1  jmcneill {
    303  1.1  jmcneill 	struct meson_sdhc_softc *sc = priv;
    304  1.1  jmcneill 	uint32_t ista;
    305  1.1  jmcneill 
    306  1.1  jmcneill 	mutex_enter(&sc->sc_intr_lock);
    307  1.1  jmcneill 	ista = SDHC_READ(sc, SD_ISTA_REG);
    308  1.1  jmcneill 
    309  1.1  jmcneill 	if (!ista) {
    310  1.1  jmcneill 		mutex_exit(&sc->sc_intr_lock);
    311  1.1  jmcneill 		return 0;
    312  1.1  jmcneill 	}
    313  1.1  jmcneill 
    314  1.1  jmcneill 	SDHC_WRITE(sc, SD_ISTA_REG, ista);
    315  1.1  jmcneill 
    316  1.1  jmcneill 	sc->sc_intr_ista |= ista;
    317  1.1  jmcneill 	cv_broadcast(&sc->sc_intr_cv);
    318  1.1  jmcneill 
    319  1.1  jmcneill 	mutex_exit(&sc->sc_intr_lock);
    320  1.1  jmcneill 
    321  1.1  jmcneill 	return 1;
    322  1.1  jmcneill }
    323  1.1  jmcneill 
    324  1.1  jmcneill static void
    325  1.1  jmcneill meson_sdhc_dmainit(struct meson_sdhc_softc *sc)
    326  1.1  jmcneill {
    327  1.1  jmcneill 	int error, rseg;
    328  1.1  jmcneill 
    329  1.1  jmcneill 	error = bus_dmamem_alloc(sc->sc_dmat, MAXPHYS, PAGE_SIZE, MAXPHYS,
    330  1.1  jmcneill 	    sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK);
    331  1.1  jmcneill 	if (error) {
    332  1.1  jmcneill 		device_printf(sc->sc_dev, "bus_dmamem_alloc failed: %d\n", error);
    333  1.1  jmcneill 		return;
    334  1.1  jmcneill 	}
    335  1.1  jmcneill 	KASSERT(rseg == 1);
    336  1.1  jmcneill 
    337  1.1  jmcneill 	error = bus_dmamem_map(sc->sc_dmat, sc->sc_segs, rseg, MAXPHYS,
    338  1.1  jmcneill 	    &sc->sc_bbuf, BUS_DMA_WAITOK);
    339  1.1  jmcneill 	if (error) {
    340  1.1  jmcneill 		device_printf(sc->sc_dev, "bus_dmamem_map failed\n");
    341  1.1  jmcneill 		return;
    342  1.1  jmcneill 	}
    343  1.1  jmcneill 
    344  1.1  jmcneill 	error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0,
    345  1.1  jmcneill 	    BUS_DMA_WAITOK, &sc->sc_dmamap);
    346  1.1  jmcneill 	if (error) {
    347  1.1  jmcneill 		device_printf(sc->sc_dev, "bus_dmamap_create failed\n");
    348  1.1  jmcneill 		return;
    349  1.1  jmcneill 	}
    350  1.1  jmcneill 
    351  1.1  jmcneill }
    352  1.1  jmcneill 
    353  1.1  jmcneill static int
    354  1.1  jmcneill meson_sdhc_default_rx_phase(struct meson_sdhc_softc *sc)
    355  1.1  jmcneill {
    356  1.1  jmcneill 	const u_int pll_freq = sc->sc_bus_freq / 1000;
    357  1.1  jmcneill 	const u_int clkc = SDHC_READ(sc, SD_CLKC_REG);
    358  1.1  jmcneill 	const u_int clk_div = __SHIFTOUT(clkc, SD_CLKC_CLK_DIV);
    359  1.1  jmcneill 	const u_int act_freq = pll_freq / clk_div;
    360  1.1  jmcneill 
    361  1.1  jmcneill 	if (act_freq > 90000) {
    362  1.1  jmcneill 		return 1;
    363  1.1  jmcneill 	} else if (act_freq > 45000) {
    364  1.1  jmcneill 		if (sc->sc_signal_voltage == SDMMC_SIGNAL_VOLTAGE_330) {
    365  1.1  jmcneill 			return 15;
    366  1.1  jmcneill 		} else {
    367  1.1  jmcneill 			return 11;
    368  1.1  jmcneill 		}
    369  1.1  jmcneill 	} else if (act_freq >= 25000) {
    370  1.1  jmcneill 		return 15;
    371  1.1  jmcneill 	} else if (act_freq > 5000) {
    372  1.1  jmcneill 		return 23;
    373  1.1  jmcneill 	} else if (act_freq > 1000) {
    374  1.1  jmcneill 		return 55;
    375  1.1  jmcneill 	} else {
    376  1.1  jmcneill 		return 1061;
    377  1.1  jmcneill 	}
    378  1.1  jmcneill }
    379  1.1  jmcneill 
    380  1.1  jmcneill static int
    381  1.1  jmcneill meson_sdhc_set_clock(struct meson_sdhc_softc *sc, u_int freq)
    382  1.1  jmcneill {
    383  1.1  jmcneill 	uint32_t clkc;
    384  1.1  jmcneill 	uint32_t clk2;
    385  1.1  jmcneill 	u_int pll_freq, clk_div;
    386  1.1  jmcneill 
    387  1.1  jmcneill 	clkc = SDHC_READ(sc, SD_CLKC_REG);
    388  1.1  jmcneill 	clkc &= ~SD_CLKC_TX_CLK_ENABLE;
    389  1.1  jmcneill 	clkc &= ~SD_CLKC_RX_CLK_ENABLE;
    390  1.1  jmcneill 	clkc &= ~SD_CLKC_SD_CLK_ENABLE;
    391  1.1  jmcneill 	SDHC_WRITE(sc, SD_CLKC_REG, clkc);
    392  1.1  jmcneill 	clkc &= ~SD_CLKC_MOD_CLK_ENABLE;
    393  1.1  jmcneill 	SDHC_WRITE(sc, SD_CLKC_REG, clkc);
    394  1.1  jmcneill 
    395  1.1  jmcneill 	if (freq == 0)
    396  1.1  jmcneill 		return 0;
    397  1.1  jmcneill 
    398  1.1  jmcneill 	clkc &= ~SD_CLKC_CLK_DIV;
    399  1.1  jmcneill 	clkc &= ~SD_CLKC_CLK_IN_SEL;
    400  1.1  jmcneill 
    401  1.1  jmcneill 	clkc |= __SHIFTIN(SD_CLKC_CLK_IN_SEL_FCLK_DIV3,
    402  1.1  jmcneill 			  SD_CLKC_CLK_IN_SEL);
    403  1.1  jmcneill 
    404  1.1  jmcneill 	pll_freq = sc->sc_bus_freq / 1000;	/* 2.55GHz */
    405  1.1  jmcneill 	clk_div = howmany(pll_freq, freq);
    406  1.1  jmcneill 
    407  1.1  jmcneill 	clkc |= __SHIFTIN(clk_div - 1, SD_CLKC_CLK_DIV);
    408  1.1  jmcneill 
    409  1.1  jmcneill 	SDHC_WRITE(sc, SD_CLKC_REG, clkc);
    410  1.1  jmcneill 
    411  1.1  jmcneill 	clkc |= SD_CLKC_MOD_CLK_ENABLE;
    412  1.1  jmcneill 	SDHC_WRITE(sc, SD_CLKC_REG, clkc);
    413  1.1  jmcneill 
    414  1.1  jmcneill 	clkc |= SD_CLKC_TX_CLK_ENABLE;
    415  1.1  jmcneill 	clkc |= SD_CLKC_RX_CLK_ENABLE;
    416  1.1  jmcneill 	clkc |= SD_CLKC_SD_CLK_ENABLE;
    417  1.1  jmcneill 	SDHC_WRITE(sc, SD_CLKC_REG, clkc);
    418  1.1  jmcneill 
    419  1.1  jmcneill 	clk2 = SDHC_READ(sc, SD_CLK2_REG);
    420  1.1  jmcneill 	clk2 &= ~SD_CLK2_SD_CLK_PHASE;
    421  1.1  jmcneill 	clk2 |= __SHIFTIN(1, SD_CLK2_SD_CLK_PHASE);
    422  1.1  jmcneill 	clk2 &= ~SD_CLK2_RX_CLK_PHASE;
    423  1.1  jmcneill 	clk2 |= __SHIFTIN(meson_sdhc_default_rx_phase(sc),
    424  1.1  jmcneill 			  SD_CLK2_RX_CLK_PHASE);
    425  1.1  jmcneill 	SDHC_WRITE(sc, SD_CLK2_REG, clk2);
    426  1.1  jmcneill 
    427  1.1  jmcneill 	return 0;
    428  1.1  jmcneill }
    429  1.1  jmcneill 
    430  1.1  jmcneill static int
    431  1.1  jmcneill meson_sdhc_wait_idle(struct meson_sdhc_softc *sc)
    432  1.1  jmcneill {
    433  1.1  jmcneill 	int i;
    434  1.1  jmcneill 
    435  1.1  jmcneill 	for (i = 0; i < 1000000; i++) {
    436  1.1  jmcneill 		const uint32_t stat = SDHC_READ(sc, SD_STAT_REG);
    437  1.1  jmcneill 		const uint32_t esta = SDHC_READ(sc, SD_ESTA_REG);
    438  1.1  jmcneill 		if ((stat & SD_STAT_BUSY) == 0 &&
    439  1.1  jmcneill 		    (esta & SD_ESTA_BUSY) == 0)
    440  1.1  jmcneill 			return 0;
    441  1.1  jmcneill 		delay(1);
    442  1.1  jmcneill 	}
    443  1.1  jmcneill 
    444  1.1  jmcneill 	return EBUSY;
    445  1.1  jmcneill }
    446  1.1  jmcneill 
    447  1.1  jmcneill static int
    448  1.1  jmcneill meson_sdhc_wait_ista(struct meson_sdhc_softc *sc, uint32_t mask, int timeout)
    449  1.1  jmcneill {
    450  1.1  jmcneill 	int retry, error;
    451  1.1  jmcneill 
    452  1.1  jmcneill 	KASSERT(mutex_owned(&sc->sc_intr_lock));
    453  1.1  jmcneill 
    454  1.1  jmcneill 	if (sc->sc_intr_ista & mask)
    455  1.1  jmcneill 		return 0;
    456  1.1  jmcneill 
    457  1.1  jmcneill 	retry = timeout / hz;
    458  1.1  jmcneill 
    459  1.1  jmcneill 	while (retry > 0) {
    460  1.1  jmcneill 		error = cv_timedwait(&sc->sc_intr_cv, &sc->sc_intr_lock, hz);
    461  1.1  jmcneill 		if (error && error != EWOULDBLOCK)
    462  1.1  jmcneill 			return error;
    463  1.1  jmcneill 		if (sc->sc_intr_ista & mask)
    464  1.1  jmcneill 			return 0;
    465  1.1  jmcneill 		--retry;
    466  1.1  jmcneill 	}
    467  1.1  jmcneill 
    468  1.1  jmcneill 	return ETIMEDOUT;
    469  1.1  jmcneill }
    470  1.1  jmcneill 
    471  1.1  jmcneill static int
    472  1.1  jmcneill meson_sdhc_host_reset(sdmmc_chipset_handle_t sch)
    473  1.1  jmcneill {
    474  1.1  jmcneill 	struct meson_sdhc_softc *sc = sch;
    475  1.1  jmcneill 	uint32_t enhc;
    476  1.1  jmcneill 
    477  1.1  jmcneill 	SDHC_WRITE(sc, SD_SRST_REG,
    478  1.1  jmcneill 	    SD_SRST_MAIN_CTRL | SD_SRST_TX_FIFO | SD_SRST_RX_FIFO |
    479  1.1  jmcneill 	    SD_SRST_DPHY_TX | SD_SRST_DPHY_RX | SD_SRST_DMA_IF);
    480  1.1  jmcneill 
    481  1.1  jmcneill 	delay(50);
    482  1.1  jmcneill 
    483  1.1  jmcneill 	SDHC_WRITE(sc, SD_SRST_REG, 0);
    484  1.1  jmcneill 
    485  1.1  jmcneill 	delay(10);
    486  1.1  jmcneill 
    487  1.1  jmcneill 	SDHC_WRITE(sc, SD_CNTL_REG,
    488  1.1  jmcneill 	    __SHIFTIN(0x7, SD_CNTL_TX_ENDIAN_CTRL) |
    489  1.1  jmcneill 	    __SHIFTIN(0x7, SD_CNTL_RX_ENDIAN_CTRL) |
    490  1.1  jmcneill 	    __SHIFTIN(0xf, SD_CNTL_RX_PERIOD) |
    491  1.1  jmcneill 	    __SHIFTIN(0x7f, SD_CNTL_RX_TIMEOUT));
    492  1.1  jmcneill 
    493  1.1  jmcneill 	SDHC_WRITE(sc, SD_CLKC_REG,
    494  1.1  jmcneill 	    SDHC_READ(sc, SD_CLKC_REG) & ~SD_CLKC_MEM_PWR);
    495  1.1  jmcneill 
    496  1.1  jmcneill 	SDHC_WRITE(sc, SD_PDMA_REG,
    497  1.1  jmcneill 	    __SHIFTIN(7, SD_PDMA_TX_BURST_LEN) |
    498  1.1  jmcneill 	    __SHIFTIN(49, SD_PDMA_TXFIFO_THRESHOLD) |
    499  1.1  jmcneill 	    __SHIFTIN(15, SD_PDMA_RX_BURST_LEN) |
    500  1.1  jmcneill 	    __SHIFTIN(7, SD_PDMA_RXFIFO_THRESHOLD) |
    501  1.1  jmcneill 	    SD_PDMA_DMA_URGENT);
    502  1.1  jmcneill 
    503  1.1  jmcneill 	SDHC_WRITE(sc, SD_MISC_REG,
    504  1.1  jmcneill 	    __SHIFTIN(7, SD_MISC_TXSTART_THRESHOLD) |
    505  1.1  jmcneill 	    __SHIFTIN(5, SD_MISC_WCRC_ERR_PATTERN) |
    506  1.1  jmcneill 	    __SHIFTIN(2, SD_MISC_WCRC_OK_PATTERN));
    507  1.1  jmcneill 
    508  1.1  jmcneill 	enhc = SDHC_READ(sc, SD_ENHC_REG);
    509  1.1  jmcneill 	enhc &= ~SD_ENHC_RXFIFO_THRESHOLD;
    510  1.1  jmcneill 	enhc |= __SHIFTIN(63, SD_ENHC_RXFIFO_THRESHOLD);
    511  1.1  jmcneill 	enhc &= ~SD_ENHC_DMA_RX_RESP;
    512  1.1  jmcneill 	enhc |= SD_ENHC_DMA_TX_RESP;
    513  1.1  jmcneill 	enhc &= ~SD_ENHC_SDIO_IRQ_PERIOD;
    514  1.1  jmcneill 	enhc |= __SHIFTIN(12, SD_ENHC_SDIO_IRQ_PERIOD);
    515  1.1  jmcneill 	enhc &= ~SD_ENHC_RX_TIMEOUT;
    516  1.1  jmcneill 	enhc |= __SHIFTIN(0xff, SD_ENHC_RX_TIMEOUT);
    517  1.1  jmcneill 	SDHC_WRITE(sc, SD_ENHC_REG, enhc);
    518  1.1  jmcneill 
    519  1.1  jmcneill 	SDHC_WRITE(sc, SD_ICTL_REG, 0);
    520  1.1  jmcneill 	SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);
    521  1.1  jmcneill 
    522  1.1  jmcneill 	return 0;
    523  1.1  jmcneill }
    524  1.1  jmcneill 
    525  1.1  jmcneill static uint32_t
    526  1.1  jmcneill meson_sdhc_host_ocr(sdmmc_chipset_handle_t sch)
    527  1.1  jmcneill {
    528  1.1  jmcneill 	return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V |
    529  1.1  jmcneill 	       MMC_OCR_HCS | MMC_OCR_S18A;
    530  1.1  jmcneill }
    531  1.1  jmcneill 
    532  1.1  jmcneill static int
    533  1.1  jmcneill meson_sdhc_host_maxblklen(sdmmc_chipset_handle_t sch)
    534  1.1  jmcneill {
    535  1.1  jmcneill 	return 512;
    536  1.1  jmcneill }
    537  1.1  jmcneill 
    538  1.1  jmcneill static int
    539  1.1  jmcneill meson_sdhc_card_detect(sdmmc_chipset_handle_t sch)
    540  1.1  jmcneill {
    541  1.1  jmcneill 	struct meson_sdhc_softc *sc = sch;
    542  1.1  jmcneill 	int val;
    543  1.1  jmcneill 
    544  1.1  jmcneill 	if (sc->sc_non_removable || sc->sc_broken_cd) {
    545  1.1  jmcneill 		return 1;
    546  1.1  jmcneill 	} else if (sc->sc_gpio_cd != NULL) {
    547  1.1  jmcneill 		val = fdtbus_gpio_read(sc->sc_gpio_cd);
    548  1.1  jmcneill 		if (sc->sc_gpio_cd_inverted)
    549  1.1  jmcneill 			val = !val;
    550  1.1  jmcneill 		return val;
    551  1.1  jmcneill 	} else {
    552  1.1  jmcneill 		return 1;
    553  1.1  jmcneill 	}
    554  1.1  jmcneill }
    555  1.1  jmcneill 
    556  1.1  jmcneill static int
    557  1.1  jmcneill meson_sdhc_write_protect(sdmmc_chipset_handle_t sch)
    558  1.1  jmcneill {
    559  1.1  jmcneill 	struct meson_sdhc_softc *sc = sch;
    560  1.1  jmcneill 	int val;
    561  1.1  jmcneill 
    562  1.1  jmcneill 	if (sc->sc_gpio_wp != NULL) {
    563  1.1  jmcneill 		val = fdtbus_gpio_read(sc->sc_gpio_wp);
    564  1.1  jmcneill 		if (sc->sc_gpio_wp_inverted)
    565  1.1  jmcneill 			val = !val;
    566  1.1  jmcneill 		return val;
    567  1.1  jmcneill 	}
    568  1.1  jmcneill 
    569  1.1  jmcneill 	return 0;
    570  1.1  jmcneill }
    571  1.1  jmcneill 
    572  1.1  jmcneill static int
    573  1.1  jmcneill meson_sdhc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
    574  1.1  jmcneill {
    575  1.1  jmcneill 	return 0;
    576  1.1  jmcneill }
    577  1.1  jmcneill 
    578  1.1  jmcneill static int
    579  1.1  jmcneill meson_sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
    580  1.1  jmcneill {
    581  1.1  jmcneill 	struct meson_sdhc_softc *sc = sch;
    582  1.1  jmcneill 
    583  1.1  jmcneill 	return meson_sdhc_set_clock(sc, freq);
    584  1.1  jmcneill }
    585  1.1  jmcneill 
    586  1.1  jmcneill static int
    587  1.1  jmcneill meson_sdhc_bus_width(sdmmc_chipset_handle_t sch, int width)
    588  1.1  jmcneill {
    589  1.1  jmcneill 	struct meson_sdhc_softc *sc = sch;
    590  1.1  jmcneill 	uint32_t cntl;
    591  1.1  jmcneill 
    592  1.1  jmcneill 	cntl = SDHC_READ(sc, SD_CNTL_REG);
    593  1.1  jmcneill 	cntl &= ~SD_CNTL_DAT_TYPE;
    594  1.1  jmcneill 	switch (width) {
    595  1.1  jmcneill 	case 1:
    596  1.1  jmcneill 		cntl |= __SHIFTIN(0, SD_CNTL_DAT_TYPE);
    597  1.1  jmcneill 		break;
    598  1.1  jmcneill 	case 4:
    599  1.1  jmcneill 		cntl |= __SHIFTIN(1, SD_CNTL_DAT_TYPE);
    600  1.1  jmcneill 		break;
    601  1.1  jmcneill 	case 8:
    602  1.1  jmcneill 		cntl |= __SHIFTIN(2, SD_CNTL_DAT_TYPE);
    603  1.1  jmcneill 		break;
    604  1.1  jmcneill 	default:
    605  1.1  jmcneill 		return EINVAL;
    606  1.1  jmcneill 	}
    607  1.1  jmcneill 
    608  1.1  jmcneill 	SDHC_WRITE(sc, SD_CNTL_REG, cntl);
    609  1.1  jmcneill 
    610  1.1  jmcneill 	return 0;
    611  1.1  jmcneill }
    612  1.1  jmcneill 
    613  1.1  jmcneill static int
    614  1.1  jmcneill meson_sdhc_bus_rod(sdmmc_chipset_handle_t sch, int on)
    615  1.1  jmcneill {
    616  1.1  jmcneill 	return ENOTSUP;
    617  1.1  jmcneill }
    618  1.1  jmcneill 
    619  1.1  jmcneill static void
    620  1.1  jmcneill meson_sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
    621  1.1  jmcneill {
    622  1.1  jmcneill 	struct meson_sdhc_softc *sc = sch;
    623  1.1  jmcneill 	uint32_t cmdval = 0, cntl, srst, pdma, ictl;
    624  1.1  jmcneill 	bool use_bbuf = false;
    625  1.1  jmcneill 	int i;
    626  1.1  jmcneill 
    627  1.1  jmcneill 	KASSERT(cmd->c_blklen <= 512);
    628  1.1  jmcneill 
    629  1.1  jmcneill 	mutex_enter(&sc->sc_intr_lock);
    630  1.1  jmcneill 
    631  1.1  jmcneill 	/* Filter SDIO commands */
    632  1.1  jmcneill 	switch (cmd->c_opcode) {
    633  1.1  jmcneill 	case SD_IO_SEND_OP_COND:
    634  1.1  jmcneill 	case SD_IO_RW_DIRECT:
    635  1.1  jmcneill 	case SD_IO_RW_EXTENDED:
    636  1.1  jmcneill 		cmd->c_error = EINVAL;
    637  1.1  jmcneill 		goto done;
    638  1.1  jmcneill 	}
    639  1.1  jmcneill 
    640  1.1  jmcneill 	if (cmd->c_opcode == MMC_STOP_TRANSMISSION)
    641  1.1  jmcneill 		cmdval |= SD_SEND_DATA_STOP;
    642  1.1  jmcneill 	if (cmd->c_flags & SCF_RSP_PRESENT)
    643  1.1  jmcneill 		cmdval |= SD_SEND_COMMAND_HAS_RESP;
    644  1.1  jmcneill 	if (cmd->c_flags & SCF_RSP_136) {
    645  1.1  jmcneill 		cmdval |= SD_SEND_RESPONSE_LENGTH;
    646  1.1  jmcneill 		cmdval |= SD_SEND_RESPONSE_NO_CRC;
    647  1.1  jmcneill 	}
    648  1.1  jmcneill 	if ((cmd->c_flags & SCF_RSP_CRC) == 0)
    649  1.1  jmcneill 		cmdval |= SD_SEND_RESPONSE_NO_CRC;
    650  1.1  jmcneill 
    651  1.1  jmcneill 	SDHC_WRITE(sc, SD_ICTL_REG, 0);
    652  1.1  jmcneill 	SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);
    653  1.1  jmcneill 	sc->sc_intr_ista = 0;
    654  1.1  jmcneill 
    655  1.1  jmcneill 	ictl = SD_INT_ERROR;
    656  1.1  jmcneill 
    657  1.1  jmcneill 	cntl = SDHC_READ(sc, SD_CNTL_REG);
    658  1.1  jmcneill 	cntl &= ~SD_CNTL_PACK_LEN;
    659  1.1  jmcneill 	if (cmd->c_datalen > 0) {
    660  1.1  jmcneill 		unsigned int nblks;
    661  1.1  jmcneill 
    662  1.1  jmcneill 		cmdval |= SD_SEND_COMMAND_HAS_DATA;
    663  1.1  jmcneill 		if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
    664  1.1  jmcneill 			cmdval |= SD_SEND_DATA_DIRECTION;
    665  1.1  jmcneill 		}
    666  1.1  jmcneill 
    667  1.1  jmcneill 		nblks = cmd->c_datalen / cmd->c_blklen;
    668  1.1  jmcneill 		if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
    669  1.1  jmcneill 			++nblks;
    670  1.1  jmcneill 
    671  1.1  jmcneill 		cntl |= __SHIFTIN(cmd->c_blklen & 0x1ff, SD_CNTL_PACK_LEN);
    672  1.1  jmcneill 
    673  1.1  jmcneill 		cmdval |= __SHIFTIN(nblks - 1, SD_SEND_TOTAL_PACK);
    674  1.1  jmcneill 
    675  1.1  jmcneill 		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
    676  1.1  jmcneill 			ictl |= SD_INT_DATA_COMPLETE;
    677  1.1  jmcneill 		} else {
    678  1.1  jmcneill 			ictl |= SD_INT_DMA_DONE;
    679  1.1  jmcneill 		}
    680  1.1  jmcneill 	} else {
    681  1.1  jmcneill 		ictl |= SD_INT_RESP_COMPLETE;
    682  1.1  jmcneill 	}
    683  1.1  jmcneill 
    684  1.1  jmcneill 	SDHC_WRITE(sc, SD_ICTL_REG, ictl);
    685  1.1  jmcneill 
    686  1.1  jmcneill 	SDHC_WRITE(sc, SD_CNTL_REG, cntl);
    687  1.1  jmcneill 
    688  1.1  jmcneill 	pdma = SDHC_READ(sc, SD_PDMA_REG);
    689  1.1  jmcneill 	if (cmd->c_datalen > 0) {
    690  1.1  jmcneill 		pdma |= SD_PDMA_DMA_MODE;
    691  1.1  jmcneill 	} else {
    692  1.1  jmcneill 		pdma &= ~SD_PDMA_DMA_MODE;
    693  1.1  jmcneill 	}
    694  1.1  jmcneill 	SDHC_WRITE(sc, SD_PDMA_REG, pdma);
    695  1.1  jmcneill 
    696  1.1  jmcneill 	SDHC_WRITE(sc, SD_ARGU_REG, cmd->c_arg);
    697  1.1  jmcneill 
    698  1.1  jmcneill 	cmd->c_error = meson_sdhc_wait_idle(sc);
    699  1.1  jmcneill 	if (cmd->c_error) {
    700  1.1  jmcneill 		goto done;
    701  1.1  jmcneill 	}
    702  1.1  jmcneill 
    703  1.1  jmcneill 	if (cmd->c_datalen > 0) {
    704  1.1  jmcneill 		cmd->c_error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
    705  1.1  jmcneill 		    sc->sc_bbuf, MAXPHYS, NULL, BUS_DMA_WAITOK);
    706  1.1  jmcneill 		if (cmd->c_error) {
    707  1.1  jmcneill 			device_printf(sc->sc_dev, "bus_dmamap_load failed\n");
    708  1.1  jmcneill 			goto done;
    709  1.1  jmcneill 		}
    710  1.1  jmcneill 		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
    711  1.1  jmcneill 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
    712  1.1  jmcneill 			    MAXPHYS, BUS_DMASYNC_PREREAD);
    713  1.1  jmcneill 		} else {
    714  1.1  jmcneill 			memcpy(sc->sc_bbuf, cmd->c_data, cmd->c_datalen);
    715  1.1  jmcneill 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
    716  1.1  jmcneill 			    MAXPHYS, BUS_DMASYNC_PREWRITE);
    717  1.1  jmcneill 		}
    718  1.1  jmcneill 		SDHC_WRITE(sc, SD_ADDR_REG, sc->sc_dmamap->dm_segs[0].ds_addr);
    719  1.1  jmcneill 		use_bbuf = true;
    720  1.1  jmcneill 	}
    721  1.1  jmcneill 
    722  1.1  jmcneill 	cmd->c_resid = cmd->c_datalen;
    723  1.1  jmcneill 	SDHC_WRITE(sc, SD_SEND_REG, cmdval | cmd->c_opcode);
    724  1.1  jmcneill 
    725  1.1  jmcneill 	if (cmd->c_datalen > 0) {
    726  1.1  jmcneill 		uint32_t wbit = ISSET(cmd->c_flags, SCF_CMD_READ) ?
    727  1.1  jmcneill 		    SD_INT_DATA_COMPLETE : SD_INT_DMA_DONE;
    728  1.1  jmcneill 		cmd->c_error = meson_sdhc_wait_ista(sc,
    729  1.1  jmcneill 		    SD_INT_ERROR | wbit, hz * 10);
    730  1.1  jmcneill 		if (cmd->c_error == 0 &&
    731  1.1  jmcneill 		    (sc->sc_intr_ista & SD_INT_ERROR)) {
    732  1.1  jmcneill 			cmd->c_error = ETIMEDOUT;
    733  1.1  jmcneill 		}
    734  1.1  jmcneill 		if (cmd->c_error) {
    735  1.1  jmcneill 			goto done;
    736  1.1  jmcneill 		}
    737  1.1  jmcneill 	} else {
    738  1.1  jmcneill 		cmd->c_error = meson_sdhc_wait_ista(sc,
    739  1.1  jmcneill 		    SD_INT_ERROR | SD_INT_RESP_COMPLETE, hz * 10);
    740  1.1  jmcneill 		if (cmd->c_error == 0 && (sc->sc_intr_ista & SD_INT_ERROR)) {
    741  1.1  jmcneill 			if (sc->sc_intr_ista & SD_INT_TIMEOUT) {
    742  1.1  jmcneill 				cmd->c_error = ETIMEDOUT;
    743  1.1  jmcneill 			} else {
    744  1.1  jmcneill 				cmd->c_error = EIO;
    745  1.1  jmcneill 			}
    746  1.1  jmcneill 		}
    747  1.1  jmcneill 		if (cmd->c_error) {
    748  1.1  jmcneill 			goto done;
    749  1.1  jmcneill 		}
    750  1.1  jmcneill 	}
    751  1.1  jmcneill 
    752  1.1  jmcneill 	SDHC_WRITE(sc, SD_ISTA_REG, sc->sc_intr_ista);
    753  1.1  jmcneill 
    754  1.1  jmcneill 	if (cmd->c_flags & SCF_RSP_PRESENT) {
    755  1.1  jmcneill 		pdma = SDHC_READ(sc, SD_PDMA_REG);
    756  1.1  jmcneill 		pdma &= ~SD_PDMA_DMA_MODE;
    757  1.1  jmcneill 		if (cmd->c_flags & SCF_RSP_136) {
    758  1.1  jmcneill 			for (i = 4; i >= 1; i--) {
    759  1.1  jmcneill 				pdma &= ~SD_PDMA_PIO_RDRESP;
    760  1.1  jmcneill 				pdma |= __SHIFTIN(i, SD_PDMA_PIO_RDRESP);
    761  1.1  jmcneill 				SDHC_WRITE(sc, SD_PDMA_REG, pdma);
    762  1.1  jmcneill 				cmd->c_resp[i - 1] = SDHC_READ(sc, SD_ARGU_REG);
    763  1.1  jmcneill 
    764  1.1  jmcneill 			}
    765  1.1  jmcneill 			if (cmd->c_flags & SCF_RSP_CRC) {
    766  1.1  jmcneill 				cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
    767  1.1  jmcneill 				    (cmd->c_resp[1] << 24);
    768  1.1  jmcneill 				cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
    769  1.1  jmcneill 				    (cmd->c_resp[2] << 24);
    770  1.1  jmcneill 				cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
    771  1.1  jmcneill 				    (cmd->c_resp[3] << 24);
    772  1.1  jmcneill 				cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
    773  1.1  jmcneill 			}
    774  1.1  jmcneill 		} else {
    775  1.1  jmcneill 			pdma &= ~SD_PDMA_PIO_RDRESP;
    776  1.1  jmcneill 			pdma |= __SHIFTIN(0, SD_PDMA_PIO_RDRESP);
    777  1.1  jmcneill 			SDHC_WRITE(sc, SD_PDMA_REG, pdma);
    778  1.1  jmcneill 			cmd->c_resp[0] = SDHC_READ(sc, SD_ARGU_REG);
    779  1.1  jmcneill 		}
    780  1.1  jmcneill 	}
    781  1.1  jmcneill 
    782  1.1  jmcneill done:
    783  1.1  jmcneill 	if (use_bbuf) {
    784  1.1  jmcneill 		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
    785  1.1  jmcneill 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
    786  1.1  jmcneill 			    MAXPHYS, BUS_DMASYNC_POSTREAD);
    787  1.1  jmcneill 		} else {
    788  1.1  jmcneill 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
    789  1.1  jmcneill 			    MAXPHYS, BUS_DMASYNC_POSTWRITE);
    790  1.1  jmcneill 		}
    791  1.1  jmcneill 		bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap);
    792  1.1  jmcneill 		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
    793  1.1  jmcneill 			memcpy(cmd->c_data, sc->sc_bbuf, cmd->c_datalen);
    794  1.1  jmcneill 		}
    795  1.1  jmcneill 	}
    796  1.1  jmcneill 
    797  1.1  jmcneill 	cmd->c_flags |= SCF_ITSDONE;
    798  1.1  jmcneill 
    799  1.1  jmcneill 	SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);
    800  1.1  jmcneill 	SDHC_WRITE(sc, SD_ICTL_REG, 0);
    801  1.1  jmcneill 
    802  1.1  jmcneill 	srst = SDHC_READ(sc, SD_SRST_REG);
    803  1.1  jmcneill 	srst |= (SD_SRST_TX_FIFO | SD_SRST_RX_FIFO);
    804  1.1  jmcneill 	SDHC_WRITE(sc, SD_SRST_REG, srst);
    805  1.1  jmcneill 
    806  1.1  jmcneill 	mutex_exit(&sc->sc_intr_lock);
    807  1.1  jmcneill }
    808  1.1  jmcneill 
    809  1.1  jmcneill static void
    810  1.1  jmcneill meson_sdhc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
    811  1.1  jmcneill {
    812  1.1  jmcneill }
    813  1.1  jmcneill 
    814  1.1  jmcneill static void
    815  1.1  jmcneill meson_sdhc_card_intr_ack(sdmmc_chipset_handle_t sch)
    816  1.1  jmcneill {
    817  1.1  jmcneill }
    818  1.1  jmcneill 
    819  1.1  jmcneill static int
    820  1.1  jmcneill meson_sdhc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage)
    821  1.1  jmcneill {
    822  1.1  jmcneill 	struct meson_sdhc_softc *sc = sch;
    823  1.1  jmcneill 	u_int uvol;
    824  1.1  jmcneill 	int error;
    825  1.1  jmcneill 
    826  1.1  jmcneill 	if (sc->sc_reg_vqmmc == NULL)
    827  1.1  jmcneill 		return 0;
    828  1.1  jmcneill 
    829  1.1  jmcneill 	switch (signal_voltage) {
    830  1.1  jmcneill 	case SDMMC_SIGNAL_VOLTAGE_330:
    831  1.1  jmcneill 		uvol = 3300000;
    832  1.1  jmcneill 		break;
    833  1.1  jmcneill 	case SDMMC_SIGNAL_VOLTAGE_180:
    834  1.1  jmcneill 		uvol = 1800000;
    835  1.1  jmcneill 		break;
    836  1.1  jmcneill 	default:
    837  1.1  jmcneill 		return EINVAL;
    838  1.1  jmcneill 	}
    839  1.1  jmcneill 
    840  1.1  jmcneill 	error = fdtbus_regulator_supports_voltage(sc->sc_reg_vqmmc, uvol, uvol);
    841  1.1  jmcneill 	if (error != 0)
    842  1.1  jmcneill 		return 0;
    843  1.1  jmcneill 
    844  1.1  jmcneill 	error = fdtbus_regulator_set_voltage(sc->sc_reg_vqmmc, uvol, uvol);
    845  1.1  jmcneill 	if (error != 0)
    846  1.1  jmcneill 		return error;
    847  1.1  jmcneill 
    848  1.1  jmcneill 	error = fdtbus_regulator_enable(sc->sc_reg_vqmmc);
    849  1.1  jmcneill 	if (error != 0)
    850  1.1  jmcneill 		return error;
    851  1.1  jmcneill 
    852  1.1  jmcneill 	sc->sc_signal_voltage = signal_voltage;
    853  1.1  jmcneill 	return 0;
    854  1.1  jmcneill }
    855  1.1  jmcneill 
    856  1.1  jmcneill static int
    857  1.1  jmcneill meson_sdhc_execute_tuning(sdmmc_chipset_handle_t sch, int timing)
    858  1.1  jmcneill {
    859  1.1  jmcneill 	static const uint8_t tuning_blk_8bit[] = {
    860  1.1  jmcneill 		0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
    861  1.1  jmcneill 		0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
    862  1.1  jmcneill 		0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
    863  1.1  jmcneill 		0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
    864  1.1  jmcneill 		0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
    865  1.1  jmcneill 		0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
    866  1.1  jmcneill 		0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
    867  1.1  jmcneill 		0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
    868  1.1  jmcneill 		0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
    869  1.1  jmcneill 		0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
    870  1.1  jmcneill 		0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
    871  1.1  jmcneill 		0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
    872  1.1  jmcneill 		0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
    873  1.1  jmcneill 		0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
    874  1.1  jmcneill 		0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
    875  1.1  jmcneill 		0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
    876  1.1  jmcneill 	};
    877  1.1  jmcneill 	static const uint8_t tuning_blk_4bit[] = {
    878  1.1  jmcneill 		0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
    879  1.1  jmcneill 		0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
    880  1.1  jmcneill 		0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
    881  1.1  jmcneill 		0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
    882  1.1  jmcneill 		0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
    883  1.1  jmcneill 		0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
    884  1.1  jmcneill 		0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
    885  1.1  jmcneill 		0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
    886  1.1  jmcneill 	};
    887  1.1  jmcneill 
    888  1.1  jmcneill 	struct meson_sdhc_softc *sc = sch;
    889  1.1  jmcneill 	struct sdmmc_command cmd;
    890  1.1  jmcneill 	uint8_t data[sizeof(tuning_blk_8bit)];
    891  1.1  jmcneill 	const uint8_t *tblk;
    892  1.1  jmcneill 	size_t tsize;
    893  1.1  jmcneill 	struct window_s {
    894  1.1  jmcneill 		int start;
    895  1.1  jmcneill 		u_int size;
    896  1.1  jmcneill 	} best = { .start = -1, .size = 0 },
    897  1.1  jmcneill 	  curr = { .start = -1, .size = 0 },
    898  1.1  jmcneill 	  wrap = { .start =  0, .size = 0 };
    899  1.1  jmcneill 	u_int ph, rx_phase, clk_div;
    900  1.1  jmcneill 	int opcode;
    901  1.1  jmcneill 
    902  1.1  jmcneill 	switch (timing) {
    903  1.1  jmcneill 	case SDMMC_TIMING_MMC_HS200:
    904  1.1  jmcneill 		tblk = tuning_blk_8bit;
    905  1.1  jmcneill 		tsize = sizeof(tuning_blk_8bit);
    906  1.1  jmcneill 		opcode = MMC_SEND_TUNING_BLOCK_HS200;
    907  1.1  jmcneill 		break;
    908  1.1  jmcneill 	case SDMMC_TIMING_UHS_SDR50:
    909  1.1  jmcneill 	case SDMMC_TIMING_UHS_SDR104:
    910  1.1  jmcneill 		tblk = tuning_blk_4bit;
    911  1.1  jmcneill 		tsize = sizeof(tuning_blk_4bit);
    912  1.1  jmcneill 		opcode = MMC_SEND_TUNING_BLOCK;
    913  1.1  jmcneill 		break;
    914  1.1  jmcneill 	default:
    915  1.1  jmcneill 		return EINVAL;
    916  1.1  jmcneill 	}
    917  1.1  jmcneill 
    918  1.1  jmcneill 	const uint32_t clkc = SDHC_READ(sc, SD_CLKC_REG);
    919  1.1  jmcneill 	clk_div = __SHIFTOUT(clkc, SD_CLKC_CLK_DIV);
    920  1.1  jmcneill 
    921  1.1  jmcneill 	for (ph = 0; ph <= clk_div; ph++) {
    922  1.1  jmcneill 		SDHC_SET_CLEAR(sc, SD_CLK2_REG,
    923  1.1  jmcneill 		    __SHIFTIN(ph, SD_CLK2_RX_CLK_PHASE), SD_CLK2_RX_CLK_PHASE);
    924  1.1  jmcneill 		delay(10);
    925  1.1  jmcneill 
    926  1.1  jmcneill 		u_int nmatch = 0;
    927  1.1  jmcneill #define NUMTRIES 10
    928  1.1  jmcneill 		for (u_int i = 0; i < NUMTRIES; i++) {
    929  1.1  jmcneill 			memset(data, 0, tsize);
    930  1.1  jmcneill 			memset(&cmd, 0, sizeof(cmd));
    931  1.1  jmcneill 			cmd.c_data = data;
    932  1.1  jmcneill 			cmd.c_datalen = cmd.c_blklen = tsize;
    933  1.1  jmcneill 			cmd.c_opcode = opcode;
    934  1.1  jmcneill 			cmd.c_arg = 0;
    935  1.1  jmcneill 			cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
    936  1.1  jmcneill 			meson_sdhc_exec_command(sc, &cmd);
    937  1.1  jmcneill 			if (cmd.c_error == 0 && memcmp(data, tblk, tsize) == 0)
    938  1.1  jmcneill 				nmatch++;
    939  1.1  jmcneill 		}
    940  1.1  jmcneill 		if (nmatch == NUMTRIES) {	/* good phase value */
    941  1.1  jmcneill 			if (wrap.start == 0)
    942  1.1  jmcneill 				wrap.size++;
    943  1.1  jmcneill 			if (curr.start == -1)
    944  1.1  jmcneill 				curr.start = ph;
    945  1.1  jmcneill 			curr.size++;
    946  1.1  jmcneill 		} else {
    947  1.1  jmcneill 			wrap.start = -1;
    948  1.1  jmcneill 			if (curr.start != -1) {	/* end of current window */
    949  1.1  jmcneill 				if (best.start == -1 || best.size < curr.size)
    950  1.1  jmcneill 					best = curr;
    951  1.1  jmcneill 				curr = (struct window_s)
    952  1.1  jmcneill 				    { .start = -1, .size = 0 };
    953  1.1  jmcneill 			}
    954  1.1  jmcneill 		}
    955  1.1  jmcneill #undef NUMTRIES
    956  1.1  jmcneill 	}
    957  1.1  jmcneill 
    958  1.1  jmcneill 	if (curr.start != -1) {	/* the current window wraps around */
    959  1.1  jmcneill 		curr.size += wrap.size;
    960  1.1  jmcneill 		if (curr.size > ph)
    961  1.1  jmcneill 			curr.size = ph;
    962  1.1  jmcneill 		if (best.start == -1 || best.size < curr.size)
    963  1.1  jmcneill 			best = curr;
    964  1.1  jmcneill 	}
    965  1.1  jmcneill 
    966  1.1  jmcneill 	if (best.start == -1) {	/* no window - use default rx_phase */
    967  1.1  jmcneill 		rx_phase = meson_sdhc_default_rx_phase(sc);
    968  1.1  jmcneill 	} else {
    969  1.1  jmcneill 		rx_phase = best.start + best.size / 2;
    970  1.1  jmcneill 		if (rx_phase >= ph)
    971  1.1  jmcneill 			rx_phase -= ph;
    972  1.1  jmcneill 	}
    973  1.1  jmcneill 
    974  1.1  jmcneill 	SDHC_SET_CLEAR(sc, SD_CLK2_REG,
    975  1.1  jmcneill 	    __SHIFTIN(rx_phase, SD_CLK2_RX_CLK_PHASE), SD_CLK2_RX_CLK_PHASE);
    976  1.1  jmcneill 
    977  1.1  jmcneill 	return 0;
    978  1.1  jmcneill }
    979