From: xbw Date: Sun, 23 Mar 2014 22:12:08 +0000 (+0800) Subject: SDMMC: X-Git-Tag: firefly_0821_release~5881 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=a9c8bad76ffaf0ade8169c8844a284c4515d87b8;p=firefly-linux-kernel-4.4.55.git SDMMC: 1.add the flag for emmc-disk. 2.the process of insert-remove card is ok. 3.modify the sdio-detect for sdio wifi. --- diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 98bc2c205259..8d4d8837fb00 100755 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2412,6 +2412,14 @@ static int mmc_blk_probe(struct mmc_card *card) #ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME mmc_set_bus_resume_policy(card->host, 1); +#endif +#if defined(CONFIG_MMC_DW_ROCKCHIP) + if(card->host->restrict_caps & RESTRICT_CARD_TYPE_EMMC){ + this_card = card; + md->disk->emmc_disk = 1; + }else { + md->disk->emmc_disk = 0; + } #endif if (mmc_add_disk(md)) goto out; @@ -2432,10 +2440,6 @@ static int mmc_blk_probe(struct mmc_card *card) pm_runtime_set_active(&card->dev); pm_runtime_enable(&card->dev); } -#if defined(CONFIG_MMC_DW_ROCKCHIP) - if(card->host->restrict_caps & RESTRICT_CARD_TYPE_EMMC) - this_card = card; -#endif return 0; diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 7767f14e359b..dbd5f78fe39e 100755 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -604,7 +604,7 @@ EXPORT_SYMBOL(mmc_free_host); * OR, rescan host from argument. * */ -int mmc_host_rescan(struct mmc_host *host) +int mmc_host_rescan(struct mmc_host *host, int val) { if(NULL != primary_sdio_host){ if(!host) @@ -618,9 +618,10 @@ int mmc_host_rescan(struct mmc_host *host) } printk("%s:mmc host rescan start!\n", mmc_hostname(host)); - - mmc_detect_change(host, msecs_to_jiffies(10)); + if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->set_sdio_status) + host->ops->set_sdio_status(host, val); + return 0; } EXPORT_SYSMBOL(mmc_host_rescan); diff --git a/drivers/mmc/host/rk_sdmmc.c b/drivers/mmc/host/rk_sdmmc.c index 4d792a609b8a..568fb02af48c 100755 --- a/drivers/mmc/host/rk_sdmmc.c +++ b/drivers/mmc/host/rk_sdmmc.c @@ -62,6 +62,8 @@ #define SDMMC_DATA_TIMEOUT_SDIO 250 #define SDMMC_DATA_TIMEOUT_EMMC 2500 +//#define SDMMC_WAIT_FOR_UNBUSY 2500 + #ifdef CONFIG_MMC_DW_IDMAC #define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \ SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \ @@ -336,6 +338,21 @@ static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd) static void dw_mci_start_command(struct dw_mci *host, struct mmc_command *cmd, u32 cmd_flags) { +#ifdef SDMMC_WAIT_FOR_UNBUSY + unsigned long time_loop = jiffies + msecs_to_jiffies(SDMMC_WAIT_FOR_UNBUSY); + unsigned int status; + bool ret=1; + + while ((ret=time_before(jiffies, time_loop))&&(test_bit(DW_MMC_CARD_PRESENT, &host->cur_slot->flags))){ + status = mci_readl(host, STATUS); + if (!(status & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY))) + break; + } ; + if(!ret) + printk("%d..%s: cmd=%d,wait for unbusy timeout.......[%s]\n", + __LINE__, __FUNCTION__,cmd->opcode,mmc_hostname(host->mmc)); +#endif + host->pre_cmd = host->cmd; host->cmd = cmd; dev_vdbg(host->dev, "start command: ARGR=0x%08x CMDR=0x%08x\n", @@ -343,7 +360,8 @@ static void dw_mci_start_command(struct dw_mci *host, mci_writel(host, CMDARG, cmd->arg); wmb(); - MMC_DBG_INFO_FUNC(host->mmc,"%d..%s start cmd=%d, arg=0x%x[%s]",__LINE__, __FUNCTION__,cmd->opcode, cmd->arg,mmc_hostname(host->mmc)); + MMC_DBG_INFO_FUNC(host->mmc,"Line%d..%s start cmd=%d, arg=0x%x[%s]",\ + __LINE__, __FUNCTION__,cmd->opcode, cmd->arg,mmc_hostname(host->mmc)); //dw_mci_regs_printk(host); if(host->mmc->hold_reg_flag) @@ -784,10 +802,23 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) { - struct dw_mci *host = slot->host; + struct dw_mci *host = slot->host; unsigned long timeout = jiffies + msecs_to_jiffies(500); unsigned int cmd_status = 0; - +#ifdef SDMMC_WAIT_FOR_UNBUSY + timeout = jiffies + msecs_to_jiffies(SDMMC_WAIT_FOR_UNBUSY); + bool ret=0; + if(test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) { + while (ret=time_before(jiffies, timeout)) { + cmd_status = mci_readl(host, STATUS); + if (!(cmd_status & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY))) + break; + } ; + if(!ret) + printk("%d..%s: wait for unbusy timeout.......[%s]\n", \ + __LINE__, __FUNCTION__, mmc_hostname(host->mmc)); + } +#endif mci_writel(host, CMDARG, arg); wmb(); mci_writel(host, CMD, SDMMC_CMD_START | cmd); @@ -1000,9 +1031,9 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) { spin_unlock_bh(&host->lock); - mrq->cmd->error = -ENOMEDIUM; - - MMC_DBG_CMD_FUNC(host->mmc, "dw_mci_reqeust--reqeuest done, cmd=%d [%s]",mrq->cmd->opcode, mmc_hostname(host->mmc)); + mrq->cmd->error = -ENOMEDIUM; + MMC_DBG_CMD_FUNC(host->mmc, "%d..%s: no card,so reqeuest done, cmd=%d [%s]",\ + __LINE__, __FUNCTION__, mrq->cmd->opcode, mmc_hostname(host->mmc)); mmc_request_done(mmc, mrq); return; @@ -1020,11 +1051,33 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) struct dw_mci_slot *slot = mmc_priv(mmc); const struct dw_mci_drv_data *drv_data = slot->host->drv_data; u32 regs; - +#ifdef SDMMC_WAIT_FOR_UNBUSY + unsigned long time_loop = jiffies + msecs_to_jiffies(SDMMC_WAIT_FOR_UNBUSY); + bool ret=0; + + if(!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)){ + printk("%d..%s: no card. [%s]\n", \ + __LINE__, __FUNCTION__, mmc_hostname(mmc)); + goto EXIT_POWER; + } + + while (ret=time_before(jiffies, time_loop)) { + regs = mci_readl(slot->host, STATUS); + if (!(regs & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY))) + break; + } ; + if(!ret) + { + printk("slot->flags=%d ", slot->flags); + dump_stack(); + printk("%d..%s: wait for unbusy timeout.......[%s]\n", \ + __LINE__, __FUNCTION__, mmc_hostname(mmc)); + } +#endif switch (ios->bus_width) { case MMC_BUS_WIDTH_4: slot->ctype = SDMMC_CTYPE_4BIT; - break; + break; case MMC_BUS_WIDTH_8: slot->ctype = SDMMC_CTYPE_8BIT; break; @@ -1057,6 +1110,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* Slot specific timing and width adjustment */ dw_mci_setup_bus(slot, false); +EXIT_POWER: switch (ios->power_mode) { case MMC_POWER_UP: set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); @@ -1103,6 +1157,29 @@ static int dw_mci_get_ro(struct mmc_host *mmc) return read_only; } +static int dw_mci_set_sdio_status(struct mmc_host *mmc, int val) +{ + struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci_board *brd = slot->host->pdata; + struct dw_mci *host = slot->host; + if (!(mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)) + return 0; + + spin_lock_bh(&host->lock); + if(val) + set_bit(DW_MMC_CARD_PRESENT, &slot->flags); + else + clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); + + spin_unlock_bh(&host->lock); + + mmc_detect_change(slot->mmc, 20); + + return 0; +} + + + static int dw_mci_get_cd(struct mmc_host *mmc) { int present; @@ -1111,13 +1188,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc) struct dw_mci *host = slot->host; int gpio_cd = mmc_gpio_get_cd(mmc); - if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO){ - spin_lock_bh(&host->lock); - set_bit(DW_MMC_CARD_PRESENT, &slot->flags); - spin_unlock_bh(&host->lock); - - return 1; - } + if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO) + return test_bit(DW_MMC_CARD_PRESENT, &slot->flags); /* Use platform get_cd function, else try onboard card detect */ if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) @@ -1259,11 +1331,35 @@ static const struct mmc_host_ops dw_mci_ops = { .set_ios = dw_mci_set_ios, .get_ro = dw_mci_get_ro, .get_cd = dw_mci_get_cd, + .set_sdio_status = dw_mci_set_sdio_status, .hw_reset = dw_mci_hw_reset, .enable_sdio_irq = dw_mci_enable_sdio_irq, .execute_tuning = dw_mci_execute_tuning, }; +static void dw_mci_enable_irq(struct dw_mci *host, bool irqflag) +{ + unsigned long flags; + + if(!host) + return; + + local_irq_save(flags); + if(host->irq_state != irqflag) + { + host->irq_state = irqflag; + if(irqflag) + { + enable_irq(host->irq); + } + else + { + disable_irq(host->irq); + } + } + local_irq_restore(flags); +} + static void dw_mci_deal_data_end(struct dw_mci *host, struct mmc_request *mrq) __releases(&host->lock) __acquires(&host->lock) @@ -2135,8 +2231,8 @@ static void dw_mci_work_routine_card(struct work_struct *work) while (present != slot->last_detect_state) { dev_dbg(&slot->mmc->class_dev, "card %s\n", present ? "inserted" : "removed"); - MMC_DBG_BOOT_FUNC(mmc, "card %s, devname=%s \n", - present ? "inserted" : "removed", mmc_hostname(mmc)); + MMC_DBG_BOOT_FUNC(mmc, " The card is %s. ===!!!!!!==[%s]\n", + present ? "inserted" : "removed.", mmc_hostname(mmc)); spin_lock_bh(&host->lock); @@ -2408,12 +2504,12 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) mmc->f_min = DW_MCI_FREQ_MIN; mmc->f_max = DW_MCI_FREQ_MAX; - printk("%d..%s: fmin=%d, fmax=%d \n", __LINE__,__FUNCTION__,mmc->f_min, mmc->f_max); + printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__,__FUNCTION__,mmc->f_min, mmc->f_max, mmc_hostname(mmc)); } else { mmc->f_min = freq[0]; mmc->f_max = freq[1]; - printk("%d..%s: fmin=%d, fmax=%d \n", __LINE__,__FUNCTION__,mmc->f_min, mmc->f_max); + printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__,__FUNCTION__,mmc->f_min, mmc->f_max, mmc_hostname(mmc)); } #endif @@ -2512,26 +2608,38 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) //pwr_en slot->pwr_en_gpio = dw_mci_of_get_pwr_en_gpio(host->dev, slot->id); -if (gpio_is_valid(slot->pwr_en_gpio)) -{ - host->vmmc = NULL; -}else{ - - host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc"); - if (IS_ERR(host->vmmc)) { - pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); - host->vmmc = NULL; - } else { - ret = regulator_enable(host->vmmc); - if (ret) { - dev_err(host->dev, - "failed to enable regulator: %d\n", ret); - goto err_setup_bus; - } - } -} + if (!(mmc->restrict_caps & RESTRICT_CARD_TYPE_SD))//(gpio_is_valid(slot->pwr_en_gpio)) + { + host->vmmc = NULL; + }else{ + + if(mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) + { + host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc"); + } + else + { + host->vmmc = NULL; + } + + if (IS_ERR(host->vmmc)) { + pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); + host->vmmc = NULL; + } else { + ret = regulator_enable(host->vmmc); + if (ret) { + dev_err(host->dev, + "failed to enable regulator: %d\n", ret); + goto err_setup_bus; + } + } + } + slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id); dw_mci_of_get_cd_gpio(host->dev, slot->id, mmc); + + if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO) + clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); ret = mmc_add_host(mmc); if (ret) @@ -2542,7 +2650,7 @@ if (gpio_is_valid(slot->pwr_en_gpio)) #endif /* Card initially undetected */ - slot->last_detect_state = 0; + slot->last_detect_state = 1; return 0; @@ -2658,11 +2766,12 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) "assuming 1 slot is available\n"); pdata->num_slots = 1; } - +#if 0 /* get quirks */ for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++) if (of_get_property(np, of_quirks[idx].quirk, NULL)) pdata->quirks |= of_quirks[idx].id; +#endif if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth)) dev_info(dev, "fifo-depth property not found, using " @@ -2717,6 +2826,7 @@ int dw_mci_probe(struct dw_mci *host) int width, i, ret = 0; u32 fifo_size; int init_slots = 0; + u32 regs; if (!host->pdata) { host->pdata = dw_mci_parse_dt(host); @@ -2785,6 +2895,7 @@ int dw_mci_probe(struct dw_mci *host) } host->quirks = host->pdata->quirks; + host->irq_state = true; spin_lock_init(&host->lock); INIT_LIST_HEAD(&host->queue); @@ -2884,14 +2995,26 @@ int dw_mci_probe(struct dw_mci *host) else host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; + /* We need at least one slot to succeed */ + for (i = 0; i < host->num_slots; i++) { + ret = dw_mci_init_slot(host, i); + if (ret) + dev_dbg(host->dev, "slot %d init failed\n", i); + else + init_slots++; + } + /* * Enable interrupts for command done, data over, data empty, card det, * receive ready and error such as transmit, receive timeout, crc error */ mci_writel(host, RINTSTS, 0xFFFFFFFF); - mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | - SDMMC_INT_TXDR | SDMMC_INT_RXDR | - DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); + regs = SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | SDMMC_INT_TXDR | + SDMMC_INT_RXDR | DW_MCI_ERROR_FLAGS; + if(!(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)) + regs |= SDMMC_INT_CD; + mci_writel(host, INTMASK, regs); + mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ dev_info(host->dev, "DW MMC controller at irq %d, " @@ -2899,15 +3022,6 @@ int dw_mci_probe(struct dw_mci *host) "%u deep fifo\n", host->irq, width, fifo_size); - /* We need at least one slot to succeed */ - for (i = 0; i < host->num_slots; i++) { - ret = dw_mci_init_slot(host, i); - if (ret) - dev_dbg(host->dev, "slot %d init failed\n", i); - else - init_slots++; - } - if (init_slots) { dev_info(host->dev, "%d slots initialized\n", init_slots); } else { @@ -3012,6 +3126,7 @@ EXPORT_SYMBOL(dw_mci_suspend); int dw_mci_resume(struct dw_mci *host) { int i, ret; + u32 regs; if (host->vmmc) { ret = regulator_enable(host->vmmc); @@ -3040,9 +3155,11 @@ int dw_mci_resume(struct dw_mci *host) mci_writel(host, TMOUT, 0xFFFFFFFF); mci_writel(host, RINTSTS, 0xFFFFFFFF); - mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | - SDMMC_INT_TXDR | SDMMC_INT_RXDR | - DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); + regs = SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | SDMMC_INT_TXDR | SDMMC_INT_RXDR | + DW_MCI_ERROR_FLAGS; + if(!(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)) + regs |= SDMMC_INT_CD; + mci_writel(host, INTMASK, regs); mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); for (i = 0; i < host->num_slots; i++) { diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c old mode 100644 new mode 100755 index e9c09604c26b..ecaee23cb4e9 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c @@ -47,7 +47,7 @@ void bcm_wlan_power_on(int flag) printk("======== PULL WL_REG_ON HIGH! ========\n"); rockchip_wifi_power(1); msleep(100); - rockchip_wifi_set_carddetect(); + rockchip_wifi_set_carddetect(1); } else { printk("======== PULL WL_REG_ON HIGH! (flag = %d) ========\n", flag); rockchip_wifi_power(1); diff --git a/include/linux/genhd.h b/include/linux/genhd.h old mode 100644 new mode 100755 index 9f3c275e053e..904f3da88690 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -200,6 +200,8 @@ struct gendisk { struct blk_integrity *integrity; #endif int node_id; + + int emmc_disk;//for emmc devive; added by xbw at 2014-03-22 }; static inline struct gendisk *part_to_disk(struct hd_struct *part) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index fd2a7075f765..168120afbcd4 100755 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -124,6 +124,7 @@ struct mmc_host_ops { void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); int (*get_ro)(struct mmc_host *host); int (*get_cd)(struct mmc_host *host); + int (*set_sdio_status)(struct mmc_host *host, int val);//added by xbw,at 2014-03-24 void (*enable_sdio_irq)(struct mmc_host *host, int enable); diff --git a/include/linux/mmc/rk_mmc.h b/include/linux/mmc/rk_mmc.h index 130b2ec80dbe..a2984f83bab9 100755 --- a/include/linux/mmc/rk_mmc.h +++ b/include/linux/mmc/rk_mmc.h @@ -190,6 +190,7 @@ struct dw_mci { /* Workaround flags */ u32 quirks; + bool irq_state; struct regulator *vmmc; /* Power regulator */ unsigned long irq_flags; /* IRQ flags */ diff --git a/include/linux/rfkill-wlan.h b/include/linux/rfkill-wlan.h index 2c1849b28448..8711e8afc050 100755 --- a/include/linux/rfkill-wlan.h +++ b/include/linux/rfkill-wlan.h @@ -40,7 +40,7 @@ struct rksdmmc_gpio_wifi_moudle { void *rockchip_mem_prealloc(int section, unsigned long size); int rockchip_wifi_power(int on); -int rockchip_wifi_set_carddetect(void); +int rockchip_wifi_set_carddetect(int val); int rockchip_wifi_get_oob_irq(void); int rockchip_wifi_reset(int on); int rockchip_wifi_mac_addr(unsigned char *buf); diff --git a/net/rfkill/rfkill-wlan.c b/net/rfkill/rfkill-wlan.c index 0b449fb9733b..b87bdd8e08b8 100755 --- a/net/rfkill/rfkill-wlan.c +++ b/net/rfkill/rfkill-wlan.c @@ -268,10 +268,10 @@ EXPORT_SYMBOL(rockchip_wifi_power); * Wifi Sdio Detect Func * *************************************************************************/ -extern int mmc_host_rescan(struct mmc_host *host); -int rockchip_wifi_set_carddetect(void) +extern int mmc_host_rescan(struct mmc_host *host, int val); +int rockchip_wifi_set_carddetect(int val) { - return mmc_host_rescan(NULL);//NULL => SDIO host + return mmc_host_rescan(NULL, val);//NULL => SDIO host } EXPORT_SYMBOL(rockchip_wifi_set_carddetect);