static void omap_hsmmc_status_notify_cb(int card_present, void *dev_id) { struct mmc_omap_host *host = dev_id; struct omap_mmc_slot_data *slot = &mmc_slot(host); printk(KERN_DEBUG "%s: card_present %d\n", mmc_hostname(host->mmc), card_present); host->carddetect = slot->card_detect(slot->card_detect_irq); sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); if (host->carddetect) { mmc_detect_change(host->mmc, (HZ * 200) / 1000); } else { mmc_omap_reset_controller_fsm(host, SRD); mmc_detect_change(host->mmc, (HZ * 50) / 1000); } }
/* * Work Item to notify the core about card insertion/removal */ static void mmc_omap_detect(struct work_struct *work) { struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, mmc_carddetect_work); struct omap_mmc_slot_data *slot = &mmc_slot(host); omap_hsmmc_enable_clks(host); host->carddetect = slot->card_detect(slot->card_detect_irq); sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); if (host->carddetect) { host->mmc->removed = 0; mmc_detect_change(host->mmc, (HZ * 200) / 1000); } else { mmc_omap_reset_controller_fsm(host, SRD); host->mmc->removed = 1; mmc_detect_change(host->mmc, (HZ * 50) / 1000); } }
/* * MMC controller IRQ handler */ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) { struct mmc_omap_host *host = dev_id; struct mmc_data *data; int end_cmd = 0, end_trans = 0, status; omap_hsmmc_enable_clks(host); if (host->cmd == NULL && host->data == NULL) { OMAP_HSMMC_WRITE(host->base, STAT, OMAP_HSMMC_READ(host->base, STAT)); return IRQ_HANDLED; } data = host->data; status = OMAP_HSMMC_READ(host->base, STAT); dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); if (status & ERR) { #ifdef CONFIG_MMC_DEBUG mmc_omap_report_irq(host, status); #endif if ((status & CMD_TIMEOUT) || (status & CMD_CRC) || (status & CMD_CEB) || (status & CMD_CIE)) { if (host->cmd) { if (status & CMD_TIMEOUT) { mmc_omap_reset_controller_fsm(host, SRC); host->cmd->error = -ETIMEDOUT; } else { host->cmd->error = -EILSEQ; } end_cmd = 1; } if (host->data) { mmc_dma_cleanup(host, -ETIMEDOUT); mmc_omap_reset_controller_fsm(host, SRD); } } if ((status & DATA_TIMEOUT) || (status & DATA_CRC) || (status & DATA_DEB)) { if (host->data) { if (status & DATA_TIMEOUT) mmc_dma_cleanup(host, -ETIMEDOUT); else mmc_dma_cleanup(host, -EILSEQ); mmc_omap_reset_controller_fsm(host, SRD); end_trans = 1; } } if (status & CARD_ERR) { dev_dbg(mmc_dev(host->mmc), "Ignoring card err CMD%d\n", host->cmd->opcode); if (host->cmd) end_cmd = 1; if (host->data) end_trans = 1; } } OMAP_HSMMC_WRITE(host->base, STAT, status); if (end_cmd || (status & CC)) mmc_omap_cmd_done(host, host->cmd); if (end_trans || (status & TC)) mmc_omap_xfer_done(host, data); /* Perform one dummy read to ensure the previous write actually went through */ status = OMAP_HSMMC_READ(host->base, STAT); return IRQ_HANDLED; }