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