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);
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);
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)
{
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
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;
}
}
/*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));