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; unsigned long duration =0; /* * 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; }
/** * mmc_gpio_request_cd - request a gpio for card-detection * @host: mmc host * @gpio: gpio number requested * * As devm_* managed functions are used in mmc_gpio_request_cd(), client * drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up, * if the requesting and freeing are only needed at probing and unbinding time * for once. However, if client drivers do something special like runtime * switching for card-detection, they are responsible for calling * mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own. * * Returns zero on success, else an error. */ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) { struct mmc_gpio *ctx; int irq = gpio_to_irq(gpio); int ret; ret = mmc_gpio_alloc(host); if (ret < 0) return ret; ctx = host->slot.handler_priv; ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN, ctx->cd_label); if (ret < 0) /* * don't bother freeing memory. It might still get used by other * slot functions, in any case it will be freed, when the device * is destroyed. */ return ret; /* * Even if gpio_to_irq() returns a valid IRQ number, the platform might * still prefer to poll, e.g., because that IRQ number is already used * by another unit and cannot be shared. */ if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) irq = -EINVAL; ctx->cd_gpio = gpio; host->slot.cd_irq = irq; ret = mmc_gpio_get_status(host); if (ret < 0) return ret; ctx->status = ret; if (irq >= 0) { ret = devm_request_threaded_irq(&host->class_dev, irq, NULL, mmc_gpio_cd_irqt, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ctx->cd_label, host); if (ret < 0) irq = ret; #ifndef VENDOR_EDIT //[email protected], 2014-07-10 Add for retry 5 times when new sdcard init error enable_irq_wake(irq); #endif /* VENDOR_EDIT */ } if (irq < 0) host->caps |= MMC_CAP_NEEDS_POLL; return 0; }
static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) { struct mmc_host *host = dev_id; struct mmc_gpio *ctx = host->slot.handler_priv; int status; spin_lock(&host->lock_cd_pin); if (host->cd_pin_depth == 0) { if (enable_detection_workqueue) { disable_irq_nosync(host->slot.cd_irq); queue_delayed_work(enable_detection_workqueue, &host->enable_detect, msecs_to_jiffies(50)); host->cd_pin_depth++; } else pr_err("%s detection workqueue is null\n", mmc_hostname(host)); } spin_unlock(&host->lock_cd_pin); 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"); irq_set_irq_type(irq, (status == 0 ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING)); ctx->status = status; host->caps |= host->caps_uhs; host->removed_cnt = 0; host->crc_count = 0; if (disable_auto_sd) goto out; mmc_detect_change(host, msecs_to_jiffies(host->extended_debounce + 200)); mmc_gpio_send_uevent(host); } out: return IRQ_HANDLED; }
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) { struct mmc_gpio *ctx; int irq = gpio_to_irq(gpio); int ret; int irq_trigger_type; ret = mmc_gpio_alloc(host); if (ret < 0) return ret; host->cd_pin_depth = 0; spin_lock_init(&host->lock_cd_pin); ctx = host->slot.handler_priv; ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN, ctx->cd_label); if (ret < 0) { return ret; } if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) irq = -EINVAL; ctx->cd_gpio = gpio; host->slot.cd_irq = irq; ret = mmc_gpio_get_status(host); if (ret < 0) return ret; irq_trigger_type = (ret == 0 ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING); ctx->status = ret; if (irq >= 0) { ret = devm_request_threaded_irq(&host->class_dev, irq, NULL, mmc_gpio_cd_irqt, irq_trigger_type | IRQF_ONESHOT, ctx->cd_label, host); if (ret < 0) irq = ret; } if (irq < 0) host->caps |= MMC_CAP_NEEDS_POLL; return 0; }
int mmc_gpio_send_uevent(struct mmc_host *host) { char *envp[2]; char state_string[16]; int status; status = mmc_gpio_get_status(host); if (unlikely(status < 0)) goto out; snprintf(state_string, sizeof(state_string), "SWITCH_STATE=%d", status); envp[0] = state_string; envp[1] = NULL; kobject_uevent_env(&host->class_dev.kobj, KOBJ_ADD, envp); out: return status; }
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; }