1 /* $OpenBSD: sdhc_fdt.c,v 1.20 2023/04/08 05:40:54 jsg 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 const 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, "arasan,sdhci-8.9a") || 130 OF_is_compatible(faa->fa_node, "brcm,bcm2711-emmc2") || 131 OF_is_compatible(faa->fa_node, "brcm,bcm2835-sdhci") || 132 OF_is_compatible(faa->fa_node, "marvell,armada-3700-sdhci") || 133 OF_is_compatible(faa->fa_node, "marvell,armada-ap806-sdhci") || 134 OF_is_compatible(faa->fa_node, "marvell,armada-cp110-sdhci")); 135 } 136 137 void 138 sdhc_fdt_attach(struct device *parent, struct device *self, void *aux) 139 { 140 struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)self; 141 struct fdt_attach_args *faa = aux; 142 struct regmap *rm = NULL; 143 uint64_t capmask = 0, capset = 0; 144 uint32_t reg, phandle, freq; 145 char pad_type[16] = { 0 }; 146 147 if (faa->fa_nreg < 1) { 148 printf(": no registers\n"); 149 return; 150 } 151 152 sc->sc_iot = faa->fa_iot; 153 sc->sc_size = faa->fa_reg[0].size; 154 sc->sc_node = faa->fa_node; 155 156 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 157 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 158 printf(": can't map registers\n"); 159 return; 160 } 161 162 pinctrl_byname(faa->fa_node, "default"); 163 164 clock_set_assigned(faa->fa_node); 165 clock_enable_all(faa->fa_node); 166 reset_deassert_all(faa->fa_node); 167 168 sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_BIO, 169 sdhc_intr, sc, sc->sc.sc_dev.dv_xname); 170 if (sc->sc_ih == NULL) { 171 printf(": can't establish interrupt\n"); 172 goto unmap; 173 } 174 175 if (OF_getproplen(faa->fa_node, "cd-gpios") > 0 || 176 OF_getproplen(faa->fa_node, "non-removable") == 0) { 177 OF_getpropintarray(faa->fa_node, "cd-gpios", sc->sc_gpio, 178 sizeof(sc->sc_gpio)); 179 gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT); 180 sc->sc.sc_card_detect = sdhc_fdt_card_detect; 181 } 182 183 sc->sc_vqmmc = OF_getpropint(sc->sc_node, "vqmmc-supply", 0); 184 185 printf("\n"); 186 187 sc->sc.sc_host = &sc->sc_host; 188 sc->sc.sc_dmat = faa->fa_dmat; 189 190 /* 191 * Arasan controller always uses 1.8V and doesn't like an 192 * explicit switch. 193 */ 194 if (OF_is_compatible(faa->fa_node, "arasan,sdhci-5.1")) 195 sc->sc.sc_signal_voltage = sdhc_fdt_signal_voltage; 196 197 /* 198 * Rockchip RK3399 PHY doesn't like being powered down at low 199 * clock speeds and needs to be powered up explicitly. 200 */ 201 if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-sdhci-5.1")) { 202 /* 203 * The eMMC core's clock multiplier is of no use, so we just 204 * clear it. Also make sure to set the base clock frequency. 205 */ 206 freq = clock_get_frequency(faa->fa_node, "clk_xin"); 207 freq /= 1000 * 1000; /* in MHz */ 208 phandle = OF_getpropint(faa->fa_node, 209 "arasan,soc-ctl-syscon", 0); 210 if (phandle) 211 rm = regmap_byphandle(phandle); 212 if (rm) { 213 regmap_write_4(rm, GRF_EMMCCORE_CON11, 214 GRF_EMMCCORE_CON11_CLOCKMULT_CLR | 215 GRF_EMMCCORE_CON11_CLOCKMULT_VAL(0)); 216 regmap_write_4(rm, GRF_EMMCCORE_CON0_BASECLOCK, 217 GRF_EMMCCORE_CON0_BASECLOCK_CLR | 218 GRF_EMMCCORE_CON0_BASECLOCK_VAL(freq)); 219 } 220 /* Provide base clock frequency for the PHY driver. */ 221 sc->sc_cd.cd_node = faa->fa_node; 222 sc->sc_cd.cd_cookie = sc; 223 sc->sc_cd.cd_get_frequency = sdhc_fdt_get_frequency; 224 clock_register(&sc->sc_cd); 225 /* 226 * Enable the PHY. The PHY should be powered on/off in 227 * the bus_clock function, but it's good enough to just 228 * enable it here right away and to keep it powered on. 229 */ 230 phy_enable(faa->fa_node, "phy_arasan"); 231 sc->sc.sc_flags |= SDHC_F_NOPWR0; 232 233 /* XXX Doesn't work on Rockchip RK3399. */ 234 capmask |= (uint64_t)SDHC_DDR50_SUPP << 32; 235 } 236 237 if (OF_is_compatible(faa->fa_node, "arasan,sdhci-8.9a")) { 238 freq = clock_get_frequency(faa->fa_node, "clk_xin"); 239 sc->sc.sc_clkbase = freq / 1000; 240 } 241 242 if (OF_is_compatible(faa->fa_node, "brcm,bcm2711-emmc2")) 243 sc->sc.sc_flags |= SDHC_F_NOPWR0; 244 245 if (OF_is_compatible(faa->fa_node, "brcm,bcm2835-sdhci")) { 246 capmask = 0xffffffff; 247 capset = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP; 248 capset |= SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT; 249 250 freq = clock_get_frequency(faa->fa_node, NULL); 251 sc->sc.sc_clkbase = freq / 1000; 252 253 sc->sc.sc_flags |= SDHC_F_32BIT_ACCESS; 254 sc->sc.sc_flags |= SDHC_F_NO_HS_BIT; 255 } 256 257 if (OF_is_compatible(faa->fa_node, "marvell,armada-3700-sdhci") || 258 OF_is_compatible(faa->fa_node, "marvell,armada-ap806-sdhci") || 259 OF_is_compatible(faa->fa_node, "marvell,armada-cp110-sdhci")) { 260 if (OF_is_compatible(faa->fa_node, 261 "marvell,armada-3700-sdhci")) { 262 KASSERT(faa->fa_nreg > 1); 263 if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr, 264 faa->fa_reg[1].size, 0, &sc->sc_pad_ioh)) { 265 printf("%s: can't map registers\n", 266 sc->sc.sc_dev.dv_xname); 267 return; 268 } 269 OF_getprop(faa->fa_node, "marvell,pad-type", 270 pad_type, sizeof(pad_type)); 271 if (!strcmp(pad_type, "fixed-1-8v")) { 272 bus_space_write_4(sc->sc_iot, sc->sc_pad_ioh, 273 ARMADA_3700_SOC_PAD_CTL, 274 ARMADA_3700_SOC_PAD_CTL_1_8V); 275 } else { 276 bus_space_write_4(sc->sc_iot, sc->sc_pad_ioh, 277 ARMADA_3700_SOC_PAD_CTL, 278 ARMADA_3700_SOC_PAD_CTL_3_3V); 279 regulator_set_voltage(sc->sc_vqmmc, 3300000); 280 } 281 } 282 283 if (OF_getpropint(faa->fa_node, "bus-width", 1) != 8) 284 capmask |= SDHC_8BIT_MODE_SUPP; 285 if (OF_getproplen(faa->fa_node, "no-1-8-v") == 0) { 286 capmask |= SDHC_VOLTAGE_SUPP_1_8V; 287 capmask |= (uint64_t)SDHC_DDR50_SUPP << 32; 288 } 289 if (OF_getproplen(faa->fa_node, 290 "marvell,xenon-phy-slow-mode") == 0) 291 sc->sc_slow_mode = 1; 292 293 sc->sc_znr = OF_getpropint(faa->fa_node, 294 "marvell,xenon-phy-znr", 0xf); 295 sc->sc_znr &= XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK; 296 sc->sc_zpr = OF_getpropint(faa->fa_node, 297 "marvell,xenon-phy-zpr", 0xf); 298 sc->sc_zpr &= XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK; 299 sc->sc_sdhc_id = OF_getpropint(faa->fa_node, 300 "marvell,xenon-sdhc-id", 0); 301 302 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 303 XENON_SYS_OP_CTRL); 304 reg |= XENON_SYS_OP_CTRL_SLOT_ENABLE(sc->sc_sdhc_id); 305 reg &= ~XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(sc->sc_sdhc_id); 306 reg &= ~XENON_SYS_OP_CTRL_AUTO_CLKGATE_DISABLE; 307 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 308 XENON_SYS_OP_CTRL, reg); 309 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 310 XENON_SYS_EXT_OP_CTRL); 311 reg |= XENON_SYS_EXT_OP_CTRL_PARALLEL_TRAN(sc->sc_sdhc_id); 312 reg |= XENON_SYS_EXT_OP_CTRL_MASK_CMD_CONFLICT_ERR; 313 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 314 XENON_SYS_EXT_OP_CTRL, reg); 315 316 freq = clock_get_frequency(faa->fa_node, NULL); 317 sc->sc.sc_clkbase = freq / 1000; 318 sc->sc.sc_bus_clock_post = sdhc_fdt_xenon_bus_clock_post; 319 } 320 321 sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_size, 1, 322 capmask, capset); 323 return; 324 325 unmap: 326 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size); 327 } 328 329 int 330 sdhc_fdt_card_detect(struct sdhc_softc *ssc) 331 { 332 struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)ssc; 333 334 if (OF_getproplen(sc->sc_node, "non-removable") == 0) 335 return 1; 336 337 return gpio_controller_get_pin(sc->sc_gpio); 338 } 339 340 int 341 sdhc_fdt_signal_voltage(struct sdhc_softc *sc, int signal_voltage) 342 { 343 switch (signal_voltage) { 344 case SDMMC_SIGNAL_VOLTAGE_180: 345 return 0; 346 default: 347 return EINVAL; 348 } 349 } 350 351 uint32_t 352 sdhc_fdt_get_frequency(void *cookie, uint32_t *cells) 353 { 354 struct sdhc_fdt_softc *sc = cookie; 355 return clock_get_frequency(sc->sc_cd.cd_node, "clk_xin"); 356 } 357 358 /* Marvell Xenon */ 359 void 360 sdhc_fdt_xenon_bus_clock_post(struct sdhc_softc *ssc, int freq, int timing) 361 { 362 struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)ssc; 363 uint32_t reg; 364 int i; 365 366 if (freq == 0) 367 return; 368 369 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 370 XENON_EMMC_PHY_PAD_CONTROL); 371 reg |= (XENON_EMMC_PHY_PAD_CONTROL_FC_DQ_RECEN | 372 XENON_EMMC_PHY_PAD_CONTROL_FC_CMD_RECEN | 373 XENON_EMMC_PHY_PAD_CONTROL_FC_QSP_RECEN | 374 XENON_EMMC_PHY_PAD_CONTROL_FC_QSN_RECEN | 375 XENON_EMMC_PHY_PAD_CONTROL_FC_ALL_CMOS_RECVR); 376 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 377 XENON_EMMC_PHY_PAD_CONTROL, reg); 378 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 379 XENON_EMMC_PHY_PAD_CONTROL1); 380 reg &= ~(XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PD | 381 XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PD); 382 reg |= (XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PU | 383 XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PU); 384 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 385 XENON_EMMC_PHY_PAD_CONTROL1, reg); 386 387 if (timing == SDMMC_TIMING_LEGACY) 388 goto phy_init; 389 390 /* TODO: check for SMF_IO_MODE and set flag */ 391 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 392 XENON_EMMC_PHY_TIMING_ADJUST); 393 reg &= ~XENON_EMMC_PHY_TIMING_ADJUST_SDIO_MODE; 394 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 395 XENON_EMMC_PHY_TIMING_ADJUST, reg); 396 397 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 398 XENON_EMMC_PHY_PAD_CONTROL2); 399 reg &= ~(XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK << 400 XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT | 401 XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK << 402 XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT); 403 reg |= sc->sc_zpr << XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT | 404 sc->sc_znr << XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT; 405 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 406 XENON_EMMC_PHY_PAD_CONTROL2, 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_EMMC_PHY_FUNC_CONTROL); 414 reg &= ~(XENON_EMMC_PHY_FUNC_CONTROL_DQ_DDR_MODE | 415 XENON_EMMC_PHY_FUNC_CONTROL_CMD_DDR_MODE); 416 reg |= XENON_EMMC_PHY_FUNC_CONTROL_DQ_ASYNC_MODE; 417 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 418 XENON_EMMC_PHY_FUNC_CONTROL, reg); 419 420 reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL); 421 reg |= SDHC_SDCLK_ENABLE; 422 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL, reg); 423 424 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 425 XENON_SLOT_EMMC_CTRL); 426 reg &= ~(XENON_SLOT_EMMC_CTRL_ENABLE_DATA_STROBE | 427 XENON_SLOT_EMMC_CTRL_ENABLE_RESP_STROBE); 428 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 429 XENON_SLOT_EMMC_CTRL, reg); 430 431 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 432 XENON_EMMC_PHY_PAD_CONTROL1); 433 reg &= ~(XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PD | 434 XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PU); 435 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 436 XENON_EMMC_PHY_PAD_CONTROL1, reg); 437 438 phy_init: 439 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 440 XENON_EMMC_PHY_TIMING_ADJUST); 441 reg |= XENON_EMMC_PHY_TIMING_ADJUST_SAMPL_INV_QSP_PHASE_SELECT; 442 reg &= ~XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE; 443 if (timing == SDMMC_TIMING_LEGACY || 444 timing == SDMMC_TIMING_HIGHSPEED || sc->sc_slow_mode) 445 reg |= XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE; 446 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 447 XENON_EMMC_PHY_TIMING_ADJUST, reg); 448 449 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 450 XENON_EMMC_PHY_TIMING_ADJUST); 451 reg |= XENON_EMMC_PHY_TIMING_ADJUST_INIT; 452 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 453 XENON_EMMC_PHY_TIMING_ADJUST, reg); 454 455 for (i = 1000; i > 0; i--) { 456 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 457 XENON_EMMC_PHY_TIMING_ADJUST); 458 if (!(reg & XENON_EMMC_PHY_TIMING_ADJUST_INIT)) 459 break; 460 delay(10); 461 } 462 if (i == 0) 463 printf("%s: phy initialization timeout\n", 464 sc->sc.sc_dev.dv_xname); 465 466 if (freq > SDMMC_SDCLK_400KHZ) { 467 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 468 XENON_SYS_OP_CTRL); 469 reg |= XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(sc->sc_sdhc_id); 470 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 471 XENON_SYS_OP_CTRL, reg); 472 } 473 } 474