aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-s3c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci-s3c.c')
-rw-r--r--drivers/mmc/host/sdhci-s3c.c99
1 files changed, 4 insertions, 95 deletions
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 781b8a943d38..fa5954a05449 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -374,82 +374,12 @@ static struct sdhci_ops sdhci_s3c_ops = {
374 .set_uhs_signaling = sdhci_set_uhs_signaling, 374 .set_uhs_signaling = sdhci_set_uhs_signaling,
375}; 375};
376 376
377static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
378{
379 struct sdhci_host *host = platform_get_drvdata(dev);
380#ifdef CONFIG_PM_RUNTIME
381 struct sdhci_s3c *sc = sdhci_priv(host);
382#endif
383 unsigned long flags;
384
385 if (host) {
386 spin_lock_irqsave(&host->lock, flags);
387 if (state) {
388 dev_dbg(&dev->dev, "card inserted.\n");
389#ifdef CONFIG_PM_RUNTIME
390 clk_prepare_enable(sc->clk_io);
391#endif
392 host->flags &= ~SDHCI_DEVICE_DEAD;
393 host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
394 } else {
395 dev_dbg(&dev->dev, "card removed.\n");
396 host->flags |= SDHCI_DEVICE_DEAD;
397 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
398#ifdef CONFIG_PM_RUNTIME
399 clk_disable_unprepare(sc->clk_io);
400#endif
401 }
402 tasklet_schedule(&host->card_tasklet);
403 spin_unlock_irqrestore(&host->lock, flags);
404 }
405}
406
407static irqreturn_t sdhci_s3c_gpio_card_detect_thread(int irq, void *dev_id)
408{
409 struct sdhci_s3c *sc = dev_id;
410 int status = gpio_get_value(sc->ext_cd_gpio);
411 if (sc->pdata->ext_cd_gpio_invert)
412 status = !status;
413 sdhci_s3c_notify_change(sc->pdev, status);
414 return IRQ_HANDLED;
415}
416
417static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
418{
419 struct s3c_sdhci_platdata *pdata = sc->pdata;
420 struct device *dev = &sc->pdev->dev;
421
422 if (devm_gpio_request(dev, pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) {
423 sc->ext_cd_gpio = pdata->ext_cd_gpio;
424 sc->ext_cd_irq = gpio_to_irq(pdata->ext_cd_gpio);
425 if (sc->ext_cd_irq &&
426 request_threaded_irq(sc->ext_cd_irq, NULL,
427 sdhci_s3c_gpio_card_detect_thread,
428 IRQF_TRIGGER_RISING |
429 IRQF_TRIGGER_FALLING |
430 IRQF_ONESHOT,
431 dev_name(dev), sc) == 0) {
432 int status = gpio_get_value(sc->ext_cd_gpio);
433 if (pdata->ext_cd_gpio_invert)
434 status = !status;
435 sdhci_s3c_notify_change(sc->pdev, status);
436 } else {
437 dev_warn(dev, "cannot request irq for card detect\n");
438 sc->ext_cd_irq = 0;
439 }
440 } else {
441 dev_err(dev, "cannot request gpio for card detect\n");
442 }
443}
444
445#ifdef CONFIG_OF 377#ifdef CONFIG_OF
446static int sdhci_s3c_parse_dt(struct device *dev, 378static int sdhci_s3c_parse_dt(struct device *dev,
447 struct sdhci_host *host, struct s3c_sdhci_platdata *pdata) 379 struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
448{ 380{
449 struct device_node *node = dev->of_node; 381 struct device_node *node = dev->of_node;
450 struct sdhci_s3c *ourhost = to_s3c(host);
451 u32 max_width; 382 u32 max_width;
452 int gpio;
453 383
454 /* if the bus-width property is not specified, assume width as 1 */ 384 /* if the bus-width property is not specified, assume width as 1 */
455 if (of_property_read_u32(node, "bus-width", &max_width)) 385 if (of_property_read_u32(node, "bus-width", &max_width))
@@ -467,18 +397,8 @@ static int sdhci_s3c_parse_dt(struct device *dev,
467 return 0; 397 return 0;
468 } 398 }
469 399
470 gpio = of_get_named_gpio(node, "cd-gpios", 0); 400 if (of_get_named_gpio(node, "cd-gpios", 0))
471 if (gpio_is_valid(gpio)) {
472 pdata->cd_type = S3C_SDHCI_CD_GPIO;
473 pdata->ext_cd_gpio = gpio;
474 ourhost->ext_cd_gpio = -1;
475 if (of_get_property(node, "cd-inverted", NULL))
476 pdata->ext_cd_gpio_invert = 1;
477 return 0; 401 return 0;
478 } else if (gpio != -ENOENT) {
479 dev_err(dev, "invalid card detect gpio specified\n");
480 return -EINVAL;
481 }
482 402
483 /* assuming internal card detect that will be configured by pinctrl */ 403 /* assuming internal card detect that will be configured by pinctrl */
484 pdata->cd_type = S3C_SDHCI_CD_INTERNAL; 404 pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
@@ -681,6 +601,8 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
681 pm_runtime_use_autosuspend(&pdev->dev); 601 pm_runtime_use_autosuspend(&pdev->dev);
682 pm_suspend_ignore_children(&pdev->dev, 1); 602 pm_suspend_ignore_children(&pdev->dev, 1);
683 603
604 mmc_of_parse(host->mmc);
605
684 ret = sdhci_add_host(host); 606 ret = sdhci_add_host(host);
685 if (ret) { 607 if (ret) {
686 dev_err(dev, "sdhci_add_host() failed\n"); 608 dev_err(dev, "sdhci_add_host() failed\n");
@@ -689,15 +611,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
689 goto err_req_regs; 611 goto err_req_regs;
690 } 612 }
691 613
692 /* The following two methods of card detection might call
693 sdhci_s3c_notify_change() immediately, so they can be called
694 only after sdhci_add_host(). Setup errors are ignored. */
695 if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_init)
696 pdata->ext_cd_init(&sdhci_s3c_notify_change);
697 if (pdata->cd_type == S3C_SDHCI_CD_GPIO &&
698 gpio_is_valid(pdata->ext_cd_gpio))
699 sdhci_s3c_setup_card_detect_gpio(sc);
700
701#ifdef CONFIG_PM_RUNTIME 614#ifdef CONFIG_PM_RUNTIME
702 if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) 615 if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
703 clk_disable_unprepare(sc->clk_io); 616 clk_disable_unprepare(sc->clk_io);
@@ -718,16 +631,12 @@ static int sdhci_s3c_remove(struct platform_device *pdev)
718{ 631{
719 struct sdhci_host *host = platform_get_drvdata(pdev); 632 struct sdhci_host *host = platform_get_drvdata(pdev);
720 struct sdhci_s3c *sc = sdhci_priv(host); 633 struct sdhci_s3c *sc = sdhci_priv(host);
721 struct s3c_sdhci_platdata *pdata = sc->pdata;
722
723 if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
724 pdata->ext_cd_cleanup(&sdhci_s3c_notify_change);
725 634
726 if (sc->ext_cd_irq) 635 if (sc->ext_cd_irq)
727 free_irq(sc->ext_cd_irq, sc); 636 free_irq(sc->ext_cd_irq, sc);
728 637
729#ifdef CONFIG_PM_RUNTIME 638#ifdef CONFIG_PM_RUNTIME
730 if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) 639 if (sc->pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
731 clk_prepare_enable(sc->clk_io); 640 clk_prepare_enable(sc->clk_io);
732#endif 641#endif
733 sdhci_remove_host(host, 1); 642 sdhci_remove_host(host, 1);