From bcec492cc1f6a3c6cbe8aa6e73b7b9d71acf6e55 Mon Sep 17 00:00:00 2001 From: lintao Date: Tue, 5 Aug 2014 12:29:23 +0800 Subject: [PATCH] mmc: fix rk3126 support (1) Add cd_gpio support (2) defconf IDMAC --- arch/arm/boot/dts/rk312x-pinctrl.dtsi | 5 ++ arch/arm/boot/dts/rk312x-sdk.dtsi | 3 +- arch/arm/boot/dts/rk312x.dtsi | 3 +- arch/arm/configs/rockchip_defconfig | 1 + drivers/mmc/host/rk_sdmmc.c | 106 ++++++++++++++++++++++---- drivers/mmc/host/rk_sdmmc.h | 3 +- 6 files changed, 104 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/dts/rk312x-pinctrl.dtsi b/arch/arm/boot/dts/rk312x-pinctrl.dtsi index 16c7b42121b6..8dec9bc2cc67 100755 --- a/arch/arm/boot/dts/rk312x-pinctrl.dtsi +++ b/arch/arm/boot/dts/rk312x-pinctrl.dtsi @@ -566,6 +566,10 @@ }; + sdmmc0_pwren: sdmmc0-pwren{ + rockchip,pins = ; + rockchip,pull = ; + }; sdmmc0_bus1: sdmmc0-bus-width1 { rockchip,pins = ; @@ -589,6 +593,7 @@ , //CMD , //CLK , //DET + , //PWREN , //D0 , //D1 , //D2 diff --git a/arch/arm/boot/dts/rk312x-sdk.dtsi b/arch/arm/boot/dts/rk312x-sdk.dtsi index d1545aeb2208..b770b89eb895 100755 --- a/arch/arm/boot/dts/rk312x-sdk.dtsi +++ b/arch/arm/boot/dts/rk312x-sdk.dtsi @@ -49,11 +49,12 @@ clock-freq-min-max = <400000 50000000>; supports-highspeed; supports-sd; + cd-gpios = <&gpio2 GPIO_A7 GPIO_ACTIVE_HIGH>;/*CD GPIO*/ broken-cd; card-detect-delay = <200>; ignore-pm-notify; keep-power-in-suspend; - //vmmc-supply = <&rk808_ldo5_reg>; + vmmc-supply = <&rk818_ldo9_reg>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/rk312x.dtsi b/arch/arm/boot/dts/rk312x.dtsi index a421946c150c..d3fa2c431a38 100755 --- a/arch/arm/boot/dts/rk312x.dtsi +++ b/arch/arm/boot/dts/rk312x.dtsi @@ -468,9 +468,8 @@ #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default", "idle"; - pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_pwren &sdmmc0_dectn &sdmmc0_bus4>; pinctrl-1 = <&sdmmc0_gpio>; - //cd-gpios = <&gpio1 GPIO_C1 GPIO_ACTIVE_HIGH>;/*CD GPIO*/ clocks = <&clk_sdmmc0>, <&clk_gates5 10>; clock-names = "clk_mmc", "hclk_mmc"; dmas = <&pdma 10>; diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 09bfd429f1db..9a6d883ac5ea 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -483,6 +483,7 @@ CONFIG_MMC_PARANOID_SD_INIT=y CONFIG_MMC_BLOCK_MINORS=32 # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_DW=y +CONFIG_MMC_DW_IDMAC=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGERS=y diff --git a/drivers/mmc/host/rk_sdmmc.c b/drivers/mmc/host/rk_sdmmc.c index 0bdaf81e81f0..5d591d049f83 100755 --- a/drivers/mmc/host/rk_sdmmc.c +++ b/drivers/mmc/host/rk_sdmmc.c @@ -1489,12 +1489,33 @@ static int dw_mci_set_sdio_status(struct mmc_host *mmc, int val) static int dw_mci_get_cd(struct mmc_host *mmc) { - int present; - struct dw_mci_slot *slot = mmc_priv(mmc); - struct dw_mci_board *brd = slot->host->pdata; - struct dw_mci *host = slot->host; - int gpio_cd = mmc_gpio_get_cd(mmc); - + int present; + struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci_board *brd = slot->host->pdata; + struct dw_mci *host = slot->host; + int gpio_cd = mmc_gpio_get_cd(mmc); + int gpio_val; + + if (cpu_is_rk312x() && + soc_is_rk3126() && + (mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)) { + gpio_cd = slot->cd_gpio; + if (gpio_is_valid(gpio_cd)) { + gpio_val = gpio_get_value_cansleep(gpio_cd); + msleep(10); + if (gpio_val == gpio_get_value_cansleep(gpio_cd)) { + gpio_cd = gpio_get_value_cansleep(gpio_cd) == 0 ? 1 : 0; + if (gpio_cd == 0) + dw_mci_ctrl_all_reset(host); + } else { + /* Jitter */ + return slot->last_detect_state; + } + } else { + dev_err(host->dev, "dw_mci_get_cd: invalid gpio_cd!\n"); + } + } + if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO) return test_bit(DW_MMC_CARD_PRESENT, &slot->flags); @@ -1508,6 +1529,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc) else present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) == 0 ? 1 : 0; + spin_lock_bh(&host->lock); if (present) { set_bit(DW_MMC_CARD_PRESENT, &slot->flags); @@ -3102,6 +3124,42 @@ static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot, if (mmc_gpio_request_cd(mmc, gpio, 0)) dev_warn(dev, "gpio [%d] request failed\n", gpio); } + +static irqreturn_t dw_mci_gpio_cd_irqt(int irq, void *dev_id) +{ + struct mmc_host *mmc = dev_id; + struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci *host = slot->host; + + queue_work(host->card_workqueue, &host->card_work); + + return IRQ_HANDLED; +} + +static void dw_mci_of_set_cd_gpio_irq(struct device *dev, u32 gpio, + struct mmc_host *mmc) +{ + struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci *host = slot->host; + int irq; + int ret; + + /* Having a missing entry is valid; return silently */ + if (!gpio_is_valid(gpio)) + return; + + irq = gpio_to_irq(gpio); + if (irq >= 0) { + ret = devm_request_threaded_irq(&mmc->class_dev, irq, + NULL, dw_mci_gpio_cd_irqt, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "dw_mci_cd", mmc); + if (ret < 0) + irq = ret; + } else { + dev_err(host->dev, "Request cd-gpio interrupt error!\n"); + } +} #else /* CONFIG_OF */ static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) { @@ -3175,6 +3233,20 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) if (of_find_property(host->dev->of_node, "supports-emmc", NULL)) mmc->restrict_caps |= RESTRICT_CARD_TYPE_EMMC; + /* We assume only low-level chip use gpio_cd */ + if (cpu_is_rk312x() && + soc_is_rk3126() && + (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)) { + slot->cd_gpio = of_get_named_gpio(host->dev->of_node, "cd-gpios", 0); + if (gpio_is_valid(slot->cd_gpio)) { + /* Request gpio int for card detection */ + dw_mci_of_set_cd_gpio_irq(host->dev, slot->cd_gpio,host->mmc); + } else { + slot->cd_gpio = -ENODEV; + dev_err(host->dev, "failed to get your cd-gpios!\n"); + } + } + if (host->pdata->get_ocr) mmc->ocr_avail = host->pdata->get_ocr(id); else @@ -3916,20 +3988,25 @@ int dw_mci_suspend(struct dw_mci *host) host->dma_ops->exit(host); /*only for sdmmc controller*/ - if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD){ + if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) { host->mmc->rescan_disable = 1; - if(cancel_delayed_work_sync(&host->mmc->detect)) + if (cancel_delayed_work_sync(&host->mmc->detect)) wake_unlock(&host->mmc->detect_wake_lock); disable_irq(host->irq); - if(pinctrl_select_state(host->pinctrl, host->pins_idle) < 0) + if (pinctrl_select_state(host->pinctrl, host->pins_idle) < 0) MMC_DBG_ERR_FUNC(host->mmc, "Idle pinctrl setting failed! [%s]", mmc_hostname(host->mmc)); - dw_mci_of_get_cd_gpio(host->dev,0,host->mmc); + mci_writel(host, RINTSTS, 0xFFFFFFFF); mci_writel(host, INTMASK, 0x00); mci_writel(host, CTRL, 0x00); - enable_irq_wake(host->mmc->slot.cd_irq); + + /* Soc rk3126 already in gpio_cd mode */ + if (!(cpu_is_rk312x() && soc_is_rk3126())) { + dw_mci_of_get_cd_gpio(host->dev, 0, host->mmc); + enable_irq_wake(host->mmc->slot.cd_irq); + } } return 0; } @@ -3949,8 +4026,11 @@ int dw_mci_resume(struct dw_mci *host) } /*only for sdmmc controller*/ if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) { - disable_irq_wake(host->mmc->slot.cd_irq); - mmc_gpio_free_cd(host->mmc); + /* Soc rk3126 already in gpio_cd mode */ + if (!(cpu_is_rk312x() && soc_is_rk3126())) { + disable_irq_wake(host->mmc->slot.cd_irq); + mmc_gpio_free_cd(host->mmc); + } if(pinctrl_select_state(host->pinctrl, host->pins_default) < 0) MMC_DBG_ERR_FUNC(host->mmc, "Default pinctrl setting failed! [%s]", mmc_hostname(host->mmc)); diff --git a/drivers/mmc/host/rk_sdmmc.h b/drivers/mmc/host/rk_sdmmc.h index 1166e4698e06..d3ed86bb6a20 100755 --- a/drivers/mmc/host/rk_sdmmc.h +++ b/drivers/mmc/host/rk_sdmmc.h @@ -293,7 +293,8 @@ struct dw_mci_slot { int quirks; int wp_gpio; - int pwr_en_gpio; + int cd_gpio; + int pwr_en_gpio; u32 ctype; u32 pre_ctype; -- 2.34.1