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