static int sdhci_sprd_probe(struct platform_device *pdev) { struct sdhci_host *host; struct sdhci_sprd_host *sprd_host; struct clk *clk; int ret = 0; host = sdhci_pltfm_init(pdev, &sdhci_sprd_pdata, sizeof(*sprd_host)); if (IS_ERR(host)) return PTR_ERR(host); host->dma_mask = DMA_BIT_MASK(64); pdev->dev.dma_mask = &host->dma_mask; host->mmc_host_ops.request = sdhci_sprd_request; host->mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_ERASE | MMC_CAP_CMD23; ret = mmc_of_parse(host->mmc); if (ret) goto pltfm_free; sprd_host = TO_SPRD_HOST(host); clk = devm_clk_get(&pdev->dev, "sdio"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto pltfm_free; } sprd_host->clk_sdio = clk; sprd_host->base_rate = clk_get_rate(sprd_host->clk_sdio); if (!sprd_host->base_rate) sprd_host->base_rate = SDHCI_SPRD_CLK_DEF_RATE; clk = devm_clk_get(&pdev->dev, "enable"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto pltfm_free; } sprd_host->clk_enable = clk; ret = clk_prepare_enable(sprd_host->clk_sdio); if (ret) goto pltfm_free; clk_prepare_enable(sprd_host->clk_enable); if (ret) goto clk_disable; sdhci_sprd_init_config(host); host->version = sdhci_readw(host, SDHCI_HOST_VERSION); sprd_host->version = ((host->version & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT); pm_runtime_get_noresume(&pdev->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_use_autosuspend(&pdev->dev); pm_suspend_ignore_children(&pdev->dev, 1); sdhci_enable_v4_mode(host); ret = sdhci_setup_host(host); if (ret) goto pm_runtime_disable; sprd_host->flags = host->flags; ret = __sdhci_add_host(host); if (ret) goto err_cleanup_host; pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); return 0; err_cleanup_host: sdhci_cleanup_host(host); pm_runtime_disable: pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); clk_disable_unprepare(sprd_host->clk_enable); clk_disable: clk_disable_unprepare(sprd_host->clk_sdio); pltfm_free: sdhci_pltfm_free(pdev); return ret; }
static int sdhci_tegra_probe(struct platform_device *pdev) { const struct of_device_id *match; const struct sdhci_tegra_soc_data *soc_data; struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct sdhci_tegra *tegra_host; struct clk *clk; int rc; match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); if (!match) return -EINVAL; soc_data = match->data; host = sdhci_pltfm_init(pdev, soc_data->pdata, sizeof(*tegra_host)); if (IS_ERR(host)) return PTR_ERR(host); pltfm_host = sdhci_priv(host); tegra_host = sdhci_pltfm_priv(pltfm_host); tegra_host->ddr_signaling = false; tegra_host->pad_calib_required = false; tegra_host->pad_control_available = false; tegra_host->soc_data = soc_data; if (soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL) { rc = tegra_sdhci_init_pinctrl_info(&pdev->dev, tegra_host); if (rc == 0) host->mmc_host_ops.start_signal_voltage_switch = sdhci_tegra_start_signal_voltage_switch; } /* Hook to periodically rerun pad calibration */ if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) host->mmc_host_ops.request = tegra_sdhci_request; host->mmc_host_ops.hs400_enhanced_strobe = tegra_sdhci_hs400_enhanced_strobe; rc = mmc_of_parse(host->mmc); if (rc) goto err_parse_dt; if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) host->mmc->caps |= MMC_CAP_1_8V_DDR; tegra_sdhci_parse_pad_autocal_dt(host); tegra_sdhci_parse_tap_and_trim(host); tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power", GPIOD_OUT_HIGH); if (IS_ERR(tegra_host->power_gpio)) { rc = PTR_ERR(tegra_host->power_gpio); goto err_power_req; } clk = devm_clk_get(mmc_dev(host->mmc), NULL); if (IS_ERR(clk)) { dev_err(mmc_dev(host->mmc), "clk err\n"); rc = PTR_ERR(clk); goto err_clk_get; } clk_prepare_enable(clk); pltfm_host->clk = clk; tegra_host->rst = devm_reset_control_get_exclusive(&pdev->dev, "sdhci"); if (IS_ERR(tegra_host->rst)) { rc = PTR_ERR(tegra_host->rst); dev_err(&pdev->dev, "failed to get reset control: %d\n", rc); goto err_rst_get; } rc = reset_control_assert(tegra_host->rst); if (rc) goto err_rst_get; usleep_range(2000, 4000); rc = reset_control_deassert(tegra_host->rst); if (rc) goto err_rst_get; usleep_range(2000, 4000); rc = sdhci_add_host(host); if (rc) goto err_add_host; return 0; err_add_host: reset_control_assert(tegra_host->rst); err_rst_get: clk_disable_unprepare(pltfm_host->clk); err_clk_get: err_power_req: err_parse_dt: sdhci_pltfm_free(pdev); return rc; }
static int sdhci_pxav3_probe(struct platform_device *pdev) { struct sdhci_pltfm_host *pltfm_host; struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; struct sdhci_host *host = NULL; struct sdhci_pxa *pxa = NULL; const struct of_device_id *match; int ret; struct clk *clk; pxa = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_pxa), GFP_KERNEL); if (!pxa) return -ENOMEM; host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, 0); if (IS_ERR(host)) return PTR_ERR(host); /* enable 1/8V DDR capable */ host->mmc->caps |= MMC_CAP_1_8V_DDR; if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) { ret = armada_38x_quirks(pdev, host); if (ret < 0) goto err_clk_get; ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info()); if (ret < 0) goto err_mbus_win; } pltfm_host = sdhci_priv(host); pltfm_host->priv = pxa; clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(clk); goto err_clk_get; } pltfm_host->clk = clk; clk_prepare_enable(clk); match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev); if (match) { ret = mmc_of_parse(host->mmc); if (ret) goto err_of_parse; sdhci_get_of_property(pdev); pdata = pxav3_get_mmc_pdata(dev); } else if (pdata) { /* on-chip device */ if (pdata->flags & PXA_FLAG_CARD_PERMANENT) host->mmc->caps |= MMC_CAP_NONREMOVABLE; /* If slot design supports 8 bit data, indicate this to MMC. */ if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) host->mmc->caps |= MMC_CAP_8_BIT_DATA; if (pdata->quirks) host->quirks |= pdata->quirks; if (pdata->quirks2) host->quirks2 |= pdata->quirks2; if (pdata->host_caps) host->mmc->caps |= pdata->host_caps; if (pdata->host_caps2) host->mmc->caps2 |= pdata->host_caps2; if (pdata->pm_caps) host->mmc->pm_caps |= pdata->pm_caps; if (gpio_is_valid(pdata->ext_cd_gpio)) { ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio, 0); if (ret) { dev_err(mmc_dev(host->mmc), "failed to allocate card detect gpio\n"); goto err_cd_req; } } } pm_runtime_get_noresume(&pdev->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_suspend_ignore_children(&pdev->dev, 1); ret = sdhci_add_host(host); if (ret) { dev_err(&pdev->dev, "failed to add host\n"); goto err_add_host; } platform_set_drvdata(pdev, host); if (host->mmc->pm_caps & MMC_PM_KEEP_POWER) { device_init_wakeup(&pdev->dev, 1); host->mmc->pm_flags |= MMC_PM_WAKE_SDIO_IRQ; } else { device_init_wakeup(&pdev->dev, 0); } pm_runtime_put_autosuspend(&pdev->dev); return 0; err_add_host: pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); err_of_parse: err_cd_req: clk_disable_unprepare(clk); err_clk_get: err_mbus_win: sdhci_pltfm_free(pdev); return ret; }
static int sdhci_at91_probe(struct platform_device *pdev) { const struct of_device_id *match; const struct sdhci_pltfm_data *soc_data; struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct sdhci_at91_priv *priv; unsigned int caps0, caps1; unsigned int clk_base, clk_mul; unsigned int gck_rate, real_gck_rate; int ret; unsigned int preset_div; match = of_match_device(sdhci_at91_dt_match, &pdev->dev); if (!match) return -EINVAL; soc_data = match->data; host = sdhci_pltfm_init(pdev, soc_data, sizeof(*priv)); if (IS_ERR(host)) return PTR_ERR(host); pltfm_host = sdhci_priv(host); priv = sdhci_pltfm_priv(pltfm_host); priv->mainck = devm_clk_get(&pdev->dev, "baseclk"); if (IS_ERR(priv->mainck)) { dev_err(&pdev->dev, "failed to get baseclk\n"); return PTR_ERR(priv->mainck); } priv->hclock = devm_clk_get(&pdev->dev, "hclock"); if (IS_ERR(priv->hclock)) { dev_err(&pdev->dev, "failed to get hclock\n"); return PTR_ERR(priv->hclock); } priv->gck = devm_clk_get(&pdev->dev, "multclk"); if (IS_ERR(priv->gck)) { dev_err(&pdev->dev, "failed to get multclk\n"); return PTR_ERR(priv->gck); } /* * The mult clock is provided by as a generated clock by the PMC * controller. In order to set the rate of gck, we have to get the * base clock rate and the clock mult from capabilities. */ clk_prepare_enable(priv->hclock); caps0 = readl(host->ioaddr + SDHCI_CAPABILITIES); caps1 = readl(host->ioaddr + SDHCI_CAPABILITIES_1); clk_base = (caps0 & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; clk_mul = (caps1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; gck_rate = clk_base * 1000000 * (clk_mul + 1); ret = clk_set_rate(priv->gck, gck_rate); if (ret < 0) { dev_err(&pdev->dev, "failed to set gck"); goto hclock_disable_unprepare; } /* * We need to check if we have the requested rate for gck because in * some cases this rate could be not supported. If it happens, the rate * is the closest one gck can provide. We have to update the value * of clk mul. */ real_gck_rate = clk_get_rate(priv->gck); if (real_gck_rate != gck_rate) { clk_mul = real_gck_rate / (clk_base * 1000000) - 1; caps1 &= (~SDHCI_CLOCK_MUL_MASK); caps1 |= ((clk_mul << SDHCI_CLOCK_MUL_SHIFT) & SDHCI_CLOCK_MUL_MASK); /* Set capabilities in r/w mode. */ writel(SDMMC_CACR_KEY | SDMMC_CACR_CAPWREN, host->ioaddr + SDMMC_CACR); writel(caps1, host->ioaddr + SDHCI_CAPABILITIES_1); /* Set capabilities in ro mode. */ writel(0, host->ioaddr + SDMMC_CACR); dev_info(&pdev->dev, "update clk mul to %u as gck rate is %u Hz\n", clk_mul, real_gck_rate); } /* * We have to set preset values because it depends on the clk_mul * value. Moreover, SDR104 is supported in a degraded mode since the * maximum sd clock value is 120 MHz instead of 208 MHz. For that * reason, we need to use presets to support SDR104. */ preset_div = DIV_ROUND_UP(real_gck_rate, 24000000) - 1; writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div, host->ioaddr + SDHCI_PRESET_FOR_SDR12); preset_div = DIV_ROUND_UP(real_gck_rate, 50000000) - 1; writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div, host->ioaddr + SDHCI_PRESET_FOR_SDR25); preset_div = DIV_ROUND_UP(real_gck_rate, 100000000) - 1; writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div, host->ioaddr + SDHCI_PRESET_FOR_SDR50); preset_div = DIV_ROUND_UP(real_gck_rate, 120000000) - 1; writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div, host->ioaddr + SDHCI_PRESET_FOR_SDR104); preset_div = DIV_ROUND_UP(real_gck_rate, 50000000) - 1; writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div, host->ioaddr + SDHCI_PRESET_FOR_DDR50); clk_prepare_enable(priv->mainck); clk_prepare_enable(priv->gck); ret = mmc_of_parse(host->mmc); if (ret) goto clocks_disable_unprepare; sdhci_get_of_property(pdev); pm_runtime_get_noresume(&pdev->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_use_autosuspend(&pdev->dev); ret = sdhci_add_host(host); if (ret) goto pm_runtime_disable; /* * When calling sdhci_runtime_suspend_host(), the sdhci layer makes * the assumption that all the clocks of the controller are disabled. * It means we can't get irq from it when it is runtime suspended. * For that reason, it is not planned to wake-up on a card detect irq * from the controller. * If we want to use runtime PM and to be able to wake-up on card * insertion, we have to use a GPIO for the card detection or we can * use polling. Be aware that using polling will resume/suspend the * controller between each attempt. * Disable SDHCI_QUIRK_BROKEN_CARD_DETECTION to be sure nobody tries * to enable polling via device tree with broken-cd property. */ if (!(host->mmc->caps & MMC_CAP_NONREMOVABLE) && mmc_gpio_get_cd(host->mmc) < 0) { host->mmc->caps |= MMC_CAP_NEEDS_POLL; host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; } pm_runtime_put_autosuspend(&pdev->dev); return 0; pm_runtime_disable: pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); clocks_disable_unprepare: clk_disable_unprepare(priv->gck); clk_disable_unprepare(priv->mainck); hclock_disable_unprepare: clk_disable_unprepare(priv->hclock); sdhci_pltfm_free(pdev); return ret; }
static int sdhci_msm_probe(struct platform_device *pdev) { struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct sdhci_msm_host *msm_host; struct resource *core_memres; struct clk *clk; int ret; u16 host_version, core_minor; u32 core_version, config; u8 core_major; host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host)); if (IS_ERR(host)) return PTR_ERR(host); host->sdma_boundary = 0; pltfm_host = sdhci_priv(host); msm_host = sdhci_pltfm_priv(pltfm_host); msm_host->mmc = host->mmc; msm_host->pdev = pdev; ret = mmc_of_parse(host->mmc); if (ret) goto pltfm_free; sdhci_get_of_property(pdev); msm_host->saved_tuning_phase = INVALID_TUNING_PHASE; /* Setup SDCC bus voter clock. */ msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); if (!IS_ERR(msm_host->bus_clk)) { /* Vote for max. clk rate for max. performance */ ret = clk_set_rate(msm_host->bus_clk, INT_MAX); if (ret) goto pltfm_free; ret = clk_prepare_enable(msm_host->bus_clk); if (ret) goto pltfm_free; } /* Setup main peripheral bus clock */ clk = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "Peripheral clk setup failed (%d)\n", ret); goto bus_clk_disable; } msm_host->bulk_clks[1].clk = clk; /* Setup SDC MMC clock */ clk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret); goto bus_clk_disable; } msm_host->bulk_clks[0].clk = clk; /* Vote for maximum clock rate for maximum performance */ ret = clk_set_rate(clk, INT_MAX); if (ret) dev_warn(&pdev->dev, "core clock boost failed\n"); clk = devm_clk_get(&pdev->dev, "cal"); if (IS_ERR(clk)) clk = NULL; msm_host->bulk_clks[2].clk = clk; clk = devm_clk_get(&pdev->dev, "sleep"); if (IS_ERR(clk)) clk = NULL; msm_host->bulk_clks[3].clk = clk; ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks), msm_host->bulk_clks); if (ret) goto bus_clk_disable; /* * xo clock is needed for FLL feature of cm_dll. * In case if xo clock is not mentioned in DT, warn and proceed. */ msm_host->xo_clk = devm_clk_get(&pdev->dev, "xo"); if (IS_ERR(msm_host->xo_clk)) { ret = PTR_ERR(msm_host->xo_clk); dev_warn(&pdev->dev, "TCXO clk not present (%d)\n", ret); } core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1); msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres); if (IS_ERR(msm_host->core_mem)) { dev_err(&pdev->dev, "Failed to remap registers\n"); ret = PTR_ERR(msm_host->core_mem); goto clk_disable; } /* Reset the vendor spec register to power on reset state */ writel_relaxed(CORE_VENDOR_SPEC_POR_VAL, host->ioaddr + CORE_VENDOR_SPEC); /* Set HC_MODE_EN bit in HC_MODE register */ writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE)); config = readl_relaxed(msm_host->core_mem + CORE_HC_MODE); config |= FF_CLK_SW_RST_DIS; writel_relaxed(config, msm_host->core_mem + CORE_HC_MODE); host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n", host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT)); core_version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION); core_major = (core_version & CORE_VERSION_MAJOR_MASK) >> CORE_VERSION_MAJOR_SHIFT; core_minor = core_version & CORE_VERSION_MINOR_MASK; dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n", core_version, core_major, core_minor); if (core_major == 1 && core_minor >= 0x42) msm_host->use_14lpp_dll_reset = true; /* * SDCC 5 controller with major version 1, minor version 0x34 and later * with HS 400 mode support will use CM DLL instead of CDC LP 533 DLL. */ if (core_major == 1 && core_minor < 0x34) msm_host->use_cdclp533 = true; /* * Support for some capabilities is not advertised by newer * controller versions and must be explicitly enabled. */ if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) { config = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES); config |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT; writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC_CAPABILITIES0); } /* * Power on reset state may trigger power irq if previous status of * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq * interrupt in GIC, any pending power irq interrupt should be * acknowledged. Otherwise power irq interrupt handler would be * fired prematurely. */ sdhci_msm_handle_pwr_irq(host, 0); /* * Ensure that above writes are propogated before interrupt enablement * in GIC. */ mb(); /* Setup IRQ for handling power/voltage tasks with PMIC */ msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq"); if (msm_host->pwr_irq < 0) { dev_err(&pdev->dev, "Get pwr_irq failed (%d)\n", msm_host->pwr_irq); ret = msm_host->pwr_irq; goto clk_disable; } sdhci_msm_init_pwr_irq_wait(msm_host); /* Enable pwr irq interrupts */ writel_relaxed(INT_MASK, msm_host->core_mem + CORE_PWRCTL_MASK); ret = devm_request_threaded_irq(&pdev->dev, msm_host->pwr_irq, NULL, sdhci_msm_pwr_irq, IRQF_ONESHOT, dev_name(&pdev->dev), host); if (ret) { dev_err(&pdev->dev, "Request IRQ failed (%d)\n", ret); goto clk_disable; } pm_runtime_get_noresume(&pdev->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, MSM_MMC_AUTOSUSPEND_DELAY_MS); pm_runtime_use_autosuspend(&pdev->dev); host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning; ret = sdhci_add_host(host); if (ret) goto pm_runtime_disable; pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); return 0; pm_runtime_disable: pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); clk_disable: clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks), msm_host->bulk_clks); bus_clk_disable: if (!IS_ERR(msm_host->bus_clk)) clk_disable_unprepare(msm_host->bus_clk); pltfm_free: sdhci_pltfm_free(pdev); return ret; }
static int sdhci_msm_probe(struct platform_device *pdev) { struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct sdhci_msm_host *msm_host; struct resource *core_memres; int ret; u16 host_version, core_minor; u32 core_version, caps; u8 core_major; host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host)); if (IS_ERR(host)) return PTR_ERR(host); pltfm_host = sdhci_priv(host); msm_host = sdhci_pltfm_priv(pltfm_host); msm_host->mmc = host->mmc; msm_host->pdev = pdev; ret = mmc_of_parse(host->mmc); if (ret) goto pltfm_free; sdhci_get_of_property(pdev); /* Setup SDCC bus voter clock. */ msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); if (!IS_ERR(msm_host->bus_clk)) { /* Vote for max. clk rate for max. performance */ ret = clk_set_rate(msm_host->bus_clk, INT_MAX); if (ret) goto pltfm_free; ret = clk_prepare_enable(msm_host->bus_clk); if (ret) goto pltfm_free; } /* Setup main peripheral bus clock */ msm_host->pclk = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(msm_host->pclk)) { ret = PTR_ERR(msm_host->pclk); dev_err(&pdev->dev, "Perpheral clk setup failed (%d)\n", ret); goto bus_clk_disable; } ret = clk_prepare_enable(msm_host->pclk); if (ret) goto bus_clk_disable; /* Setup SDC MMC clock */ msm_host->clk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(msm_host->clk)) { ret = PTR_ERR(msm_host->clk); dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret); goto pclk_disable; } /* Vote for maximum clock rate for maximum performance */ ret = clk_set_rate(msm_host->clk, INT_MAX); if (ret) dev_warn(&pdev->dev, "core clock boost failed\n"); ret = clk_prepare_enable(msm_host->clk); if (ret) goto pclk_disable; core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1); msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres); if (IS_ERR(msm_host->core_mem)) { dev_err(&pdev->dev, "Failed to remap registers\n"); ret = PTR_ERR(msm_host->core_mem); goto clk_disable; } /* Reset the core and Enable SDHC mode */ writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) | CORE_SW_RST, msm_host->core_mem + CORE_POWER); /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */ usleep_range(1000, 5000); if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) { dev_err(&pdev->dev, "Stuck in reset\n"); ret = -ETIMEDOUT; goto clk_disable; } /* Set HC_MODE_EN bit in HC_MODE register */ writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE)); host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n", host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT)); core_version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION); core_major = (core_version & CORE_VERSION_MAJOR_MASK) >> CORE_VERSION_MAJOR_SHIFT; core_minor = core_version & CORE_VERSION_MINOR_MASK; dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n", core_version, core_major, core_minor); /* * Support for some capabilities is not advertised by newer * controller versions and must be explicitly enabled. */ if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) { caps = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES); caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT; writel_relaxed(caps, host->ioaddr + CORE_VENDOR_SPEC_CAPABILITIES0); } ret = sdhci_add_host(host); if (ret) goto clk_disable; return 0; clk_disable: clk_disable_unprepare(msm_host->clk); pclk_disable: clk_disable_unprepare(msm_host->pclk); bus_clk_disable: if (!IS_ERR(msm_host->bus_clk)) clk_disable_unprepare(msm_host->bus_clk); pltfm_free: sdhci_pltfm_free(pdev); return ret; }
static int moxart_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; struct resource res_mmc; struct mmc_host *mmc; struct moxart_host *host = NULL; struct dma_slave_config cfg; struct clk *clk; void __iomem *reg_mmc; int irq, ret; u32 i; mmc = mmc_alloc_host(sizeof(struct moxart_host), dev); if (!mmc) { dev_err(dev, "mmc_alloc_host failed\n"); ret = -ENOMEM; goto out; } ret = of_address_to_resource(node, 0, &res_mmc); if (ret) { dev_err(dev, "of_address_to_resource failed\n"); goto out; } irq = irq_of_parse_and_map(node, 0); if (irq <= 0) { dev_err(dev, "irq_of_parse_and_map failed\n"); ret = -EINVAL; goto out; } clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto out; } reg_mmc = devm_ioremap_resource(dev, &res_mmc); if (IS_ERR(reg_mmc)) { ret = PTR_ERR(reg_mmc); goto out; } ret = mmc_of_parse(mmc); if (ret) goto out; host = mmc_priv(mmc); host->mmc = mmc; host->base = reg_mmc; host->reg_phys = res_mmc.start; host->timeout = msecs_to_jiffies(1000); host->sysclk = clk_get_rate(clk); host->fifo_width = readl(host->base + REG_FEATURE) << 2; host->dma_chan_tx = dma_request_slave_channel_reason(dev, "tx"); host->dma_chan_rx = dma_request_slave_channel_reason(dev, "rx"); spin_lock_init(&host->lock); mmc->ops = &moxart_ops; mmc->f_max = DIV_ROUND_CLOSEST(host->sysclk, 2); mmc->f_min = DIV_ROUND_CLOSEST(host->sysclk, CLK_DIV_MASK * 2); mmc->ocr_avail = 0xffff00; /* Support 2.0v - 3.6v power. */ if (IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { if (PTR_ERR(host->dma_chan_tx) == -EPROBE_DEFER || PTR_ERR(host->dma_chan_rx) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto out; } dev_dbg(dev, "PIO mode transfer enabled\n"); host->have_dma = false; } else { dev_dbg(dev, "DMA channels found (%p,%p)\n", host->dma_chan_tx, host->dma_chan_rx); host->have_dma = true; cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.direction = DMA_MEM_TO_DEV; cfg.src_addr = 0; cfg.dst_addr = host->reg_phys + REG_DATA_WINDOW; dmaengine_slave_config(host->dma_chan_tx, &cfg); cfg.direction = DMA_DEV_TO_MEM; cfg.src_addr = host->reg_phys + REG_DATA_WINDOW; cfg.dst_addr = 0; dmaengine_slave_config(host->dma_chan_rx, &cfg); } switch ((readl(host->base + REG_BUS_WIDTH) >> 3) & 3) { case 1: mmc->caps |= MMC_CAP_4_BIT_DATA; break; case 2: mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; break; default: break; } writel(0, host->base + REG_INTERRUPT_MASK); writel(CMD_SDC_RESET, host->base + REG_COMMAND); for (i = 0; i < MAX_RETRIES; i++) { if (!(readl(host->base + REG_COMMAND) & CMD_SDC_RESET)) break; udelay(5); } ret = devm_request_irq(dev, irq, moxart_irq, 0, "moxart-mmc", host); if (ret) goto out; dev_set_drvdata(dev, mmc); mmc_add_host(mmc); dev_dbg(dev, "IRQ=%d, FIFO is %d bytes\n", irq, host->fifo_width); return 0; out: if (mmc) mmc_free_host(mmc); return ret; }
static int sdhci_msm_probe(struct platform_device *pdev) { struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct sdhci_msm_host *msm_host; struct resource *core_memres; int ret; u16 host_version; msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); if (!msm_host) return -ENOMEM; msm_host->sdhci_msm_pdata.ops = &sdhci_msm_ops; host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0); if (IS_ERR(host)) return PTR_ERR(host); pltfm_host = sdhci_priv(host); pltfm_host->priv = msm_host; msm_host->mmc = host->mmc; msm_host->pdev = pdev; ret = mmc_of_parse(host->mmc); if (ret) goto pltfm_free; sdhci_get_of_property(pdev); /* Setup SDCC bus voter clock. */ msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); if (!IS_ERR(msm_host->bus_clk)) { /* Vote for max. clk rate for max. performance */ ret = clk_set_rate(msm_host->bus_clk, INT_MAX); if (ret) goto pltfm_free; ret = clk_prepare_enable(msm_host->bus_clk); if (ret) goto pltfm_free; } /* Setup main peripheral bus clock */ msm_host->pclk = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(msm_host->pclk)) { ret = PTR_ERR(msm_host->pclk); dev_err(&pdev->dev, "Perpheral clk setup failed (%d)\n", ret); goto bus_clk_disable; } ret = clk_prepare_enable(msm_host->pclk); if (ret) goto bus_clk_disable; /* Setup SDC MMC clock */ msm_host->clk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(msm_host->clk)) { ret = PTR_ERR(msm_host->clk); dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret); goto pclk_disable; } ret = clk_prepare_enable(msm_host->clk); if (ret) goto pclk_disable; core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1); msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres); if (IS_ERR(msm_host->core_mem)) { dev_err(&pdev->dev, "Failed to remap registers\n"); ret = PTR_ERR(msm_host->core_mem); goto clk_disable; } /* Reset the core and Enable SDHC mode */ writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) | CORE_SW_RST, msm_host->core_mem + CORE_POWER); /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */ usleep_range(1000, 5000); if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) { dev_err(&pdev->dev, "Stuck in reset\n"); ret = -ETIMEDOUT; goto clk_disable; } /* Set HC_MODE_EN bit in HC_MODE register */ writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE)); host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE; host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n", host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT)); ret = sdhci_add_host(host); if (ret) goto clk_disable; return 0; clk_disable: clk_disable_unprepare(msm_host->clk); pclk_disable: clk_disable_unprepare(msm_host->pclk); bus_clk_disable: if (!IS_ERR(msm_host->bus_clk)) clk_disable_unprepare(msm_host->bus_clk); pltfm_free: sdhci_pltfm_free(pdev); return ret; }
static int sh_mmcif_probe(struct platform_device *pdev) { int ret = 0, irq[2]; struct mmc_host *mmc; struct sh_mmcif_host *host; struct sh_mmcif_plat_data *pd = pdev->dev.platform_data; struct resource *res; void __iomem *reg; const char *name; irq[0] = platform_get_irq(pdev, 0); irq[1] = platform_get_irq(pdev, 1); if (irq[0] < 0) { dev_err(&pdev->dev, "Get irq error\n"); return -ENXIO; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(reg)) return PTR_ERR(reg); mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev); if (!mmc) return -ENOMEM; ret = mmc_of_parse(mmc); if (ret < 0) goto err_host; host = mmc_priv(mmc); host->mmc = mmc; host->addr = reg; host->timeout = msecs_to_jiffies(10000); host->ccs_enable = !pd || !pd->ccs_unsupported; host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present; host->pd = pdev; spin_lock_init(&host->lock); mmc->ops = &sh_mmcif_ops; sh_mmcif_init_ocr(host); mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_WAIT_WHILE_BUSY; if (pd && pd->caps) mmc->caps |= pd->caps; mmc->max_segs = 32; mmc->max_blk_size = 512; mmc->max_req_size = PAGE_CACHE_SIZE * mmc->max_segs; mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size; mmc->max_seg_size = mmc->max_req_size; platform_set_drvdata(pdev, host); pm_runtime_enable(&pdev->dev); host->power = false; host->hclk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(host->hclk)) { ret = PTR_ERR(host->hclk); dev_err(&pdev->dev, "cannot get clock: %d\n", ret); goto err_pm; } ret = sh_mmcif_clk_update(host); if (ret < 0) goto err_pm; ret = pm_runtime_resume(&pdev->dev); if (ret < 0) goto err_clk; INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); sh_mmcif_sync_reset(host); sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); name = irq[1] < 0 ? dev_name(&pdev->dev) : "sh_mmc:error"; ret = devm_request_threaded_irq(&pdev->dev, irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, name, host); if (ret) { dev_err(&pdev->dev, "request_irq error (%s)\n", name); goto err_clk; } if (irq[1] >= 0) { ret = devm_request_threaded_irq(&pdev->dev, irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); if (ret) { dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); goto err_clk; } } if (pd && pd->use_cd_gpio) { ret = mmc_gpio_request_cd(mmc, pd->cd_gpio, 0); if (ret < 0) goto err_clk; } mutex_init(&host->thread_lock); ret = mmc_add_host(mmc); if (ret < 0) goto err_clk; dev_pm_qos_expose_latency_limit(&pdev->dev, 100); dev_info(&pdev->dev, "Chip version 0x%04x, clock rate %luMHz\n", sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0xffff, clk_get_rate(host->hclk) / 1000000UL); clk_disable_unprepare(host->hclk); return ret; err_clk: clk_disable_unprepare(host->hclk); err_pm: pm_runtime_disable(&pdev->dev); err_host: mmc_free_host(mmc); return ret; }
static int mxs_mmc_probe(struct platform_device *pdev) { const struct of_device_id *of_id = of_match_device(mxs_mmc_dt_ids, &pdev->dev); struct device_node *np = pdev->dev.of_node; struct mxs_mmc_host *host; struct mmc_host *mmc; struct resource *iores; int ret = 0, irq_err; struct regulator *reg_vmmc; struct mxs_ssp *ssp; irq_err = platform_get_irq(pdev, 0); if (irq_err < 0) return irq_err; mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev); if (!mmc) return -ENOMEM; host = mmc_priv(mmc); ssp = &host->ssp; ssp->dev = &pdev->dev; iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); ssp->base = devm_ioremap_resource(&pdev->dev, iores); if (IS_ERR(ssp->base)) { ret = PTR_ERR(ssp->base); goto out_mmc_free; } ssp->devid = (enum mxs_ssp_id) of_id->data; host->mmc = mmc; host->sdio_irq_en = 0; reg_vmmc = devm_regulator_get(&pdev->dev, "vmmc"); if (!IS_ERR(reg_vmmc)) { ret = regulator_enable(reg_vmmc); if (ret) { dev_err(&pdev->dev, "Failed to enable vmmc regulator: %d\n", ret); goto out_mmc_free; } } ssp->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ssp->clk)) { ret = PTR_ERR(ssp->clk); goto out_mmc_free; } ret = clk_prepare_enable(ssp->clk); if (ret) goto out_mmc_free; ret = mxs_mmc_reset(host); if (ret) { dev_err(&pdev->dev, "Failed to reset mmc: %d\n", ret); goto out_clk_disable; } ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx"); if (!ssp->dmach) { dev_err(mmc_dev(host->mmc), "%s: failed to request dma\n", __func__); ret = -ENODEV; goto out_clk_disable; } /* set mmc core parameters */ mmc->ops = &mxs_mmc_ops; mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; host->broken_cd = of_property_read_bool(np, "broken-cd"); mmc->f_min = 400000; mmc->f_max = 288000000; ret = mmc_of_parse(mmc); if (ret) goto out_clk_disable; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->max_segs = 52; mmc->max_blk_size = 1 << 0xf; mmc->max_blk_count = (ssp_is_old(ssp)) ? 0xff : 0xffffff; mmc->max_req_size = (ssp_is_old(ssp)) ? 0xffff : 0xffffffff; mmc->max_seg_size = dma_get_max_seg_size(ssp->dmach->device->dev); platform_set_drvdata(pdev, mmc); ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0, dev_name(&pdev->dev), host); if (ret) goto out_free_dma; spin_lock_init(&host->lock); ret = mmc_add_host(mmc); if (ret) goto out_free_dma; dev_info(mmc_dev(host->mmc), "initialized\n"); return 0; out_free_dma: dma_release_channel(ssp->dmach); out_clk_disable: clk_disable_unprepare(ssp->clk); out_mmc_free: mmc_free_host(mmc); return ret; }