Lines Matching +full:sdhci +full:- +full:caps
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
29 * Marvell Xenon SDHCI controller driver.
54 #include <dev/sdhci/sdhci.h>
55 #include <dev/sdhci/sdhci_xenon.h>
71 return (bus_read_1(sc->mem_res, off)); in sdhci_xenon_read_1()
80 bus_write_1(sc->mem_res, off, val); in sdhci_xenon_write_1()
89 return (bus_read_2(sc->mem_res, off)); in sdhci_xenon_read_2()
98 bus_write_2(sc->mem_res, off, val); in sdhci_xenon_write_2()
107 return bus_read_4(sc->mem_res, off); in sdhci_xenon_read_4()
116 bus_write_4(sc->mem_res, off, val); in sdhci_xenon_write_4()
125 bus_read_multi_4(sc->mem_res, off, data, count); in sdhci_xenon_read_multi_4()
134 bus_write_multi_4(sc->mem_res, off, data, count); in sdhci_xenon_write_multi_4()
142 sdhci_generic_intr(sc->slot); in sdhci_xenon_intr()
150 return (sdhci_generic_get_ro(bus, dev) ^ sc->wp_inverted); in sdhci_xenon_get_ro()
159 if (slot->version < SDHCI_SPEC_300) in sdhci_xenon_set_uhs_timing()
162 mtx_assert(&slot->mtx, MA_OWNED); in sdhci_xenon_set_uhs_timing()
163 ios = &slot->host.ios; in sdhci_xenon_set_uhs_timing()
168 if (ios->clock > SD_SDR50_MAX) { in sdhci_xenon_set_uhs_timing()
169 if (ios->timing == bus_timing_mmc_hs400 || in sdhci_xenon_set_uhs_timing()
170 ios->timing == bus_timing_mmc_hs400es) in sdhci_xenon_set_uhs_timing()
172 else if (ios->timing == bus_timing_mmc_hs200) in sdhci_xenon_set_uhs_timing()
177 else if (ios->clock > SD_SDR25_MAX) in sdhci_xenon_set_uhs_timing()
179 else if (ios->clock > SD_SDR12_MAX) { in sdhci_xenon_set_uhs_timing()
180 if (ios->timing == bus_timing_uhs_ddr50 || in sdhci_xenon_set_uhs_timing()
181 ios->timing == bus_timing_mmc_ddr52) in sdhci_xenon_set_uhs_timing()
185 } else if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) in sdhci_xenon_set_uhs_timing()
198 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST); in sdhci_xenon_phy_init()
200 switch (ios->timing) { in sdhci_xenon_phy_init()
211 if (sc->slow_mode) in sdhci_xenon_phy_init()
213 bus_write_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST, reg); in sdhci_xenon_phy_init()
215 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST); in sdhci_xenon_phy_init()
217 bus_write_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST, reg); in sdhci_xenon_phy_init()
220 for (i = 100; i > 0; i--) { in sdhci_xenon_phy_init()
223 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST); in sdhci_xenon_phy_init()
244 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL); in sdhci_xenon_phy_set()
249 bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL, reg); in sdhci_xenon_phy_set()
252 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1); in sdhci_xenon_phy_set()
255 bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1, reg); in sdhci_xenon_phy_set()
257 if (ios->timing == bus_timing_normal) in sdhci_xenon_phy_set()
261 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST); in sdhci_xenon_phy_set()
263 bus_write_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST, reg); in sdhci_xenon_phy_set()
270 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL2); in sdhci_xenon_phy_set()
272 reg |= ((sc->znr << XENON_ZNR_SHIFT) | sc->zpr); in sdhci_xenon_phy_set()
273 bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL2, reg); in sdhci_xenon_phy_set()
276 reg = bus_read_4(sc->mem_res, SDHCI_CLOCK_CONTROL); in sdhci_xenon_phy_set()
278 bus_write_4(sc->mem_res, SDHCI_CLOCK_CONTROL, reg); in sdhci_xenon_phy_set()
280 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_FUNC_CONTROL); in sdhci_xenon_phy_set()
281 switch (ios->timing) { in sdhci_xenon_phy_set()
297 bus_write_4(sc->mem_res, XENON_EMMC_PHY_FUNC_CONTROL, reg); in sdhci_xenon_phy_set()
300 reg = bus_read_4(sc->mem_res, SDHCI_CLOCK_CONTROL); in sdhci_xenon_phy_set()
302 bus_write_4(sc->mem_res, SDHCI_CLOCK_CONTROL, reg); in sdhci_xenon_phy_set()
304 if (ios->timing == bus_timing_mmc_hs400) in sdhci_xenon_phy_set()
305 bus_write_4(sc->mem_res, XENON_EMMC_PHY_LOGIC_TIMING_ADJUST, in sdhci_xenon_phy_set()
309 reg = bus_read_4(sc->mem_res, XENON_SLOT_EMMC_CTRL); in sdhci_xenon_phy_set()
311 bus_write_4(sc->mem_res, XENON_SLOT_EMMC_CTRL, reg); in sdhci_xenon_phy_set()
314 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1); in sdhci_xenon_phy_set()
316 bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1, reg); in sdhci_xenon_phy_set()
337 ios = &slot->host.ios; in sdhci_xenon_update_ios()
339 switch (ios->power_mode) { in sdhci_xenon_update_ios()
344 device_printf(sc->dev, "Powering down sd/mmc\n"); in sdhci_xenon_update_ios()
346 if (sc->vmmc_supply) in sdhci_xenon_update_ios()
347 regulator_disable(sc->vmmc_supply); in sdhci_xenon_update_ios()
348 if (sc->vqmmc_supply) in sdhci_xenon_update_ios()
349 regulator_disable(sc->vqmmc_supply); in sdhci_xenon_update_ios()
353 device_printf(sc->dev, "Powering up sd/mmc\n"); in sdhci_xenon_update_ios()
355 if (sc->vmmc_supply) in sdhci_xenon_update_ios()
356 regulator_enable(sc->vmmc_supply); in sdhci_xenon_update_ios()
357 if (sc->vqmmc_supply) in sdhci_xenon_update_ios()
358 regulator_enable(sc->vqmmc_supply); in sdhci_xenon_update_ios()
363 if (ios->clock != 0) in sdhci_xenon_update_ios()
366 if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) { in sdhci_xenon_update_ios()
368 reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL); in sdhci_xenon_update_ios()
369 reg |= 1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sc->slot_id); in sdhci_xenon_update_ios()
370 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); in sdhci_xenon_update_ios()
386 if (slot->version < SDHCI_SPEC_300) in sdhci_xenon_switch_vccq()
391 if (sc->vqmmc_supply == NULL && !sc->skip_regulators) in sdhci_xenon_switch_vccq()
396 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2); in sdhci_xenon_switch_vccq()
397 switch (slot->host.ios.vccq) { in sdhci_xenon_switch_vccq()
402 bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2); in sdhci_xenon_switch_vccq()
404 if (!sc->skip_regulators) { in sdhci_xenon_switch_vccq()
406 err = regulator_set_voltage(sc->vqmmc_supply, in sdhci_xenon_switch_vccq()
409 device_printf(sc->dev, in sdhci_xenon_switch_vccq()
410 "Cannot set vqmmc to %d<->%d\n", in sdhci_xenon_switch_vccq()
424 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2); in sdhci_xenon_switch_vccq()
429 if (!(slot->host.caps & MMC_CAP_SIGNALING_180)) { in sdhci_xenon_switch_vccq()
435 bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2); in sdhci_xenon_switch_vccq()
437 if (!sc->skip_regulators) { in sdhci_xenon_switch_vccq()
439 err = regulator_set_voltage(sc->vqmmc_supply, in sdhci_xenon_switch_vccq()
442 device_printf(sc->dev, in sdhci_xenon_switch_vccq()
443 "Cannot set vqmmc to %d<->%d\n", in sdhci_xenon_switch_vccq()
457 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2); in sdhci_xenon_switch_vccq()
479 sc->slot->quirks = val; in sdhci_xenon_parse_prop()
480 sc->znr = XENON_ZNR_DEF_VALUE; in sdhci_xenon_parse_prop()
481 if (device_get_property(dev, "marvell,xenon-phy-znr", in sdhci_xenon_parse_prop()
483 sc->znr = val & XENON_ZNR_MASK; in sdhci_xenon_parse_prop()
484 sc->zpr = XENON_ZPR_DEF_VALUE; in sdhci_xenon_parse_prop()
485 if (device_get_property(dev, "marvell,xenon-phy-zpr", in sdhci_xenon_parse_prop()
487 sc->zpr = val & XENON_ZPR_MASK; in sdhci_xenon_parse_prop()
488 if (device_has_property(dev, "marvell,xenon-phy-slow-mode")) in sdhci_xenon_parse_prop()
489 sc->slow_mode = true; in sdhci_xenon_parse_prop()
499 sc->dev = dev; in sdhci_xenon_attach()
500 sc->slot_id = 0; in sdhci_xenon_attach()
504 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, in sdhci_xenon_attach()
506 if (sc->irq_res == NULL) { in sdhci_xenon_attach()
513 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, in sdhci_xenon_attach()
515 if (sc->mem_res == NULL) { in sdhci_xenon_attach()
517 rman_get_rid(sc->irq_res), sc->irq_res); in sdhci_xenon_attach()
524 sc->slot->max_clk = XENON_MMC_MAX_CLK; in sdhci_xenon_attach()
525 if (sc->slot->host.f_max > 0) in sdhci_xenon_attach()
526 sc->slot->max_clk = sc->slot->host.f_max; in sdhci_xenon_attach()
528 if (sdhci_init_slot(dev, sc->slot, 0)) in sdhci_xenon_attach()
532 sc->slot->host.caps &= ~MMC_CAP_SIGNALING_120; in sdhci_xenon_attach()
535 if (sc->slow_mode) in sdhci_xenon_attach()
536 sc->slot->host.caps &= ~MMC_CAP_SIGNALING_180; in sdhci_xenon_attach()
539 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, in sdhci_xenon_attach()
540 NULL, sdhci_xenon_intr, sc, &sc->intrhand); in sdhci_xenon_attach()
547 reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL); in sdhci_xenon_attach()
549 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); in sdhci_xenon_attach()
552 reg |= (1 << sc->slot_id); in sdhci_xenon_attach()
553 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); in sdhci_xenon_attach()
556 reg = bus_read_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL); in sdhci_xenon_attach()
557 reg |= (1 << sc->slot_id); in sdhci_xenon_attach()
558 bus_write_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL, reg); in sdhci_xenon_attach()
562 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); in sdhci_xenon_attach()
565 reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL); in sdhci_xenon_attach()
566 reg &= ~(1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sc->slot_id)); in sdhci_xenon_attach()
567 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); in sdhci_xenon_attach()
570 reg = bus_read_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL); in sdhci_xenon_attach()
572 bus_write_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL, reg); in sdhci_xenon_attach()
575 sdhci_start_slot(sc->slot); in sdhci_xenon_attach()
580 bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), in sdhci_xenon_attach()
581 sc->irq_res); in sdhci_xenon_attach()
582 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), in sdhci_xenon_attach()
583 sc->mem_res); in sdhci_xenon_attach()
584 free(sc->slot, M_DEVBUF); in sdhci_xenon_attach()
585 sc->slot = NULL; in sdhci_xenon_attach()
596 bus_teardown_intr(dev, sc->irq_res, sc->intrhand); in sdhci_xenon_detach()
597 bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), in sdhci_xenon_detach()
598 sc->irq_res); in sdhci_xenon_detach()
599 sdhci_cleanup_slot(sc->slot); in sdhci_xenon_detach()
600 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), in sdhci_xenon_detach()
601 sc->mem_res); in sdhci_xenon_detach()
602 free(sc->slot, M_DEVBUF); in sdhci_xenon_detach()
603 sc->slot = NULL; in sdhci_xenon_detach()
623 /* SDHCI registers accessors */