1 /* $OpenBSD: sdhc_fdt.c,v 1.12 2020/05/31 11:47:09 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2017 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/malloc.h> 20 #include <sys/systm.h> 21 22 #include <machine/bus.h> 23 #include <machine/fdt.h> 24 #include <machine/intr.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/ofw_clock.h> 28 #include <dev/ofw/ofw_gpio.h> 29 #include <dev/ofw/ofw_misc.h> 30 #include <dev/ofw/ofw_pinctrl.h> 31 #include <dev/ofw/ofw_regulator.h> 32 #include <dev/ofw/fdt.h> 33 34 #include <dev/sdmmc/sdhcreg.h> 35 #include <dev/sdmmc/sdhcvar.h> 36 #include <dev/sdmmc/sdmmcvar.h> 37 38 /* RK3399 */ 39 #define GRF_EMMCCORE_CON0_BASECLOCK 0xf000 40 #define GRF_EMMCCORE_CON0_BASECLOCK_CLR (0xff << 24) 41 #define GRF_EMMCCORE_CON0_BASECLOCK_VAL(x) (((x) & 0xff) << 8) 42 #define GRF_EMMCCORE_CON11 0xf02c 43 #define GRF_EMMCCORE_CON11_CLOCKMULT_CLR (0xff << 16) 44 #define GRF_EMMCCORE_CON11_CLOCKMULT_VAL(x) (((x) & 0xff) << 0) 45 46 /* Marvell Xenon */ 47 #define XENON_SYS_OP_CTRL 0x108 48 #define XENON_SYS_OP_CTRL_SLOT_ENABLE(x) (1 << (x)) 49 #define XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(x) (1 << ((x) + 8)) 50 #define XENON_SYS_OP_CTRL_AUTO_CLKGATE_DISABLE (1 << 20) 51 #define XENON_SYS_EXT_OP_CTRL 0x10c 52 #define XENON_SYS_EXT_OP_CTRL_PARALLEL_TRAN(x) (1 << (x)) 53 #define XENON_SYS_EXT_OP_CTRL_MASK_CMD_CONFLICT_ERR (1 << 8) 54 #define XENON_SLOT_EMMC_CTRL 0x130 55 #define XENON_SLOT_EMMC_CTRL_ENABLE_DATA_STROBE (1 << 24) 56 #define XENON_SLOT_EMMC_CTRL_ENABLE_RESP_STROBE (1 << 25) 57 #define XENON_EMMC_PHY_TIMING_ADJUST 0x170 58 #define XENON_EMMC_PHY_TIMING_ADJUST_SAMPL_INV_QSP_PHASE_SELECT (1 << 18) 59 #define XENON_EMMC_PHY_TIMING_ADJUST_SDIO_MODE (1 << 28) 60 #define XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE (1 << 29) 61 #define XENON_EMMC_PHY_TIMING_ADJUST_INIT (1U << 31) 62 #define XENON_EMMC_PHY_FUNC_CONTROL 0x174 63 #define XENON_EMMC_PHY_FUNC_CONTROL_DQ_ASYNC_MODE (1 << 4) 64 #define XENON_EMMC_PHY_FUNC_CONTROL_DQ_DDR_MODE (0xff << 8) 65 #define XENON_EMMC_PHY_FUNC_CONTROL_CMD_DDR_MODE (1 << 16) 66 #define XENON_EMMC_PHY_PAD_CONTROL 0x178 67 #define XENON_EMMC_PHY_PAD_CONTROL_FC_DQ_RECEN (1 << 24) 68 #define XENON_EMMC_PHY_PAD_CONTROL_FC_CMD_RECEN (1 << 25) 69 #define XENON_EMMC_PHY_PAD_CONTROL_FC_QSP_RECEN (1 << 26) 70 #define XENON_EMMC_PHY_PAD_CONTROL_FC_QSN_RECEN (1 << 27) 71 #define XENON_EMMC_PHY_PAD_CONTROL_FC_ALL_CMOS_RECVR 0xf000 72 #define XENON_EMMC_PHY_PAD_CONTROL1 0x17c 73 #define XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PD (1 << 8) 74 #define XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PD (1 << 9) 75 #define XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PU (1 << 24) 76 #define XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PU (1 << 25) 77 #define XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PD 0xff 78 #define XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PU (0xff << 16) 79 #define XENON_EMMC_PHY_PAD_CONTROL2 0x180 80 #define XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT 0 81 #define XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK 0x1f 82 #define XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT 8 83 #define XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK 0x1f 84 85 #define ARMADA_3700_SOC_PAD_CTL 0 86 #define ARMADA_3700_SOC_PAD_CTL_3_3V 0 87 #define ARMADA_3700_SOC_PAD_CTL_1_8V 1 88 89 struct sdhc_fdt_softc { 90 struct sdhc_softc sc; 91 bus_space_tag_t sc_iot; 92 bus_space_handle_t sc_ioh; 93 bus_space_handle_t sc_pad_ioh; 94 bus_size_t sc_size; 95 void *sc_ih; 96 int sc_node; 97 uint32_t sc_gpio[3]; 98 uint32_t sc_vqmmc; 99 100 /* Marvell Xenon */ 101 int sc_sdhc_id; 102 int sc_slow_mode; 103 uint32_t sc_znr; 104 uint32_t sc_zpr; 105 106 struct sdhc_host *sc_host; 107 struct clock_device sc_cd; 108 }; 109 110 int sdhc_fdt_match(struct device *, void *, void *); 111 void sdhc_fdt_attach(struct device *, struct device *, void *); 112 113 struct cfattach sdhc_fdt_ca = { 114 sizeof(struct sdhc_fdt_softc), sdhc_fdt_match, sdhc_fdt_attach 115 }; 116 117 int sdhc_fdt_card_detect(struct sdhc_softc *); 118 int sdhc_fdt_signal_voltage(struct sdhc_softc *, int); 119 uint32_t sdhc_fdt_get_frequency(void *, uint32_t *); 120 121 void sdhc_fdt_xenon_bus_clock_post(struct sdhc_softc *, int, int); 122 123 int 124 sdhc_fdt_match(struct device *parent, void *match, void *aux) 125 { 126 struct fdt_attach_args *faa = aux; 127 128 return (OF_is_compatible(faa->fa_node, "arasan,sdhci-5.1") || 129 OF_is_compatible(faa->fa_node, "brcm,bcm2711-emmc2") || 130 OF_is_compatible(faa->fa_node, "brcm,bcm2835-sdhci") || 131 OF_is_compatible(faa->fa_node, "marvell,armada-3700-sdhci") || 132 OF_is_compatible(faa->fa_node, "marvell,armada-ap806-sdhci") || 133 OF_is_compatible(faa->fa_node, "marvell,armada-cp110-sdhci")); 134 } 135 136 void 137 sdhc_fdt_attach(struct device *parent, struct device *self, void *aux) 138 { 139 struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)self; 140 struct fdt_attach_args *faa = aux; 141 struct regmap *rm = NULL; 142 uint32_t reg, phandle, freq, cap = 0; 143 char pad_type[16] = { 0 }; 144 145 if (faa->fa_nreg < 1) { 146 printf(": no registers\n"); 147 return; 148 } 149 150 sc->sc_iot = faa->fa_iot; 151 sc->sc_size = faa->fa_reg[0].size; 152 sc->sc_node = faa->fa_node; 153 154 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 155 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 156 printf(": can't map registers\n"); 157 return; 158 } 159 160 pinctrl_byname(faa->fa_node, "default"); 161 162 clock_set_assigned(faa->fa_node); 163 clock_enable_all(faa->fa_node); 164 reset_deassert_all(faa->fa_node); 165 166 sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_BIO, 167 sdhc_intr, sc, sc->sc.sc_dev.dv_xname); 168 if (sc->sc_ih == NULL) { 169 printf(": can't establish interrupt\n"); 170 goto unmap; 171 } 172 173 if (OF_getproplen(faa->fa_node, "cd-gpios") > 0 || 174 OF_getproplen(faa->fa_node, "non-removable") == 0) { 175 OF_getpropintarray(faa->fa_node, "cd-gpios", sc->sc_gpio, 176 sizeof(sc->sc_gpio)); 177 gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT); 178 sc->sc.sc_card_detect = sdhc_fdt_card_detect; 179 } 180 181 sc->sc_vqmmc = OF_getpropint(sc->sc_node, "vqmmc-supply", 0); 182 183 printf("\n"); 184 185 sc->sc.sc_host = &sc->sc_host; 186 sc->sc.sc_dmat = faa->fa_dmat; 187 188 /* 189 * Arasan controller always uses 1.8V and doesn't like an 190 * explicit switch. 191 */ 192 if (OF_is_compatible(faa->fa_node, "arasan,sdhci-5.1")) 193 sc->sc.sc_signal_voltage = sdhc_fdt_signal_voltage; 194 195 /* 196 * Rockchip RK3399 PHY doesn't like being powered down at low 197 * clock speeds and needs to be powered up explicitly. 198 */ 199 if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-sdhci-5.1")) { 200 /* 201 * The eMMC core's clock multiplier is of no use, so we just 202 * clear it. Also make sure to set the base clock frequency. 203 */ 204 freq = clock_get_frequency(faa->fa_node, "clk_xin"); 205 freq /= 1000 * 1000; /* in MHz */ 206 phandle = OF_getpropint(faa->fa_node, 207 "arasan,soc-ctl-syscon", 0); 208 if (phandle) 209 rm = regmap_byphandle(phandle); 210 if (rm) { 211 regmap_write_4(rm, GRF_EMMCCORE_CON11, 212 GRF_EMMCCORE_CON11_CLOCKMULT_CLR | 213 GRF_EMMCCORE_CON11_CLOCKMULT_VAL(0)); 214 regmap_write_4(rm, GRF_EMMCCORE_CON0_BASECLOCK, 215 GRF_EMMCCORE_CON0_BASECLOCK_CLR | 216 GRF_EMMCCORE_CON0_BASECLOCK_VAL(freq)); 217 } 218 /* Provide base clock frequency for the PHY driver. */ 219 sc->sc_cd.cd_node = faa->fa_node; 220 sc->sc_cd.cd_cookie = sc; 221 sc->sc_cd.cd_get_frequency = sdhc_fdt_get_frequency; 222 clock_register(&sc->sc_cd); 223 /* 224 * Enable the PHY. The PHY should be powered on/off in 225 * the bus_clock function, but it's good enough to just 226 * enable it here right away and to keep it powered on. 227 */ 228 phy_enable(faa->fa_node, "phy_arasan"); 229 sc->sc.sc_flags |= SDHC_F_NOPWR0; 230 231 /* XXX Doesn't work on Rockchip RK3399. */ 232 sc->sc.sc_flags |= SDHC_F_NODDR50; 233 } 234 235 if (OF_is_compatible(faa->fa_node, "brcm,bcm2711-emmc2")) 236 sc->sc.sc_flags |= SDHC_F_NOPWR0; 237 238 if (OF_is_compatible(faa->fa_node, "brcm,bcm2835-sdhci")) { 239 cap = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP; 240 cap |= SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT; 241 242 freq = clock_get_frequency(faa->fa_node, NULL); 243 sc->sc.sc_clkbase = freq / 1000; 244 245 sc->sc.sc_flags |= SDHC_F_32BIT_ACCESS; 246 } 247 248 if (OF_is_compatible(faa->fa_node, "marvell,armada-3700-sdhci") || 249 OF_is_compatible(faa->fa_node, "marvell,armada-ap806-sdhci") || 250 OF_is_compatible(faa->fa_node, "marvell,armada-cp110-sdhci")) { 251 if (OF_is_compatible(faa->fa_node, 252 "marvell,armada-3700-sdhci")) { 253 KASSERT(faa->fa_nreg > 1); 254 if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr, 255 faa->fa_reg[1].size, 0, &sc->sc_pad_ioh)) { 256 printf("%s: can't map registers\n", 257 sc->sc.sc_dev.dv_xname); 258 return; 259 } 260 OF_getprop(faa->fa_node, "marvell,pad-type", 261 pad_type, sizeof(pad_type)); 262 if (!strcmp(pad_type, "fixed-1-8v")) { 263 bus_space_write_4(sc->sc_iot, sc->sc_pad_ioh, 264 ARMADA_3700_SOC_PAD_CTL, 265 ARMADA_3700_SOC_PAD_CTL_1_8V); 266 } else { 267 bus_space_write_4(sc->sc_iot, sc->sc_pad_ioh, 268 ARMADA_3700_SOC_PAD_CTL, 269 ARMADA_3700_SOC_PAD_CTL_3_3V); 270 regulator_set_voltage(sc->sc_vqmmc, 3300000); 271 } 272 } 273 274 cap = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 275 SDHC_CAPABILITIES); 276 if (OF_getpropint(faa->fa_node, "bus-width", 1) != 8) 277 cap &= ~SDHC_8BIT_MODE_SUPP; 278 if (OF_getproplen(faa->fa_node, "no-1-8-v") == 0) 279 cap &= ~SDHC_VOLTAGE_SUPP_1_8V; 280 if (OF_getproplen(faa->fa_node, 281 "marvell,xenon-phy-slow-mode") == 0) 282 sc->sc_slow_mode = 1; 283 284 sc->sc_znr = OF_getpropint(faa->fa_node, 285 "marvell,xenon-phy-znr", 0xf); 286 sc->sc_znr &= XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK; 287 sc->sc_zpr = OF_getpropint(faa->fa_node, 288 "marvell,xenon-phy-zpr", 0xf); 289 sc->sc_zpr &= XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK; 290 sc->sc_sdhc_id = OF_getpropint(faa->fa_node, 291 "marvell,xenon-sdhc-id", 0); 292 293 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 294 XENON_SYS_OP_CTRL); 295 reg |= XENON_SYS_OP_CTRL_SLOT_ENABLE(sc->sc_sdhc_id); 296 reg &= ~XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(sc->sc_sdhc_id); 297 reg &= ~XENON_SYS_OP_CTRL_AUTO_CLKGATE_DISABLE; 298 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 299 XENON_SYS_OP_CTRL, reg); 300 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 301 XENON_SYS_EXT_OP_CTRL); 302 reg |= XENON_SYS_EXT_OP_CTRL_PARALLEL_TRAN(sc->sc_sdhc_id); 303 reg |= XENON_SYS_EXT_OP_CTRL_MASK_CMD_CONFLICT_ERR; 304 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 305 XENON_SYS_EXT_OP_CTRL, reg); 306 307 freq = clock_get_frequency(faa->fa_node, NULL); 308 sc->sc.sc_clkbase = freq / 1000; 309 sc->sc.sc_bus_clock_post = sdhc_fdt_xenon_bus_clock_post; 310 } 311 312 sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_size, 1, cap); 313 return; 314 315 unmap: 316 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size); 317 } 318 319 int 320 sdhc_fdt_card_detect(struct sdhc_softc *ssc) 321 { 322 struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)ssc; 323 324 if (OF_getproplen(sc->sc_node, "non-removable") == 0) 325 return 1; 326 327 return gpio_controller_get_pin(sc->sc_gpio); 328 } 329 330 int 331 sdhc_fdt_signal_voltage(struct sdhc_softc *sc, int signal_voltage) 332 { 333 switch (signal_voltage) { 334 case SDMMC_SIGNAL_VOLTAGE_180: 335 return 0; 336 default: 337 return EINVAL; 338 } 339 } 340 341 uint32_t 342 sdhc_fdt_get_frequency(void *cookie, uint32_t *cells) 343 { 344 struct sdhc_fdt_softc *sc = cookie; 345 return clock_get_frequency(sc->sc_cd.cd_node, "clk_xin"); 346 } 347 348 /* Marvell Xenon */ 349 void 350 sdhc_fdt_xenon_bus_clock_post(struct sdhc_softc *ssc, int freq, int timing) 351 { 352 struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)ssc; 353 uint32_t reg; 354 int i; 355 356 if (freq == 0) 357 return; 358 359 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 360 XENON_EMMC_PHY_PAD_CONTROL); 361 reg |= (XENON_EMMC_PHY_PAD_CONTROL_FC_DQ_RECEN | 362 XENON_EMMC_PHY_PAD_CONTROL_FC_CMD_RECEN | 363 XENON_EMMC_PHY_PAD_CONTROL_FC_QSP_RECEN | 364 XENON_EMMC_PHY_PAD_CONTROL_FC_QSN_RECEN | 365 XENON_EMMC_PHY_PAD_CONTROL_FC_ALL_CMOS_RECVR); 366 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 367 XENON_EMMC_PHY_PAD_CONTROL, reg); 368 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 369 XENON_EMMC_PHY_PAD_CONTROL1); 370 reg &= ~(XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PD | 371 XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PD); 372 reg |= (XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PU | 373 XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PU); 374 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 375 XENON_EMMC_PHY_PAD_CONTROL1, reg); 376 377 if (timing == SDMMC_TIMING_LEGACY) 378 goto phy_init; 379 380 /* TODO: check for SMF_IO_MODE and set flag */ 381 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 382 XENON_EMMC_PHY_TIMING_ADJUST); 383 reg &= ~XENON_EMMC_PHY_TIMING_ADJUST_SDIO_MODE; 384 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 385 XENON_EMMC_PHY_TIMING_ADJUST, reg); 386 387 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 388 XENON_EMMC_PHY_PAD_CONTROL2); 389 reg &= ~(XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK << 390 XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT | 391 XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK << 392 XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT); 393 reg |= sc->sc_zpr << XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT | 394 sc->sc_znr << XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT; 395 396 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL); 397 reg &= ~SDHC_SDCLK_ENABLE; 398 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL, reg); 399 400 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 401 XENON_EMMC_PHY_FUNC_CONTROL); 402 reg &= ~(XENON_EMMC_PHY_FUNC_CONTROL_DQ_DDR_MODE | 403 XENON_EMMC_PHY_FUNC_CONTROL_CMD_DDR_MODE); 404 reg |= XENON_EMMC_PHY_FUNC_CONTROL_DQ_ASYNC_MODE; 405 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 406 XENON_EMMC_PHY_FUNC_CONTROL, reg); 407 408 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL); 409 reg |= SDHC_SDCLK_ENABLE; 410 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL, reg); 411 412 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 413 XENON_SLOT_EMMC_CTRL); 414 reg &= ~(XENON_SLOT_EMMC_CTRL_ENABLE_DATA_STROBE | 415 XENON_SLOT_EMMC_CTRL_ENABLE_RESP_STROBE); 416 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 417 XENON_SLOT_EMMC_CTRL, reg); 418 419 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 420 XENON_EMMC_PHY_PAD_CONTROL1); 421 reg &= ~(XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PD | 422 XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PU); 423 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 424 XENON_EMMC_PHY_PAD_CONTROL1, reg); 425 426 phy_init: 427 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 428 XENON_EMMC_PHY_TIMING_ADJUST); 429 reg |= XENON_EMMC_PHY_TIMING_ADJUST_SAMPL_INV_QSP_PHASE_SELECT; 430 reg &= ~XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE; 431 if (timing == SDMMC_TIMING_LEGACY || 432 timing == SDMMC_TIMING_HIGHSPEED || sc->sc_slow_mode) 433 reg |= XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE; 434 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 435 XENON_EMMC_PHY_TIMING_ADJUST, reg); 436 437 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 438 XENON_EMMC_PHY_TIMING_ADJUST); 439 reg |= XENON_EMMC_PHY_TIMING_ADJUST_INIT; 440 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 441 XENON_EMMC_PHY_TIMING_ADJUST, reg); 442 443 for (i = 1000; i > 0; i--) { 444 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 445 XENON_EMMC_PHY_TIMING_ADJUST); 446 if (!(reg & XENON_EMMC_PHY_TIMING_ADJUST_INIT)) 447 break; 448 delay(10); 449 } 450 if (i == 0) 451 printf("%s: phy initialization timeout\n", 452 sc->sc.sc_dev.dv_xname); 453 454 if (freq > SDMMC_SDCLK_400KHZ) { 455 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 456 XENON_SYS_OP_CTRL); 457 reg |= XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(sc->sc_sdhc_id); 458 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 459 XENON_SYS_OP_CTRL, reg); 460 } 461 } 462