From patchwork Tue Jun 16 10:37:19 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vignesh Raghavendra X-Patchwork-Id: 6617271 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7991AC0433 for ; Tue, 16 Jun 2015 10:38:02 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9003B20503 for ; Tue, 16 Jun 2015 10:38:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7ABAA2050B for ; Tue, 16 Jun 2015 10:38:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932468AbbFPKho (ORCPT ); Tue, 16 Jun 2015 06:37:44 -0400 Received: from bear.ext.ti.com ([192.94.94.41]:58570 "EHLO bear.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932404AbbFPKhi (ORCPT ); Tue, 16 Jun 2015 06:37:38 -0400 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id t5GAbW6u012734; Tue, 16 Jun 2015 05:37:32 -0500 Received: from DFLE73.ent.ti.com (dfle73.ent.ti.com [128.247.5.110]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id t5GAbWoB032155; Tue, 16 Jun 2015 05:37:32 -0500 Received: from dlep32.itg.ti.com (157.170.170.100) by DFLE73.ent.ti.com (128.247.5.110) with Microsoft SMTP Server id 14.3.224.2; Tue, 16 Jun 2015 05:37:31 -0500 Received: from uda0132425.apr.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep32.itg.ti.com (8.14.3/8.13.8) with ESMTP id t5GAbJjt017652; Tue, 16 Jun 2015 05:37:29 -0500 From: Vignesh R To: Ulf Hansson CC: Andreas Fenkart , Tony Lindgren , NeilBrown , Vignesh R , , , Subject: [PATCH 3/3] mmc: host: omap_hsmmc: Add custom card detect irq handler Date: Tue, 16 Jun 2015 16:07:19 +0530 Message-ID: <1434451039-18195-4-git-send-email-vigneshr@ti.com> X-Mailer: git-send-email 2.4.1 In-Reply-To: <1434451039-18195-1-git-send-email-vigneshr@ti.com> References: <1434451039-18195-1-git-send-email-vigneshr@ti.com> MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Usually when there is an error in transfer, DTO/CTO or other error interrupts are raised. But if the card is unplugged in the middle of a data transfer, it is observed that, neither completion(success) or timeout(error) interrupts are raised. Hence, the mmc-core is waiting for-ever for the transfer to complete. This results failure to recognise sd card on the next insertion. The only way to solve this is to introduce code to detect this condition and recover on card insertion (in hsmmc specific cd_irq). Hence, introduce cd_irq and add code to clear mmc_request that is pending from the failed transaction. Signed-off-by: Vignesh R --- drivers/mmc/host/omap_hsmmc.c | 73 ++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index fb4bfefd9250..ec1fff3c0c9c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -221,6 +221,12 @@ struct omap_hsmmc_host { #define HSMMC_WAKE_IRQ_ENABLED (1 << 2) struct omap_hsmmc_next next_data; struct omap_hsmmc_platform_data *pdata; + /* + * flag to determine whether card was removed during data + * transfer + */ + bool transfer_incomplete; + /* return MMC cover switch state, can be NULL if not supported. * @@ -867,6 +873,26 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req } /* + * Cleanup incomplete card removal sequence. This will make sure the + * next card enumeration is clean. + */ +static void omap_hsmmc_request_clear(struct omap_hsmmc_host *host, + struct mmc_request *mrq) +{ + unsigned long flags; + + spin_lock_irqsave(&host->irq_lock, flags); + host->req_in_progress = 0; + host->dma_ch = -1; + spin_unlock_irqrestore(&host->irq_lock, flags); + + mmc_request_done(host->mmc, mrq); + if (host->mmc->card) + mmc_card_set_removed(host->mmc->card); + host->mrq = NULL; +} + +/* * Notify the transfer complete to MMC core */ static void @@ -1248,6 +1274,47 @@ static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id) return IRQ_HANDLED; } +/* + * irq handler to notify the core about card insertion/removal + */ +static irqreturn_t omap_hsmmc_cd_irq(int irq, void *dev_id) +{ + struct omap_hsmmc_host *host = mmc_priv(dev_id); + int carddetect = mmc_gpio_get_cd(host->mmc); + struct mmc_request *mrq = host->mrq; + + /* + * If the card was removed in the middle of data transfer last + * time, the TC/CC/timeout interrupt is not raised due to which + * mmc_request is not cleared. Hence, this card insertion will + * still see pending mmc_request. Clear the request to make sure + * that this card enumeration is successful. + */ + if (!carddetect && mrq && host->transfer_incomplete) { + omap_hsmmc_disable_irq(host); + dev_info(host->dev, + "card removed during transfer last time\n"); + hsmmc_command_incomplete(host, -ENOMEDIUM, 1); + omap_hsmmc_request_clear(host, host->mrq); + dev_info(host->dev, "recovery done\n"); + } + host->transfer_incomplete = false; + + mmc_detect_change(host->mmc, (HZ * 200) / 1000); + + /* + * The current mmc_request is usually null before card removal + * sequence is complete. It may not be null if TC/CC interrupt + * never happens due to removal of card during a data + * transfer. Set a flag to indicate mmc_request was not null + * in order to do cleanup on next card insertion. + */ + if (carddetect && mrq) + host->transfer_incomplete = true; + + return IRQ_HANDLED; +} + static void omap_hsmmc_dma_callback(void *param) { struct omap_hsmmc_host *host = param; @@ -1918,7 +1985,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) struct mmc_host *mmc; struct omap_hsmmc_host *host = NULL; struct resource *res; - int ret, irq; + int ret, irq, len; const struct of_device_id *match; dma_cap_mask_t mask; unsigned tx_req, rx_req; @@ -1980,6 +2047,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (ret) goto err_gpio; + /* register cd_irq, if cd-gpios property is specified in dt */ + if (of_find_property(host->dev->of_node, "cd-gpios", &len)) + mmc_gpio_set_cd_isr(mmc, omap_hsmmc_cd_irq); + platform_set_drvdata(pdev, host); if (pdev->dev.of_node)