Index: head/sys/arm/allwinner/aw_mmc.c =================================================================== --- head/sys/arm/allwinner/aw_mmc.c +++ head/sys/arm/allwinner/aw_mmc.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include @@ -49,6 +51,7 @@ #include #include +#include #include #include @@ -122,6 +125,7 @@ int aw_timeout; struct callout aw_timeoutc; struct mmc_host aw_host; + struct mmc_fdt_helper mmc_helper; #ifdef MMCCAM union ccb * ccb; struct cam_devq * devq; @@ -136,9 +140,8 @@ uint32_t aw_intr; uint32_t aw_intr_wait; void * aw_intrhand; - regulator_t aw_reg_vmmc; - regulator_t aw_reg_vqmmc; unsigned int aw_clock; + device_t child; /* Fields required for DMA access. */ bus_addr_t aw_dma_desc_phys; @@ -164,6 +167,7 @@ static int aw_mmc_init(struct aw_mmc_softc *); static void aw_mmc_intr(void *); static int aw_mmc_update_clock(struct aw_mmc_softc *, uint32_t); +static void aw_mmc_helper_cd_handler(device_t, bool); static void aw_mmc_print_error(uint32_t); static int aw_mmc_update_ios(device_t, device_t); @@ -360,6 +364,40 @@ } #endif /* MMCCAM */ +static void +aw_mmc_helper_cd_handler(device_t dev, bool present) +{ + struct aw_mmc_softc *sc; + + sc = device_get_softc(dev); + AW_MMC_LOCK(sc); + if (present) { + if (sc->child == NULL) { + if (bootverbose) + device_printf(sc->aw_dev, "Card inserted\n"); + + sc->child = device_add_child(sc->aw_dev, "mmc", -1); + AW_MMC_UNLOCK(sc); + if (sc->child) { + device_set_ivars(sc->child, sc); + (void)device_probe_and_attach(sc->child); + } + } else + AW_MMC_UNLOCK(sc); + } else { + /* Card isn't present, detach if necessary */ + if (sc->child != NULL) { + if (bootverbose) + device_printf(sc->aw_dev, "Card removed\n"); + + AW_MMC_UNLOCK(sc); + device_delete_child(sc->aw_dev, sc->child); + sc->child = NULL; + } else + AW_MMC_UNLOCK(sc); + } +} + static int aw_mmc_probe(device_t dev) { @@ -377,15 +415,11 @@ static int aw_mmc_attach(device_t dev) { - device_t child; struct aw_mmc_softc *sc; struct sysctl_ctx_list *ctx; struct sysctl_oid_list *tree; - uint32_t bus_width, max_freq; - phandle_t node; int error; - node = ofw_bus_get_node(dev); sc = device_get_softc(dev); sc->aw_dev = dev; @@ -399,7 +433,7 @@ return (ENXIO); } if (bus_setup_intr(dev, sc->aw_res[AW_MMC_IRQRES], - INTR_TYPE_MISC | INTR_MPSAFE, NULL, aw_mmc_intr, sc, + INTR_TYPE_NET | INTR_MPSAFE, NULL, aw_mmc_intr, sc, &sc->aw_intrhand)) { bus_release_resources(dev, aw_mmc_res_spec, sc->aw_res); device_printf(dev, "cannot setup interrupt handler\n"); @@ -463,47 +497,15 @@ goto fail; } - if (OF_getencprop(node, "bus-width", &bus_width, sizeof(uint32_t)) <= 0) - bus_width = 4; - - if (regulator_get_by_ofw_property(dev, 0, "vmmc-supply", - &sc->aw_reg_vmmc) == 0) { - if (bootverbose) - device_printf(dev, "vmmc-supply regulator found\n"); - } - if (regulator_get_by_ofw_property(dev, 0, "vqmmc-supply", - &sc->aw_reg_vqmmc) == 0 && bootverbose) { - if (bootverbose) - device_printf(dev, "vqmmc-supply regulator found\n"); - } - + /* Set some defaults for freq and supported mode */ sc->aw_host.f_min = 400000; - - if (OF_getencprop(node, "max-frequency", &max_freq, - sizeof(uint32_t)) <= 0) - max_freq = 52000000; - sc->aw_host.f_max = max_freq; - + sc->aw_host.f_max = 52000000; sc->aw_host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340; - sc->aw_host.caps = MMC_CAP_HSPEED | MMC_CAP_UHS_SDR12 | - MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | - MMC_CAP_UHS_DDR50 | MMC_CAP_MMC_DDR52; + sc->aw_host.caps |= MMC_CAP_HSPEED | MMC_CAP_SIGNALING_330; + mmc_fdt_parse(dev, 0, &sc->mmc_helper, &sc->aw_host); + mmc_fdt_gpio_setup(dev, 0, &sc->mmc_helper, aw_mmc_helper_cd_handler); - if (sc->aw_reg_vqmmc != NULL) { - if (regulator_check_voltage(sc->aw_reg_vqmmc, 1800000) == 0) - sc->aw_host.caps |= MMC_CAP_SIGNALING_180; - if (regulator_check_voltage(sc->aw_reg_vqmmc, 3300000) == 0) - sc->aw_host.caps |= MMC_CAP_SIGNALING_330; - } else - sc->aw_host.caps |= MMC_CAP_SIGNALING_330; - - if (bus_width >= 4) - sc->aw_host.caps |= MMC_CAP_4_BIT_DATA; - if (bus_width >= 8) - sc->aw_host.caps |= MMC_CAP_8_BIT_DATA; - #ifdef MMCCAM - child = NULL; /* Not used by MMCCAM, need to silence compiler warnings */ sc->ccb = NULL; if ((sc->devq = cam_simq_alloc(1)) == NULL) { goto fail; @@ -530,18 +532,8 @@ } mtx_unlock(&sc->sim_mtx); -#else /* !MMCCAM */ - child = device_add_child(dev, "mmc", -1); - if (child == NULL) { - device_printf(dev, "attaching MMC bus failed!\n"); - goto fail; - } - if (device_probe_and_attach(child) != 0) { - device_printf(dev, "attaching MMC child failed!\n"); - device_delete_child(dev, child); - goto fail; - } #endif /* MMCCAM */ + return (0); fail: @@ -1301,7 +1293,7 @@ sc = device_get_softc(bus); - if (sc->aw_reg_vqmmc == NULL) + if (sc->mmc_helper.vqmmc_supply == NULL) return EOPNOTSUPP; switch (sc->aw_host.ios.vccq) { @@ -1315,7 +1307,7 @@ return EINVAL; } - err = regulator_set_voltage(sc->aw_reg_vqmmc, uvolt, uvolt); + err = regulator_set_voltage(sc->mmc_helper.vqmmc_supply, uvolt, uvolt); if (err != 0) { device_printf(sc->aw_dev, "Cannot set vqmmc to %d<->%d\n", @@ -1360,10 +1352,10 @@ if (bootverbose) device_printf(sc->aw_dev, "Powering down sd/mmc\n"); - if (sc->aw_reg_vmmc) - regulator_disable(sc->aw_reg_vmmc); - if (sc->aw_reg_vqmmc) - regulator_disable(sc->aw_reg_vqmmc); + if (sc->mmc_helper.vmmc_supply) + regulator_disable(sc->mmc_helper.vmmc_supply); + if (sc->mmc_helper.vqmmc_supply) + regulator_disable(sc->mmc_helper.vqmmc_supply); aw_mmc_reset(sc); break; @@ -1371,10 +1363,10 @@ if (bootverbose) device_printf(sc->aw_dev, "Powering up sd/mmc\n"); - if (sc->aw_reg_vmmc) - regulator_enable(sc->aw_reg_vmmc); - if (sc->aw_reg_vqmmc) - regulator_enable(sc->aw_reg_vqmmc); + if (sc->mmc_helper.vmmc_supply) + regulator_enable(sc->mmc_helper.vmmc_supply); + if (sc->mmc_helper.vqmmc_supply) + regulator_enable(sc->mmc_helper.vqmmc_supply); aw_mmc_init(sc); break; }; @@ -1450,8 +1442,11 @@ static int aw_mmc_get_ro(device_t bus, device_t child) { + struct aw_mmc_softc *sc; - return (0); + sc = device_get_softc(bus); + + return (mmc_fdt_gpio_get_readonly(&sc->mmc_helper)); } static int