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