static irqreturn_t at91_mmc_det_irq(int irq, void *_host) { struct at91mci_host *host = _host; int present = !gpio_get_value(irq_to_gpio(irq)); /* * we expect this irq on both insert and remove, * and use a short delay to debounce. */ if (present != host->present) { host->present = present; pr_debug("%s: card %s\n", mmc_hostname(host->mmc), present ? "insert" : "remove"); if (!present) { pr_debug("****** Resetting SD-card bus width ******\n"); at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); } mmc_detect_change(host->mmc, msecs_to_jiffies(100)); } return IRQ_HANDLED; }
/** * mmc_resume_host - resume a previously suspended host * @host: mmc host */ int mmc_resume_host(struct mmc_host *host) { #if 0 // kimhyuns remove to recognize card // for issue fix for ecim G0100145817 if(host->bus_dead ) #else if((host->bus_dead) && (host->index!=0)) #endif { printk("No Suspend resume in case of bus-dead if init failed -- %s \r\n",__FUNCTION__); return 0; } mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if ( host->card && mmc_card_sdio(host->card)){ //ijihyun.jung -Sec VinsQ printk("mmc%d:mmc_resume_host: skip mmc_power_up()\n", host->index); } else { mmc_power_up(host); } mmc_select_voltage(host, host->ocr);//cyj_dc23 -kernel 협의 BUG_ON(!host->bus_ops->resume); host->bus_ops->resume(host); } mmc_bus_put(host); /* * We add a slight delay here so that resume can progress * in parallel. */ if ( host->card && mmc_card_sdio(host->card)) { //ijihyun.jung -Sec VinsQ printk("mmc%d:mmc_resume_host: skip mmc_detect_change()\n", host->index); } else{ printk("mmc%d:mmc_resume_host: excute mmc_detect_change()\n", host->index); mmc_detect_change(host, 1); } return 0; }
static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) { /* Schedule a card detection after a debounce timeout */ struct mmc_host *host = dev_id; struct mmc_gpio *ctx = host->slot.handler_priv; int status; /* * In case host->ops are not yet initialized return immediately. * The card will get detected later when host driver calls * mmc_add_host() after host->ops are initialized. */ if (!host->ops) goto out; if (host->ops->card_event) host->ops->card_event(host); status = mmc_gpio_get_status(host); if (unlikely(status < 0)) goto out; #ifdef VENDOR_EDIT //[email protected], 2014-07-10 Add for retry 5 times when new sdcard init error host->detect_change_retry = 5; #endif /* VENDOR_EDIT */ if (status ^ ctx->status) { pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n", mmc_hostname(host), ctx->status, status, (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ? "HIGH" : "LOW"); ctx->status = status; /* Schedule a card detection after a debounce timeout */ mmc_detect_change(host, msecs_to_jiffies(200)); } out: return IRQ_HANDLED; }
static irqreturn_t sunximmc_irq(int irq, void *dev_id) { struct sunxi_mmc_host *smc_host = dev_id; unsigned long iflags; spin_lock_irqsave(&smc_host->lock, iflags); smc_host->sdio_int = 0; if (smc_host->cd_mode == CARD_DETECT_BY_DATA3) { smc_host->change = 0; } sdxc_check_status(smc_host); if (smc_host->wait == SDC_WAIT_FINALIZE) { tasklet_schedule(&smc_host->tasklet); } spin_unlock_irqrestore(&smc_host->lock, iflags); /* sdio interrupt call */ if (smc_host->sdio_int) { mmc_signal_sdio_irq(smc_host->mmc); // SMC_MSG("- sdio int -\n"); } /* card detect change */ if (smc_host->cd_mode == CARD_DETECT_BY_DATA3) { if (smc_host->change) { mmc_detect_change(smc_host->mmc, msecs_to_jiffies(300)); } } return IRQ_HANDLED; }
/** * mmc_resume_host - resume a previously suspended host * @host: mmc host */ int mmc_resume_host(struct mmc_host *host) { int err = 0; mmc_bus_get(host); if (mmc_bus_manual_resume(host)) { host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; mmc_bus_put(host); return 0; } if (host->bus_ops && !host->bus_dead) { mmc_power_up(host); mmc_select_voltage(host, host->ocr); BUG_ON(!host->bus_ops->resume); err = host->bus_ops->resume(host); if (err) { printk(KERN_WARNING "%s: error %d during resume " "(card was removed?)\n", mmc_hostname(host), err); err = 0; } } mmc_bus_put(host); #if defined(CONFIG_ATH_WIFI) || defined(CONFIG_BCM_WIFI) if (host->index == ATH_WIFI_SDCC_INDEX) { pr_info("%s: mmc_resume_host in wifi slot skip cmd7\n", mmc_hostname(host)); return err; } #endif /* * We add a slight delay here so that resume can progress * in parallel. */ mmc_detect_change(host, 1); return err; }
static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) { /* Schedule a card detection after a debounce timeout */ struct mmc_host *host = dev_id; struct mmc_gpio *ctx = host->slot.handler_priv; int status; /* * In case host->ops are not yet initialized return immediately. * The card will get detected later when host driver calls * mmc_add_host() after host->ops are initialized. */ if (!host->ops) goto out; if (host->ops->card_event) host->ops->card_event(host); status = mmc_gpio_read_status(host); if (unlikely(status < 0)) goto out; if (status ^ ctx->status) { pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n", mmc_hostname(host), ctx->status, status, (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ? "HIGH" : "LOW"); ctx->status = status; host->card_bad = 0; host->requests = 0ULL; host->request_errors = 0ULL; /* Schedule a card detection after a debounce timeout */ mmc_detect_change(host, msecs_to_jiffies(200)); } out: return IRQ_HANDLED; }
int wlan_device_set_carddetect(int val) { pr_info("%s: %d\n", __func__, val); mdelay(100); #if 0 wlan_device_cd = val; if (wifi_status_cb) { wifi_status_cb(val, wifi_status_cb_devid); } else pr_warning("%s: Nobody to notify\n", __func__); #endif #ifdef CONFIG_WLAN_SDIO // sdhci_bus_scan(); if(wlan_mmc) { mmc_detect_change(wlan_mmc, 0); } else { pr_info("%s wlan_mmc is null,carddetect failed \n ",__func__); } #endif return 0; }
static void s3c24xx_irq_cd_handler( void *param ) { struct mmc_host *host=(struct mmc_host *) param; /* We want the MMC/SD stack to redetect if this IRQ goes off. To do this */ /* we remove the bus when this IRQ occurs. mmc_detect_change will then */ /* make sure the bus is reenumerated. */ mmc_flush_scheduled_work(); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); } mmc_bus_put(host); mmc_detect_change( host, HZ/10 ); return; }
/** * mmc_resume_host - resume a previously suspended host * @host: mmc host */ int mmc_resume_host(struct mmc_host *host) { int err = 0; mmc_bus_get(host); if (host->bus_resume_flags & MMC_BUSRESUME_MANUAL_RESUME) { host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; mmc_bus_put(host); return 0; } if (host->bus_ops && !host->bus_dead) { mmc_power_up(host); mmc_select_voltage(host, host->ocr); BUG_ON(!host->bus_ops->resume); err = host->bus_ops->resume(host); if (err) { printk(KERN_WARNING "%s: error %d during resume " "(card was removed?)\n", mmc_hostname(host), err); if (host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); /* no need to bother upper layers */ err = 0; } } mmc_bus_put(host); /* * We add a slight delay here so that resume can progress * in parallel. */ mmc_detect_change(host, 1); return err; }
/** * mmc_resume_host - resume a previously suspended host * @host: mmc host */ int mmc_resume_host(struct mmc_host *host) { int err = 0; mmc_bus_get(host); if (mmc_bus_manual_resume(host)) { #ifndef CONFIG_PM_RUNTIME host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; #endif mmc_bus_put(host); return 0; } if (host->bus_ops && !host->bus_dead) { if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { mmc_power_up(host); mmc_select_voltage(host, host->ocr); } BUG_ON(!host->bus_ops->resume); err = host->bus_ops->resume(host); if (err) { printk(KERN_WARNING "%s: error %d during resume " "(card was removed?)\n", mmc_hostname(host), err); err = 0; } } mmc_bus_put(host); /* * We add a slight delay here so that resume can progress * in parallel. */ if (!(host->pm_flags & MMC_PM_KEEP_POWER)) mmc_detect_change(host, 1); return err; }
/** * mmc_resume_host - resume a previously suspended host * @host: mmc host */ int mmc_resume_host(struct mmc_host *host) { int err = 0; mmc_bus_get(host); if (host->bus_resume_flags & MMC_BUSRESUME_MANUAL_RESUME) { host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; mmc_bus_put(host); return 0; } if (host->bus_ops && !host->bus_dead) { if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { mmc_power_up(host); mmc_select_voltage(host, host->ocr); } BUG_ON(!host->bus_ops->resume); err = host->bus_ops->resume(host); if (err) { printk(KERN_WARNING "%s: error %d during resume " "(card was removed?)\n", mmc_hostname(host), err); err = 0; } } mmc_bus_put(host); /* * We add a slight delay here so that resume can progress * in parallel. */ #if 1 /* ATHENV */ if (!host->card || host->card->type != MMC_TYPE_SDIO) #endif /* ATHENV */ mmc_detect_change(host, 1); return err; }
static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id) { struct mmc_host *host = dev_id; struct mmc_cd_gpio *cd = host->hotplug.handler_priv; int status; status = mmc_cd_get_status(host); if (unlikely(status < 0)) goto out; if (status ^ cd->status) { pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n", mmc_hostname(host), cd->status, status, (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ? "HIGH" : "LOW"); cd->status = status; /* Schedule a card detection after a debounce timeout */ mmc_detect_change(host, msecs_to_jiffies(100)); } out: return IRQ_HANDLED; }
static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id) { struct mmc_host *host = dev_id; struct mmc_cd_gpio *cd = host->hotplug.handler_priv; int status; status = mmc_cd_get_status(host); if (unlikely(status < 0)) goto out; if (status ^ cd->status) { pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n", mmc_hostname(host), cd->status, status, (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ? "HIGH" : "LOW"); cd->status = status; #ifdef CONFIG_MACH_LGE if(!status ) //active high & active low status value is low when sdcard ejected . { mmc_gpio_irq_flag =1; } else { mmc_gpio_irq_flag =0; } pr_info("%s: mmc_gpio_irq_flagd !!!!! %d\n",mmc_hostname(host),mmc_gpio_irq_flag ); #endif /* Schedule a card detection after a debounce timeout */ mmc_detect_change(host, msecs_to_jiffies(100)); } out: return IRQ_HANDLED; }
static void hi_mci_detect_card(unsigned long arg) { struct himci_host *host = (struct himci_host *)arg; unsigned int i, curr_status, status[3], detect_retry_count = 0; himci_assert(host); while (1) { for (i = 0; i < 3; i++) { status[i] = hi_mci_sys_card_detect(host); udelay(10); } if ((status[0] == status[1]) && (status[0] == status[2])) break; detect_retry_count++; if (detect_retry_count >= retry_count) { himci_error("this is a dithering,card detect error!"); goto err; } } curr_status = status[0]; if (curr_status != host->card_status) { himci_trace(2, "begin card_status = %d\n", host->card_status); host->card_status = curr_status; if (curr_status != CARD_UNPLUGED) { hi_mci_init_card(host); printk(KERN_INFO "card connected!\n"); } else printk(KERN_INFO "card disconnected!\n"); mmc_detect_change(host->mmc, 0); } err: mod_timer(&host->timer, jiffies + detect_time); }
/** * mmc_resume_host - resume a previously suspended host * @host: mmc host */ int mmc_resume_host(struct mmc_host *host) { #ifdef CONFIG_HUAWEI_WIFI_SDCC struct msmsdcc_host *sdcc_host = mmc_priv(host); #endif mmc_bus_get(host); if (host->bus_resume_flags & MMC_BUSRESUME_MANUAL_RESUME) { host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; mmc_bus_put(host); return 0; } if (host->bus_ops && !host->bus_dead) { mmc_power_up(host); mmc_select_voltage(host, host->ocr); BUG_ON(!host->bus_ops->resume); host->bus_ops->resume(host); } mmc_bus_put(host); /* * We add a slight delay here so that resume can progress * in parallel. */ #ifdef CONFIG_HUAWEI_WIFI_SDCC if (sdcc_host->pdev_id != ATH_WLAN_SLOT) { #endif mmc_detect_change(host, 1); #ifdef CONFIG_HUAWEI_WIFI_SDCC } #endif return 0; }
static ssize_t set_polling(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct mmc_host *mmc = dev_get_drvdata(dev); struct msmsdcc_host *host = mmc_priv(mmc); int value; unsigned long flags; sscanf(buf, "%d", &value); spin_lock_irqsave(&host->lock, flags); if (value) { mmc->caps |= MMC_CAP_NEEDS_POLL; mmc_detect_change(host->mmc, 0); } else { mmc->caps &= ~MMC_CAP_NEEDS_POLL; } #ifdef CONFIG_HAS_EARLYSUSPEND host->polling_enabled = mmc->caps & MMC_CAP_NEEDS_POLL; #endif spin_unlock_irqrestore(&host->lock, flags); return count; }
void sdhci_s3c_force_presence_change(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); printk(KERN_DEBUG "%s : Enter",__FUNCTION__); mmc_detect_change(host->mmc, msecs_to_jiffies(0)); }
void mmc_start_host(struct mmc_host *host) { mmc_power_off(host); mmc_detect_change(host, 0); }
static void sh_mmcif_detect(struct mmc_host *mmc) { mmc_detect_change(mmc, 0); }
static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id) { mmc_detect_change(dev_id, msecs_to_jiffies(100)); return IRQ_HANDLED; }
static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) { /* Schedule a card detection after a debounce timeout */ struct mmc_host *host = dev_id; struct mmc_gpio *ctx = host->slot.handler_priv; int status; #ifdef CONFIG_HUAWEI_KERNEL unsigned long duration =0; #endif /* * In case host->ops are not yet initialized return immediately. * The card will get detected later when host driver calls * mmc_add_host() after host->ops are initialized. */ if (!host->ops) goto out; if (host->ops->card_event) host->ops->card_event(host); status = mmc_gpio_get_status(host); if (unlikely(status < 0)) goto out; if (status ^ ctx->status) { pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n", mmc_hostname(host), ctx->status, status, (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ? "HIGH" : "LOW"); ctx->status = status; #ifdef CONFIG_HUAWEI_KERNEL duration = jiffies - msmsdcc_irqtime; /* current msmsdcc is present, add to handle dithering */ if (status) { /* the distance of two interrupts can not less than 7 second */ if (duration < (7 * HZ)) { duration = (7 * HZ) - duration; } else { /* 100 millisecond */ duration = msecs_to_jiffies(100); } } else { duration = msecs_to_jiffies(2000); } mmc_detect_change(host, duration); msmsdcc_irqtime = jiffies; #else /* Schedule a card detection after a debounce timeout */ mmc_detect_change(host, msecs_to_jiffies(200)); #endif } out: return IRQ_HANDLED; }
static void mmc_detect_callback(unsigned long data) { mmc_detect_change(mmc_detect.devid); }
static void imxmci_tasklet_fnc(unsigned long data) { struct imxmci_host *host = (struct imxmci_host *)data; u32 stat; unsigned int data_dir_mask = 0; /* STATUS_WR_CRC_ERROR_CODE_MASK */ int timeout = 0; if(atomic_read(&host->stuck_timeout) > 4) { char *what; timeout = 1; stat = MMC_STATUS; host->status_reg = stat; if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) what = "RESP+DMA"; else what = "RESP"; else if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events)) what = "DATA"; else what = "DMA"; else what = "???"; dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n", what, stat, MMC_INT_MASK); dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n", MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma)); dev_err(mmc_dev(host->mmc), "CMD%d, prevCMD%d, bus %d-bit, dma_size = 0x%x\n", host->cmd?host->cmd->opcode:0, host->prev_cmd_code, 1<<host->actual_bus_width, host->dma_size); } if(!host->present || timeout) host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ | STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR; if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) { clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events); stat = MMC_STATUS; /* * This is not required in theory, but there is chance to miss some flag * which clears automatically by mask write, FreeScale original code keeps * stat from IRQ time so do I */ stat |= host->status_reg; if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) { imxmci_busy_wait_for_status(host, &stat, STATUS_END_CMD_RESP | STATUS_ERR_MASK, 20, "imxmci_tasklet_fnc resp (ERRATUM #4)"); } if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) { if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) imxmci_cmd_done(host, stat); if(host->data && (stat & STATUS_ERR_MASK)) imxmci_data_done(host, stat); } if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) { stat |= MMC_STATUS; if(imxmci_cpu_driven_data(host, &stat)){ if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) imxmci_cmd_done(host, stat); atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m, &host->pending_events); imxmci_data_done(host, stat); } } } if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) && !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) { stat = MMC_STATUS; /* Same as above */ stat |= host->status_reg; if(host->dma_dir == DMA_TO_DEVICE) { data_dir_mask = STATUS_WRITE_OP_DONE; } else { data_dir_mask = STATUS_DATA_TRANS_DONE; } if(stat & data_dir_mask) { clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events); imxmci_data_done(host, stat); } } if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) { if(host->cmd) imxmci_cmd_done(host, STATUS_TIME_OUT_RESP); if(host->data) imxmci_data_done(host, STATUS_TIME_OUT_READ | STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR); if(host->req) imxmci_finish_request(host, host->req); mmc_detect_change(host->mmc, msecs_to_jiffies(100)); } }
static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id) { /* Schedule a card detection after a debounce timeout */ mmc_detect_change(dev_id, msecs_to_jiffies(100)); return IRQ_HANDLED; }
static irqreturn_t sdhci_acpi_sd_cd(int irq, void *dev_id) { mmc_detect_change(dev_id, msecs_to_jiffies(200)); return IRQ_HANDLED; }
void mmc_start_host(struct mmc_host *host) { mmc_power_off(host); mmc_detect_change(host, msecs_to_jiffies(host->init_delay)); }
static int __devinit sunximmc_probe(struct platform_device *pdev) { struct sunxi_mmc_host *smc_host = NULL; struct mmc_host *mmc = NULL; int ret = 0; char mmc_para[16] = {0}; int card_detmode = 0; SMC_MSG("%s: pdev->name: %s, pdev->id: %d\n", dev_name(&pdev->dev), pdev->name, pdev->id); mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev); if (!mmc) { SMC_ERR("mmc alloc host failed\n"); ret = -ENOMEM; goto probe_out; } smc_host = mmc_priv(mmc); memset((void*)smc_host, 0, sizeof(smc_host)); smc_host->mmc = mmc; smc_host->pdev = pdev; spin_lock_init(&smc_host->lock); tasklet_init(&smc_host->tasklet, sunximmc_tasklet, (unsigned long) smc_host); smc_host->cclk = 400000; smc_host->mod_clk = SMC_MAX_MOD_CLOCK(pdev->id); smc_host->clk_source = SMC_MOD_CLK_SRC(pdev->id); mmc->ops = &sunximmc_ops; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->caps = MMC_CAP_4_BIT_DATA|MMC_CAP_MMC_HIGHSPEED|MMC_CAP_SD_HIGHSPEED|MMC_CAP_SDIO_IRQ; mmc->f_min = 400000; mmc->f_max = SMC_MAX_IO_CLOCK(pdev->id); #ifdef MMC_PM_IGNORE_PM_NOTIFY if (pdev->id==3 && !mmc_pm_io_shd_suspend_host()) mmc->pm_flags = MMC_PM_IGNORE_PM_NOTIFY; #endif mmc->max_blk_count = 4095; mmc->max_blk_size = 4095; mmc->max_req_size = 4095 * 512; //32bit byte counter = 2^32 - 1 mmc->max_seg_size = mmc->max_req_size; mmc->max_segs = 256; if (sunximmc_resource_request(smc_host)) { SMC_ERR("%s: Failed to get resouce.\n", dev_name(&pdev->dev)); goto probe_free_host; } if (sunximmc_set_src_clk(smc_host)) { goto probe_free_host; } sunximmc_init_controller(smc_host); smc_host->power_on = 1; sunximmc_procfs_attach(smc_host); /* irq */ smc_host->irq = platform_get_irq(pdev, 0); if (smc_host->irq == 0) { dev_err(&pdev->dev, "Failed to get interrupt resouce.\n"); ret = -EINVAL; goto probe_free_resource; } if (request_irq(smc_host->irq, sunximmc_irq, 0, DRIVER_NAME, smc_host)) { dev_err(&pdev->dev, "Failed to request smc card interrupt.\n"); ret = -ENOENT; goto probe_free_irq; } disable_irq(smc_host->irq); /* add host */ ret = mmc_add_host(mmc); if (ret) { dev_err(&pdev->dev, "Failed to add mmc host.\n"); goto probe_free_irq; } platform_set_drvdata(pdev, mmc); //fetch card detecetd mode sprintf(mmc_para, "mmc%d_para", pdev->id); ret = script_parser_fetch(mmc_para, "sdc_detmode", &card_detmode, sizeof(int)); if (ret) { SMC_ERR("sdc fetch card detect mode failed\n"); } smc_host->cd_mode = card_detmode; if (smc_host->cd_mode == CARD_DETECT_BY_GPIO) { //initial card detect timer init_timer(&smc_host->cd_timer); smc_host->cd_timer.expires = jiffies + 1*HZ; smc_host->cd_timer.function = &sunximmc_cd_timer; smc_host->cd_timer.data = (unsigned long)smc_host; add_timer(&smc_host->cd_timer); smc_host->present = 0; } enable_irq(smc_host->irq); mutex_lock(&sw_host_rescan_mutex); if (smc_host->cd_mode == CARD_ALWAYS_PRESENT || sw_host_rescan_pending[pdev->id]) { smc_host->present = 1; mmc_detect_change(smc_host->mmc, msecs_to_jiffies(300)); } sw_host[pdev->id] = smc_host; mutex_unlock(&sw_host_rescan_mutex); SMC_MSG("mmc%d Probe: base:0x%p irq:%u dma:%u pdes:0x%p, ret %d.\n", pdev->id, smc_host->smc_base, smc_host->irq, smc_host->dma_no, smc_host->pdes, ret); goto probe_out; probe_free_irq: if (smc_host->irq) { free_irq(smc_host->irq, smc_host); } probe_free_resource: sunximmc_resource_release(smc_host); probe_free_host: mmc_free_host(mmc); probe_out: return ret; }
static int mmc_queue_thread(void *d) { struct mmc_queue *mq = d; struct request_queue *q = mq->queue; struct request *req; //ruanmeisi_20100603 int issue_ret = 0; #ifdef CONFIG_MMC_PERF_PROFILING ktime_t start, diff; struct mmc_host *host = mq->card->host; unsigned long bytes_xfer; #endif current->flags |= PF_MEMALLOC; down(&mq->thread_sem); do { req = NULL; //ruanmeisi_20100603 if (kthread_should_stop()) { remove_all_req(mq); break; } //end spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); if (!blk_queue_plugged(q)) req = blk_fetch_request(q); mq->req = req; spin_unlock_irq(q->queue_lock); if (!req) { if (kthread_should_stop()) { set_current_state(TASK_RUNNING); break; } up(&mq->thread_sem); schedule(); down(&mq->thread_sem); continue; } set_current_state(TASK_RUNNING); #ifdef CONFIG_MMC_AUTO_SUSPEND mmc_auto_suspend(mq->card->host, 0); #endif #ifdef CONFIG_MMC_BLOCK_PARANOID_RESUME if (mq->check_status) { struct mmc_command cmd; int retries = 3; do { int err; cmd.opcode = MMC_SEND_STATUS; cmd.arg = mq->card->rca << 16; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; mmc_claim_host(mq->card->host); err = mmc_wait_for_cmd(mq->card->host, &cmd, 5); mmc_release_host(mq->card->host); if (err) { printk(KERN_ERR "%s: failed to get status (%d)\n", __func__, err); msleep(5); retries--; continue; } printk(KERN_DEBUG "%s: status 0x%.8x\n", __func__, cmd.resp[0]); } while (retries && (!(cmd.resp[0] & R1_READY_FOR_DATA) || (R1_CURRENT_STATE(cmd.resp[0]) == 7))); mq->check_status = 0; } #endif //ruanmeisi_20100529 #ifdef CONFIG_MMC_PERF_PROFILING bytes_xfer = blk_rq_bytes(req); if (rq_data_dir(req) == READ) { start = ktime_get(); issue_ret = mq->issue_fn(mq, req); diff = ktime_sub(ktime_get(), start); host->perf.rbytes_mmcq += bytes_xfer; host->perf.rtime_mmcq = ktime_add(host->perf.rtime_mmcq, diff); } else { start = ktime_get(); issue_ret = mq->issue_fn(mq, req); diff = ktime_sub(ktime_get(), start); host->perf.wbytes_mmcq += bytes_xfer; host->perf.wtime_mmcq = ktime_add(host->perf.wtime_mmcq, diff); } #else issue_ret = mq->issue_fn(mq, req); #endif //ruanmeisi if (0 == issue_ret) { int err; mmc_claim_host(mq->card->host); err = mmc_send_status(mq->card, NULL); mmc_release_host(mq->card->host); if (err) { printk(KERN_ERR "rms:%s: failed to get status (%d) maybe the card is removed\n", __func__, err); //sdcard is removed? mmc_detect_change(mq->card->host, 0); msleep(500); //set_current_state(TASK_INTERRUPTIBLE); //schedule_timeout(HZ / 2); continue; } } } while (1); up(&mq->thread_sem); return 0; }
static irqreturn_t goldfish_mmc_irq(int irq, void *dev_id) { struct goldfish_mmc_host * host = (struct goldfish_mmc_host *)dev_id; u16 status; int end_command = 0; int end_transfer = 0; int transfer_error = 0; int state_changed = 0; int cmd_timeout = 0; while ((status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS)) != 0) { GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status); if (status & MMC_STAT_END_OF_CMD) { end_command = 1; } if (status & MMC_STAT_END_OF_DATA) { end_transfer = 1; } if (status & MMC_STAT_STATE_CHANGE) { state_changed = 1; } if (status & MMC_STAT_CMD_TIMEOUT) { end_command = 0; cmd_timeout = 1; } } if (cmd_timeout) { struct mmc_request *mrq = host->mrq; mrq->cmd->error = -ETIMEDOUT; host->mrq = NULL; mmc_request_done(host->mmc, mrq); } if (end_command) { goldfish_mmc_cmd_done(host, host->cmd); } if (transfer_error) goldfish_mmc_xfer_done(host, host->data); else if (end_transfer) { host->dma_done = 1; goldfish_mmc_end_of_data(host, host->data); } else if (host->data != NULL && host->mrq->cmd->opcode == 13) { /* * WORKAROUND -- after porting this driver from 2.6 to 3.4, * this case pops up during device initialization. * This happens as the host stack is sending ACMD13 which * involves data read while goldfish emulator implementation * only supports CMD13 which does not have data phase. * The workaround works by passing garbage result to the stack. * TODO -- To implement proper response */ host->dma_done = 1; goldfish_mmc_end_of_data(host, host->data); } if (state_changed) { u32 state = GOLDFISH_MMC_READ(host, MMC_STATE); pr_info("%s: Card detect now %d\n", __func__, (state & MMC_STATE_INSERTED)); mmc_detect_change(host->mmc, 0); } if (!end_command && !end_transfer && !transfer_error && !state_changed && !cmd_timeout) { status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS); dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status); if (status != 0) { GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status); GOLDFISH_MMC_WRITE(host, MMC_INT_ENABLE, 0); } } return IRQ_HANDLED; }
static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev) { mmc_detect_change(dev_get_drvdata(&pdev->dev), msecs_to_jiffies(100)); }