/* * Card detection callback from host. */ static void mmc_detect(struct mmc_host *host) { int err; BUG_ON(!host); BUG_ON(!host->card); mmc_claim_host(host); /* * Just check if our card has been removed. */ err = mmc_send_status(host->card, NULL); mmc_release_host(host); if (err) { mmc_remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); } }
/** * mmc_suspend_host - suspend a host * @host: mmc host * @state: suspend mode (PM_SUSPEND_xxx) */ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) { cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) host->bus_ops->suspend(host); if (!host->bus_ops->resume) { 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_power_off(host); return 0; }
/** * mmc_suspend_host - suspend a host * @host: mmc host * @state: suspend mode (PM_SUSPEND_xxx) */ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) { int err = 0; if (mmc_bus_needs_resume(host)) return 0; if (host->caps & MMC_CAP_DISABLE) cancel_delayed_work(&host->disable); cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); if (err == -ENOSYS || !host->bus_ops->resume) { /* * We simply "remove" the card in this case. * It will be redetected on resume. */ if (host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); err = 0; } } mmc_bus_put(host); if (!err) mmc_power_off(host); return err; }
void mmc_stop_host(struct mmc_host *host) { #ifdef CONFIG_MMC_DEBUG unsigned long flags; spin_lock_irqsave(&host->lock, flags); host->removed = 1; spin_unlock_irqrestore(&host->lock, flags); #endif if (host->caps & MMC_CAP_DISABLE) cancel_delayed_work(&host->disable); if (unlikely(cancel_delayed_work(&host->detect))) { atomic_dec(&wakelock_refs); } mmc_flush_scheduled_work(); /* clear pm flags now and let card drivers set them as needed */ host->pm_flags = 0; 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); return; } mmc_bus_put(host); BUG_ON(host->card); mmc_power_off(host); }
/* * Starting point for SD card init. */ int mmc_attach_sd(struct mmc_host *host) { int err; u32 ocr; #ifdef CONFIG_MMC_PARANOID_SD_INIT int retries; #endif BUG_ON(!host); WARN_ON(!host->claimed); /* Make sure we are at 3.3V signalling voltage */ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); if (err) return err; err = mmc_send_app_op_cond(host, 0, &ocr); if (err) return err; mmc_sd_attach_bus_ops(host); if (host->ocr_avail_sd) host->ocr_avail = host->ocr_avail_sd; /* * We need to get OCR a different way for SPI. */ if (mmc_host_is_spi(host)) { mmc_go_idle(host); err = mmc_spi_read_ocr(host, 0, &ocr); if (err) goto err; } /* * Sanity check the voltages that the card claims to * support. */ if (ocr & 0x7F) { printk(KERN_WARNING "%s: card claims to support voltages " "below the defined range. These will be ignored.\n", mmc_hostname(host)); ocr &= ~0x7F; } if ((ocr & MMC_VDD_165_195) && !(host->ocr_avail_sd & MMC_VDD_165_195)) { printk(KERN_WARNING "%s: SD card claims to support the " "incompletely defined 'low voltage range'. This " "will be ignored.\n", mmc_hostname(host)); ocr &= ~MMC_VDD_165_195; } host->ocr = mmc_select_voltage(host, ocr); /* * Can we support the voltage(s) of the card(s)? */ if (!host->ocr) { err = -EINVAL; goto err; } /* * Detect and init the card. */ #ifdef CONFIG_MMC_PARANOID_SD_INIT retries = 5; while (retries) { err = mmc_sd_init_card(host, host->ocr, NULL); if (err) { retries--; continue; } break; } if (!retries) { printk(KERN_ERR "%s: mmc_sd_init_card() failure (err = %d)\n", mmc_hostname(host), err); goto err; } #else err = mmc_sd_init_card(host, host->ocr, NULL); if (err) goto err; #endif mmc_release_host(host); err = mmc_add_card(host->card); mmc_claim_host(host); if (err) goto remove_card; return 0; remove_card: mmc_release_host(host); mmc_remove_card(host->card); host->card = NULL; mmc_claim_host(host); err: mmc_detach_bus(host); printk(KERN_ERR "%s: error %d whilst initialising SD card\n", mmc_hostname(host), err); return err; }
/* * Starting point for MMC card init. */ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) { struct mmc_card *card; int err; u32 cid[4]; unsigned int max_dtr; BUG_ON(!host); BUG_ON(!host->claimed); mmc_attach_bus(host, &mmc_ops); host->ocr = mmc_select_voltage(host, ocr); /* * Can we support the voltage of the card? */ if (!host->ocr) goto err; /* * Since we're changing the OCR value, we seem to * need to tell some cards to go back to the idle * state. We wait 1ms to give cards time to * respond. */ mmc_go_idle(host); /* The extra bit indicates that we support high capacity */ mmc_send_op_cond(host, host->ocr | (1 << 30), NULL); /* * Fetch CID from card. */ err = mmc_all_send_cid(host, cid); if (err != MMC_ERR_NONE) goto err; /* * Allocate card structure. */ card = mmc_alloc_card(host); if (IS_ERR(card)) goto err; card->type = MMC_TYPE_MMC; card->rca = 1; memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); /* * Set card RCA. */ err = mmc_set_relative_addr(card); if (err != MMC_ERR_NONE) goto free_card; mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); /* * Fetch CSD from card. */ err = mmc_send_csd(card, card->raw_csd); if (err != MMC_ERR_NONE) goto free_card; mmc_decode_csd(card); mmc_decode_cid(card); /* * Fetch and process extened CSD. * This will switch into high-speed and wide bus modes, * as available. */ err = mmc_select_card(card); if (err != MMC_ERR_NONE) goto free_card; err = mmc_process_ext_csd(card); if (err != MMC_ERR_NONE) goto free_card; /* * Compute bus speed. */ max_dtr = (unsigned int)-1; if (mmc_card_highspeed(card)) { if (max_dtr > card->ext_csd.hs_max_dtr) max_dtr = card->ext_csd.hs_max_dtr; } else if (max_dtr > card->csd.max_dtr) { max_dtr = card->csd.max_dtr; } mmc_set_clock(host, max_dtr); host->card = card; mmc_release_host(host); err = mmc_register_card(card); if (err) goto reclaim_host; return 0; reclaim_host: mmc_claim_host(host); free_card: mmc_remove_card(card); host->card = NULL; err: mmc_detach_bus(host); mmc_release_host(host); return 0; }
void mmc_rescan(struct work_struct *work) { struct mmc_host *host = container_of(work, struct mmc_host, detect.work); u32 ocr; int err; int extend_wakelock = 0; mmc_bus_get(host); /* if there is a card registered, check whether it is still present */ if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) { if(host->ops->get_cd && host->ops->get_cd(host) == 0) { if(host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); } else host->bus_ops->detect(host); } /* If the card was removed the bus will be marked * as dead - extend the wakelock so userspace * can respond */ if (host->bus_dead) extend_wakelock = 1; mmc_bus_put(host); mmc_bus_get(host); /* if there still is a card present, stop here */ if (host->bus_ops != NULL) { mmc_bus_put(host); goto out; } /* detect a newly inserted card */ /* * Only we can add a new handler, so it's safe to * release the lock here. */ mmc_bus_put(host); if (host->ops->get_cd && host->ops->get_cd(host) == 0) goto out; mmc_claim_host(host); mmc_power_up(host); mmc_go_idle(host); mmc_send_if_cond(host, host->ocr_avail); /* * First we search for SDIO... */ printk(KERN_DEBUG "*** DEBUG : First we search for SDIO...(%d)***\n", host->index); err = mmc_send_io_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sdio(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } /* * ...then normal SD... */ printk(KERN_DEBUG "*** DEBUG : ...then normal SD...(%d) ***\n", host->index); err = mmc_send_app_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sd(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } /* * ...and finally MMC. */ printk(KERN_DEBUG "*** DEBUG : ...and finally MMC. (%d)***\n", host->index); err = mmc_send_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_mmc(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } mmc_release_host(host); mmc_power_off(host); out: #if 0 //if (extend_wakelock) // wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); //else // wake_unlock(&mmc_delayed_work_wake_lock); #else if (atomic_dec_return(&wakelock_refs) > 0) { printk(KERN_DEBUG "Another host want the wakelock : %d\n", atomic_read(&wakelock_refs)); } else { printk(KERN_DEBUG "mmc%d: wake_lock_timeout 1sec %d\n", host->index, atomic_read(&wakelock_refs)); wake_lock_timeout(&mmc_delayed_work_wake_lock, msecs_to_jiffies(1000)); } #endif if (host->caps & MMC_CAP_NEEDS_POLL) mmc_schedule_delayed_work(&host->detect, HZ); }
void mmc_rescan(struct work_struct *work) { struct mmc_host *host = container_of(work, struct mmc_host, detect.work); u32 ocr; int err; int extend_wakelock = 0; mmc_bus_get(host); /* if there is a card registered, check whether it is still present */ if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) { if(host->ops->get_cd && host->ops->get_cd(host) == 0) { if(host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); } else host->bus_ops->detect(host); } /* If the card was removed the bus will be marked * as dead - extend the wakelock so userspace * can respond */ if (host->bus_dead) extend_wakelock = 1; mmc_bus_put(host); mmc_bus_get(host); /* if there still is a card present, stop here */ if (host->bus_ops != NULL) { mmc_bus_put(host); goto out; } /* detect a newly inserted card */ /* * Only we can add a new handler, so it's safe to * release the lock here. */ mmc_bus_put(host); if (host->ops->get_cd && host->ops->get_cd(host) == 0) goto out; mmc_claim_host(host); mmc_power_up(host); mmc_go_idle(host); mmc_send_if_cond(host, host->ocr_avail); /* * First we search for SDIO... */ printk(KERN_DEBUG "*** DEBUG : First we search for SDIO...(%d)***\n", host->index); err = mmc_send_io_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sdio(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } /* * ...then normal SD... */ printk(KERN_DEBUG "*** DEBUG : ...then normal SD...(%d) ***\n", host->index); err = mmc_send_app_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sd(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } /* * ...and finally MMC. */ printk(KERN_DEBUG "*** DEBUG : ...and finally MMC. (%d)***\n", host->index); err = mmc_send_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_mmc(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } mmc_release_host(host); mmc_power_off(host); out: if (--wakelock_refs > 0) { pr_debug("%s: other host want the wakelock\n", mmc_hostname(host)); } else { #if defined(CONFIG_MMC_BLOCK_DEFERRED_RESUME) && defined(CONFIG_MACH_S5PC110_P1) wake_lock_timeout(&mmc_delayed_work_wake_lock, 3*HZ); #else /* CONFIG_MMC_BLOCK_DEFERRED_RESUME && CONFIG_MACH_S5PC110_P1 */ if (extend_wakelock) wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); else wake_unlock(&mmc_delayed_work_wake_lock); #endif /* CONFIG_MMC_BLOCK_DEFERRED_RESUME && CONFIG_MACH_S5PC110_P1 */ } if (host->caps & MMC_CAP_NEEDS_POLL) mmc_schedule_delayed_work(&host->detect, HZ); }
/** * mmc_suspend_host - suspend a host * @host: mmc host */ int mmc_suspend_host(struct mmc_host *host) { int err = 0; if (mmc_bus_needs_resume(host)) return 0; if (host->caps & MMC_CAP_DISABLE) cancel_delayed_work(&host->disable); cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { /* * A long response time is not acceptable for device drivers * when doing suspend. Prevent mmc_claim_host in the suspend * sequence, to potentially wait "forever" by trying to * pre-claim the host. * * Skip try claim host for SDIO cards, doing so fixes deadlock * conditions. The function driver suspend may again call into * SDIO driver within a different context for enabling power * save mode in the card and hence wait in mmc_claim_host * causing deadlock. */ if (!(host->card && mmc_card_sdio(host->card))) if (!mmc_try_claim_host(host)) err = -EBUSY; if (!err) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); if (!(host->card && mmc_card_sdio(host->card))) mmc_do_release_host(host); if (err == -ENOSYS || !host->bus_ops->resume) { /* * We simply "remove" the card in this case. * It will be redetected on resume. */ if (host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_power_off(host); mmc_release_host(host); host->pm_flags = 0; err = 0; } } } #ifdef CONFIG_PM_RUNTIME if (mmc_bus_manual_resume(host)) host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; #endif mmc_bus_put(host); if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER)) mmc_power_off(host); return err; }
void mmc_rescan(struct work_struct *work) { struct mmc_host *host = container_of(work, struct mmc_host, detect.work); u32 ocr; int err; unsigned long flags; int extend_wakelock = 0; spin_lock_irqsave(&host->lock, flags); if (host->rescan_disable) { spin_unlock_irqrestore(&host->lock, flags); if (atomic_dec_return(&wakelock_refs) > 0) { printk(KERN_DEBUG "Another host want the wakelock : %d\n", atomic_read(&wakelock_refs)); }else { printk(KERN_DEBUG "unlock case1 : mmc%d: wake_lock_timeout 0.5 sec %d\n", host->index, atomic_read(&wakelock_refs)); wake_lock_timeout(&mmc_delayed_work_wake_lock, msecs_to_jiffies(500)); } return; } spin_unlock_irqrestore(&host->lock, flags); //[NAGSM_Android_HDLNC_SDcard_shinjonghyun_20100504 : mutual exclusion when MoviNand and SD cardusing using this funtion // mutex_lock(&host->carddetect_lock); //]NAGSM_Android_HDLNC_SDcard_shinjonghyun_20100504 : mutual exclusion when MoviNand and SD cardusing using this funtion mmc_bus_get(host); /* if there is a card registered, check whether it is still present */ if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) { if(host->ops->get_cd && host->ops->get_cd(host) == 0) { if(host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); } else host->bus_ops->detect(host); } /* If the card was removed the bus will be marked * as dead - extend the wakelock so userspace * can respond */ if (host->bus_dead) extend_wakelock = 1; mmc_bus_put(host); mmc_bus_get(host); printk(KERN_DEBUG "*** DEBUG : start %s (mmc%d)***\n", __func__, host->index); /* if there still is a card present, stop here */ if (host->bus_ops != NULL) { mmc_bus_put(host); goto out; } /* detect a newly inserted card */ /* * Only we can add a new handler, so it's safe to * release the lock here. */ mmc_bus_put(host); if (host->ops->get_cd && host->ops->get_cd(host) == 0) goto out; mmc_claim_host(host); mmc_power_up(host); sdio_reset(host); mmc_go_idle(host); mmc_send_if_cond(host, host->ocr_avail); /* * First we search for SDIO... */ printk(KERN_DEBUG "*** DEBUG : First we search for SDIO...(%d)***\n", host->index); err = mmc_send_io_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sdio(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } /* * ...then normal SD... */ printk(KERN_DEBUG "*** DEBUG : ...then normal SD...(%d) ***\n", host->index); err = mmc_send_app_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sd(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } /* * ...and finally MMC. */ printk(KERN_DEBUG "*** DEBUG : ...and finally MMC. (%d)***\n", host->index); err = mmc_send_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_mmc(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } printk(KERN_DEBUG "*** DEBUG : end %s (mmc%d)***\n", __func__, host->index); mmc_release_host(host); mmc_power_off(host); out: #if 0 //if (extend_wakelock) // wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); //else // wake_unlock(&mmc_delayed_work_wake_lock); #else if (atomic_dec_return(&wakelock_refs) > 0) { printk(KERN_DEBUG "Another host want the wakelock : %d\n", atomic_read(&wakelock_refs)); } else { printk(KERN_DEBUG "unlock case2 : mmc%d: wake_lock_timeout 0.5 sec %d\n", host->index, atomic_read(&wakelock_refs)); wake_lock_timeout(&mmc_delayed_work_wake_lock, msecs_to_jiffies(500)); } #endif if (host->caps & MMC_CAP_NEEDS_POLL) mmc_schedule_delayed_work(&host->detect, HZ); //[NAGSM_Android_HDLNC_SDcard_shinjonghyun_20100504 : mutual exclusion when MoviNand and SD cardusing using this funtion // mutex_unlock(&host->carddetect_lock); //]NAGSM_Android_HDLNC_SDcard_shinjonghyun_20100504 : mutual exclusion when MoviNand and SD cardusing using this funtion }
int mmc_attach_sd(struct mmc_host *host, u32 ocr) { int err; #ifdef CONFIG_MMC_PARANOID_SD_INIT int retries; #endif BUG_ON(!host); WARN_ON(!host->claimed); mmc_sd_attach_bus_ops(host); if (mmc_host_is_spi(host)) { mmc_go_idle(host); err = mmc_spi_read_ocr(host, 0, &ocr); if (err) goto err; } if (ocr & 0x7F) { printk(KERN_WARNING "%s: card claims to support voltages " "below the defined range. These will be ignored.\n", mmc_hostname(host)); ocr &= ~0x7F; } if (ocr & MMC_VDD_165_195) { printk(KERN_WARNING "%s: SD card claims to support the " "incompletely defined 'low voltage range'. This " "will be ignored.\n", mmc_hostname(host)); ocr &= ~MMC_VDD_165_195; } host->ocr = mmc_select_voltage(host, ocr); if (!host->ocr) { err = -EINVAL; goto err; } #ifdef CONFIG_MMC_PARANOID_SD_INIT retries = 5; while (retries) { err = mmc_sd_init_card(host, host->ocr, NULL); if (err) { retries--; continue; } break; } if (!retries) { printk(KERN_ERR "%s: mmc_sd_init_card() failure (err = %d)\n", mmc_hostname(host), err); goto err; } #else err = mmc_sd_init_card(host, host->ocr, NULL); if (err) goto err; #endif mmc_release_host(host); err = mmc_add_card(host->card); if (err) goto remove_card; return 0; remove_card: mmc_remove_card(host->card); host->card = NULL; mmc_claim_host(host); err: mmc_detach_bus(host); mmc_release_host(host); printk(KERN_ERR "%s: error %d whilst initialising SD card\n", mmc_hostname(host), err); return err; }
/* Do the card removal on suspend if card is assumed removeable * Do that in pm notifier while userspace isn't yet frozen, so we will be able * to sync the card. */ int mmc_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused) { struct mmc_host *host = container_of( notify_block, struct mmc_host, pm_notify); unsigned long flags; switch (mode) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: spin_lock_irqsave(&host->lock, flags); if (mmc_bus_needs_resume(host)) { spin_unlock_irqrestore(&host->lock, flags); break; } host->rescan_disable = 1; spin_unlock_irqrestore(&host->lock, flags); cancel_delayed_work_sync(&host->detect); if (!host->bus_ops || host->bus_ops->suspend) break; if (host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); break; case PM_POST_SUSPEND: case PM_POST_HIBERNATION: spin_lock_irqsave(&host->lock, flags); if (mmc_bus_manual_resume(host)) { spin_unlock_irqrestore(&host->lock, flags); break; } host->rescan_disable = 0; spin_unlock_irqrestore(&host->lock, flags); #if defined(CONFIG_MACH_ACER_A4) || defined(CONFIG_MACH_ACER_A5) printk("*** %s: trigger polling\n", __func__); if (host && host->card && host->card->cis.vendor == ATHR_MANUF_CODE) { printk("*** %s: WIFI slot. Skip detect.\n", __func__); return 0; } #endif #if defined(CONFIG_MACH_ACER_A4) if (host && !strcmp(mmc_hostname(host), "mmc1")) { pr_info("*** %s: mmc1. Skip detect.\n", __func__); return 0; } #endif #if defined(CONFIG_MACH_ACER_A5) if (host && !strcmp(mmc_hostname(host), "mmc0")) { pr_info("*** %s: mmc0 slot. Skip detect.\n", __func__); return 0; } if (host && !strcmp(mmc_hostname(host), "mmc2")) { pr_info("*** %s: mmc2 slot. Skip detect.\n", __func__); return 0; } #endif mmc_detect_change(host, 0); } return 0; }
/** * 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) { 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); #if defined(CONFIG_MACH_ACER_A4) || defined(CONFIG_MACH_ACER_A5) 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 */ #endif err = 0; } } mmc_bus_put(host); #if defined(CONFIG_MACH_ACER_A4) || defined(CONFIG_MACH_ACER_A5) /* ATHENV */ if (host && host->card) { struct mmc_card *card = host->card; if (card->cis.vendor == ATHR_MANUF_CODE) { /* WIFI doesn't need to detect again. */ return 0; } } /* ATHENV */ #endif #if defined(CONFIG_MACH_ACER_A4) if (host && !strcmp(mmc_hostname(host), "mmc1")) { pr_info("*** %s: mmc1. Skip detect.\n", __func__); return 0; } #endif #if defined(CONFIG_MACH_ACER_A5) if (host && !strcmp(mmc_hostname(host), "mmc0")) { pr_info("*** %s: mmc0. Skip detect.\n", __func__); return 0; } if (host && !strcmp(mmc_hostname(host), "mmc2")) { pr_info("*** %s: mmc2. Skip detect.\n", __func__); return 0; } #endif return err; }
void mmc_rescan(struct work_struct *work) { struct mmc_host *host = container_of(work, struct mmc_host, detect.work); u32 ocr; int err; unsigned long flags; int extend_wakelock = 0; spin_lock_irqsave(&host->lock, flags); if (host->rescan_disable) { spin_unlock_irqrestore(&host->lock, flags); return; } spin_unlock_irqrestore(&host->lock, flags); mmc_bus_get(host); /* if there is a card registered, check whether it is still present */ if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) { if(host->ops->get_cd && host->ops->get_cd(host) == 0) { if(host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); } else host->bus_ops->detect(host); } /* If the card was removed the bus will be marked * as dead - extend the wakelock so userspace * can respond */ if (host->bus_dead) extend_wakelock = 1; mmc_bus_put(host); mmc_bus_get(host); /* if there still is a card present, stop here */ if (host->bus_ops != NULL) { mmc_bus_put(host); goto out; } /* detect a newly inserted card */ /* * Only we can add a new handler, so it's safe to * release the lock here. */ mmc_bus_put(host); if (host->ops->get_cd && host->ops->get_cd(host) == 0) goto out; mmc_claim_host(host); mmc_power_up(host); sdio_reset(host); mmc_go_idle(host); mmc_send_if_cond(host, host->ocr_avail); /* * First we search for SDIO... */ err = mmc_send_io_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sdio(host, ocr)){ printk("mmc_attach_sdio err\n"); mmc_power_off(host); } printk("mmc_attach_sdio end\n"); extend_wakelock = 1; goto out; } /* * ...then normal SD... */ err = mmc_send_app_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sd(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } /* * ...and finally MMC. */ err = mmc_send_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_mmc(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } mmc_release_host(host); mmc_power_off(host); out: if (extend_wakelock) wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); else wake_unlock(&mmc_delayed_work_wake_lock); if (host->caps & MMC_CAP_NEEDS_POLL) mmc_schedule_delayed_work(&host->detect, HZ); }
/* * Starting point for SD card init. */ int mmc_attach_sd(struct mmc_host *host) { int err; u32 ocr; BUG_ON(!host); WARN_ON(!host->claimed); err = mmc_send_app_op_cond(host, 0, &ocr); if (err) return err; mmc_sd_attach_bus_ops(host); if (host->ocr_avail_sd) host->ocr_avail = host->ocr_avail_sd; /* * We need to get OCR a different way for SPI. */ if (mmc_host_is_spi(host)) { mmc_go_idle(host); err = mmc_spi_read_ocr(host, 0, &ocr); if (err) goto err; } /* * Sanity check the voltages that the card claims to * support. */ if (ocr & 0x7F) { printk(KERN_WARNING "%s: card claims to support voltages " "below the defined range. These will be ignored.\n", mmc_hostname(host)); ocr &= ~0x7F; } if ((ocr & MMC_VDD_165_195) && !(host->ocr_avail_sd & MMC_VDD_165_195)) { printk(KERN_WARNING "%s: SD card claims to support the " "incompletely defined 'low voltage range'. This " "will be ignored.\n", mmc_hostname(host)); ocr &= ~MMC_VDD_165_195; } host->ocr = mmc_select_voltage(host, ocr); /* * Can we support the voltage(s) of the card(s)? */ if (!host->ocr) { err = -EINVAL; goto err; } /* * Detect and init the card. */ err = mmc_sd_init_card(host, host->ocr, NULL); if (err) goto err; mmc_release_host(host); err = mmc_add_card(host->card); mmc_claim_host(host); if (err) goto remove_card; return 0; remove_card: mmc_release_host(host); mmc_remove_card(host->card); host->card = NULL; mmc_claim_host(host); err: mmc_detach_bus(host); printk(KERN_ERR "%s: error %d whilst initialising SD card\n", mmc_hostname(host), err); return err; }
/* * Starting point for SD card init. */ int mmc_attach_sd(struct mmc_host *host, u32 ocr) { int err; #ifdef CONFIG_MMC_PARANOID_SD_INIT int retries; #endif BUG_ON(!host); WARN_ON(!host->claimed); mmc_sd_attach_bus_ops(host); /* * We need to get OCR a different way for SPI. */ if (mmc_host_is_spi(host)) { mmc_go_idle(host); err = mmc_spi_read_ocr(host, 0, &ocr); if (err) goto err; } /* * Sanity check the voltages that the card claims to * support. */ if (ocr & 0x7F) { printk(KERN_WARNING "%s: card claims to support voltages " "below the defined range. These will be ignored.\n", mmc_hostname(host)); ocr &= ~0x7F; } if (ocr & MMC_VDD_165_195) { printk(KERN_WARNING "%s: SD card claims to support the " "incompletely defined 'low voltage range'. This " "will be ignored.\n", mmc_hostname(host)); ocr &= ~MMC_VDD_165_195; } host->ocr = mmc_select_voltage(host, ocr); /* * Can we support the voltage(s) of the card(s)? */ if (!host->ocr) { err = -EINVAL; goto err; } /* * Detect and init the card. */ #ifdef CONFIG_MMC_PARANOID_SD_INIT retries = 5; while (retries) { err = mmc_sd_init_card(host, host->ocr, NULL); if (err) { #if 1 if (!strcmp(mmc_hostname(host), "mmc2")) { g_sd_power_dircect_ctrl = 1; mmc_power_off(host); mdelay(200); mmc_power_up(host); mmc_select_voltage(host, host->ocr); mdelay(10); g_sd_power_dircect_ctrl = 0; printk("\n(SD initialization) retry count=%d\n",retries); } #endif retries--; continue; } break; } if (!retries) { printk(KERN_ERR "%s: mmc_sd_init_card() failure (err = %d)\n", mmc_hostname(host), err); goto err; } #else err = mmc_sd_init_card(host, host->ocr, NULL); if (err) goto err; #endif mmc_release_host(host); err = mmc_add_card(host->card); if (err) goto remove_card; return 0; remove_card: mmc_remove_card(host->card); host->card = NULL; mmc_claim_host(host); err: mmc_detach_bus(host); mmc_release_host(host); printk(KERN_ERR "%s: error %d whilst initialising SD card\n", mmc_hostname(host), err); return err; }
void mmc_rescan(struct work_struct *work) { struct mmc_host *host = container_of(work, struct mmc_host, detect.work); u32 ocr; int err; int extend_wakelock = 0; mmc_bus_get(host); if (host->ops->get_cd && host->ops->get_cd(host) == 0) { 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); } extend_wakelock = 1; } else { if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) { if (host->index == 1) { if (!q_wlan_flag) host->bus_ops->detect(host); printk("[MMC]> host name %s, q_wlan_flag: %d\n", mmc_hostname(host), q_wlan_flag); } else { host->bus_ops->detect(host); printk("[MMC]> host name %s, q_wlan_flag: %d\n", mmc_hostname(host), q_wlan_flag); } } if (host->bus_dead) extend_wakelock = 1; } #if 0 /* if there is a card registered, check whether it is still present */ if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) host->bus_ops->detect(host); /* If the card was removed the bus will be marked * as dead - extend the wakelock so userspace * can respond */ if (host->bus_dead) extend_wakelock = 1; #endif mmc_bus_put(host); mmc_bus_get(host); /* if there still is a card present, stop here */ if (host->bus_ops != NULL) { mmc_bus_put(host); goto out; } /* detect a newly inserted card */ /* * Only we can add a new handler, so it's safe to * release the lock here. */ mmc_bus_put(host); if (host->ops->get_cd && host->ops->get_cd(host) == 0) goto out; mmc_claim_host(host); mmc_power_up(host); mmc_go_idle(host); mmc_send_if_cond(host, host->ocr_avail); /* * First we search for SDIO... */ err = mmc_send_io_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sdio(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } /* * ...then normal SD... */ err = mmc_send_app_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_sd(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } /* * ...and finally MMC. */ err = mmc_send_op_cond(host, 0, &ocr); if (!err) { if (mmc_attach_mmc(host, ocr)) mmc_power_off(host); extend_wakelock = 1; goto out; } mmc_release_host(host); mmc_power_off(host); out: if (extend_wakelock) wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); else wake_unlock(&mmc_delayed_work_wake_lock); if (host->caps & MMC_CAP_NEEDS_POLL) mmc_schedule_delayed_work(&host->detect, HZ); if (host->ops->notify_card_present) { if (host->card) { host->ops->notify_card_present(host, mmc_card_present(host->card)); } else { host->ops->notify_card_present(host, 0); } } if (host->ops->enable_cd_irq) { host->ops->enable_cd_irq(host); } }
/* * Starting point for MMC card init. */ int mmc_attach_mmc(struct mmc_host *host) { int err; u32 ocr; BUG_ON(!host); WARN_ON(!host->claimed); err = mmc_send_op_cond(host, 0, &ocr); if (err) return err; mmc_attach_bus_ops(host); /* * We need to get OCR a different way for SPI. */ if (mmc_host_is_spi(host)) { err = mmc_spi_read_ocr(host, 1, &ocr); if (err) goto err; } /* * Sanity check the voltages that the card claims to * support. */ if (ocr & 0x7F) { printk(KERN_WARNING "%s: card claims to support voltages " "below the defined range. These will be ignored.\n", mmc_hostname(host)); ocr &= ~0x7F; } host->ocr = mmc_select_voltage(host, ocr); /* * Can we support the voltage of the card? */ if (!host->ocr) { err = -EINVAL; goto err; } /* * Detect and init the card. */ err = mmc_init_card(host, host->ocr, NULL); if (err) goto err; mmc_release_host(host); err = mmc_add_card(host->card); mmc_claim_host(host); if (err) goto remove_card; return 0; remove_card: mmc_release_host(host); mmc_remove_card(host->card); mmc_claim_host(host); host->card = NULL; err: mmc_detach_bus(host); printk(KERN_ERR "%s: error %d whilst initialising MMC card\n", mmc_hostname(host), err); return err; }
/* * Starting point for MMC card init. */ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) { int err; int i = 0; BUG_ON(!host); WARN_ON(!host->claimed); mmc_attach_bus_ops(host); /* * We need to get OCR a different way for SPI. */ if (mmc_host_is_spi(host)) { err = mmc_spi_read_ocr(host, 1, &ocr); if (err) goto err; } /* * Sanity check the voltages that the card claims to * support. */ if (ocr & 0x7F) { printk(KERN_WARNING "%s: card claims to support voltages " "below the defined range. These will be ignored.\n", mmc_hostname(host)); ocr &= ~0x7F; } host->ocr = mmc_select_voltage(host, ocr); /* * Can we support the voltage of the card? */ if (!host->ocr) { err = -EINVAL; goto err; } /* * Detect and init the card. */ err = mmc_init_card(host, host->ocr, NULL); if (err) goto err; /* WA : Lock/Unlock CMD in case of 32nm iNAND */ /*check iNAND*/ if (host->card->cid.manfid == 0x45 || host->card->cid.manfid == 0x02) /*check 32nm*/ if (!(host->card->ext_csd.hpi & 0x1)) { printk(KERN_DEBUG "%s: Lock-unlock started, MID=0x%x, HPI=0x%x\n", __func__, host->card->cid.manfid, host->card->ext_csd.hpi); for (i = 0 ; i < 50 ; i++) { if (mmc_send_lock_cmd(host, 1)) { printk(KERN_ERR "%s: eMMC lock CMD is failed.\n", mmc_hostname(host)); goto remove_card; } if (mmc_send_lock_cmd(host, 0)) { printk(KERN_ERR "%s: eMMC unlock CMD is failed.\n", mmc_hostname(host)); goto remove_card; } } printk(KERN_DEBUG "%s:COMPLETED\n",__func__); } mmc_release_host(host); err = mmc_add_card(host->card); if (err) goto remove_card; return 0; remove_card: mmc_remove_card(host->card); host->card = NULL; mmc_claim_host(host); err: mmc_detach_bus(host); mmc_release_host(host); printk(KERN_ERR "%s: error %d whilst initialising MMC card\n", mmc_hostname(host), err); return err; }