/** * mmc_gpio_request_cd - request a gpio for card-detection * @host: mmc host * @gpio: gpio number requested * @debounce: debounce time in microseconds * * As devm_* managed functions are used in mmc_gpio_request_cd(), client * drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up, * if the requesting and freeing are only needed at probing and unbinding time * for once. However, if client drivers do something special like runtime * switching for card-detection, they are responsible for calling * mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own. * * If GPIO debouncing is desired, set the debounce parameter to a non-zero * value. The caller is responsible for ensuring that the GPIO driver associated * with the GPIO supports debouncing, otherwise an error will be returned. * * Returns zero on success, else an error. */ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, unsigned int debounce) { struct mmc_gpio *ctx; int ret; ret = mmc_gpio_alloc(host); if (ret < 0) return ret; ctx = host->slot.handler_priv; ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN, ctx->cd_label); if (ret < 0) /* * don't bother freeing memory. It might still get used by other * slot functions, in any case it will be freed, when the device * is destroyed. */ return ret; if (debounce) { ret = gpio_set_debounce(gpio, debounce); if (ret < 0) return ret; } ctx->override_cd_active_level = true; ctx->cd_gpio = gpio_to_desc(gpio); mmc_gpiod_request_cd_irq(host); return 0; }
static int sdhci_sirf_probe(struct platform_device *pdev) { struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct sdhci_sirf_priv *priv; struct clk *clk; int gpio_cd; int ret; clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { dev_err(&pdev->dev, "unable to get clock"); return PTR_ERR(clk); } if (pdev->dev.of_node) gpio_cd = of_get_named_gpio(pdev->dev.of_node, "cd-gpios", 0); else gpio_cd = -EINVAL; host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata, sizeof(struct sdhci_sirf_priv)); if (IS_ERR(host)) return PTR_ERR(host); pltfm_host = sdhci_priv(host); pltfm_host->clk = clk; priv = sdhci_pltfm_priv(pltfm_host); priv->gpio_cd = gpio_cd; sdhci_get_of_property(pdev); ret = clk_prepare_enable(pltfm_host->clk); if (ret) goto err_clk_prepare; ret = sdhci_add_host(host); if (ret) goto err_sdhci_add; /* * We must request the IRQ after sdhci_add_host(), as the tasklet only * gets setup in sdhci_add_host() and we oops. */ if (gpio_is_valid(priv->gpio_cd)) { ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd, 0); if (ret) { dev_err(&pdev->dev, "card detect irq request failed: %d\n", ret); goto err_request_cd; } mmc_gpiod_request_cd_irq(host->mmc); } return 0; err_request_cd: sdhci_remove_host(host, 0); err_sdhci_add: clk_disable_unprepare(pltfm_host->clk); err_clk_prepare: sdhci_pltfm_free(pdev); return ret; }