linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Balaji T K <balajitk@ti.com>
To: Andreas Fenkart <afenkart@gmail.com>
Cc: Tony Lindgren <tony@atomide.com>, Chris Ball <chris@printf.net>,
	Grant Likely <grant.likely@secretlab.ca>,
	Felipe Balbi <balbi@ti.com>,
	zonque@gmail.com, galak@codeaurora.org,
	linux-doc@vger.kernel.org, linux-mmc@vger.kernel.org,
	linux-omap@vger.kernel.org
Subject: Re: [PATCH v9 resend 1/3] mmc: omap_hsmmc: Enable SDIO interrupt
Date: Fri, 21 Mar 2014 21:40:49 +0530	[thread overview]
Message-ID: <532C6489.4050307@ti.com> (raw)
In-Reply-To: <1395404448-30030-2-git-send-email-afenkart@gmail.com>

On Friday 21 March 2014 05:50 PM, Andreas Fenkart wrote:

Thanks Andreas for the patch series

I rebased against latest mmc-next, made few changes to your patch.
I have hosted your series along with devm cleanups on a branch[1] for testing
[1]
git://git.ti.com/~balajitk/ti-linux-kernel/omap-hsmmc.git omap_hsmmc_sdio_irq_devm_cleanup

Can you please test on your platform and provide feedback.

Details about the changes below.

> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> @@ -1088,6 +1113,45 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
>   	return IRQ_HANDLED;
>   }
>
> +static inline void hsmmc_enable_wake_irq(struct omap_hsmmc_host *host)
> +{
> +	unsigned long flags;
> +
> +	if (!host->wake_irq)
> +		return;
> +
> +	spin_lock_irqsave(&host->irq_lock, flags);
> +	enable_irq(host->wake_irq);
> +	host->wake_irq_en = true;

Using wake_irq_en flag leads to wake_irq enabled always after
suspend/resume due to unbalanced disable/enable_irq
so adding back HSMMC_WAKE_IRQ_ENABLED to host->flags

> +	spin_unlock_irqrestore(&host->irq_lock, flags);
> +}
> +
> +static inline void hsmmc_disable_wake_irq(struct omap_hsmmc_host *host)
> +{
> +	unsigned long flags;
> +
> +	if (!host->wake_irq)
> +		return;
> +
> +	spin_lock_irqsave(&host->irq_lock, flags);
> +	if (host->wake_irq_en)
> +		disable_irq_nosync(host->wake_irq);
> +	host->wake_irq_en = false;
> +	spin_unlock_irqrestore(&host->irq_lock, flags);
> +}
> +
> +static irqreturn_t omap_hsmmc_wake_irq(int irq, void *dev_id)
> +{
> +	struct omap_hsmmc_host *host = dev_id;
> +
> +	/* cirq is level triggered, disable to avoid infinite loop */
> +	hsmmc_disable_wake_irq(host);
> +
> +	pm_request_resume(host->dev); /* no use counter */
> +
> +	return IRQ_HANDLED;
> +}
> +
>   static void set_sd_bus_power(struct omap_hsmmc_host *host)
>   {
>   	unsigned long i;
> @@ -1591,6 +1655,72 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
>   		mmc_slot(host).init_card(card);
>   }
>
> +static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
> +{
> +	struct omap_hsmmc_host *host = mmc_priv(mmc);
> +	u32 irq_mask;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&host->irq_lock, flags);
> +

Introduced check for runtime suspend to be sure and explicitly
enable clocks using runtime_get_sync for enable sdio irq path.

> +	irq_mask = OMAP_HSMMC_READ(host->base, ISE);
> +	if (enable) {
> +		host->flags |= HSMMC_SDIO_IRQ_ENABLED;
> +		irq_mask |= CIRQ_EN;
> +	} else {
> +		host->flags &= ~HSMMC_SDIO_IRQ_ENABLED;
> +		irq_mask &= ~CIRQ_EN;
> +	}
> +	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
> +
> +	/*
> +	 * if enable, piggy back detection on current request
> +	 * but always disable immediately
> +	 */
> +	if (!host->req_in_progress || !enable)
> +		OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
> +
> +	/* flush posted write */
> +	OMAP_HSMMC_READ(host->base, IE);
> +
> +	spin_unlock_irqrestore(&host->irq_lock, flags);
> +}
> +
> +static int omap_hscmm_configure_wake_irq(struct omap_hsmmc_host *host)
> +{
> +	struct mmc_host *mmc = host->mmc;
> +	int ret;
> +
> +	/*
> +	 * The wake-irq is needed for omaps with wake-up path and also
> +	 * when doing GPIO remuxing, because omap_hsmmc is doing runtime PM.
> +	 * So there's nothing stopping from shutting it down. And there's
> +	 * really no need to block runtime PM for it as it's working.
> +	 */
> +	if (!host->dev->of_node || !host->wake_irq)
> +		return -ENODEV;
> +
> +	/* Prevent auto-enabling of IRQ */
> +	irq_set_status_flags(host->wake_irq, IRQ_NOAUTOEN);
> +	ret = request_irq(host->wake_irq, omap_hsmmc_wake_irq,
> +			  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> +			  mmc_hostname(mmc), host);

Replaced request_irq with devm_request_irq

> +	if (ret) {
> +		dev_err(mmc_dev(host->mmc),
> +			"Unable to request wake IRQ\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * Some omaps don't have wake-up path from deeper idle states
> +	 * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
> +	 */
> +	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING)
> +		host->flags |= HSMMC_SWAKEUP_QUIRK;
> +
> +	return 0;
> +}
> +
>   static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
>   {
>   	u32 hctl, capa, value;
> @@ -1643,7 +1773,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = {
>   	.get_cd = omap_hsmmc_get_cd,
>   	.get_ro = omap_hsmmc_get_ro,
>   	.init_card = omap_hsmmc_init_card,
> -	/* NYET -- enable_sdio_irq */
> +	.enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
>   };
>
>   #ifdef CONFIG_DEBUG_FS
> @@ -1704,8 +1834,19 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc)
>
>   #endif
>
> +struct of_data {
> +	u16 offset;
> +	int flags;
> +};
> +
>   #ifdef CONFIG_OF
> -static u16 omap4_reg_offset = 0x100;
> +static struct of_data omap4_data = {
> +	.offset	= 0x100,
> +};
> +static struct of_data am33xx_data = {
> +	.offset	= 0x100,
> +	.flags	= OMAP_HSMMC_SWAKEUP_MISSING,
> +};
>
>   static const struct of_device_id omap_mmc_of_match[] = {
>   	{
> @@ -1716,7 +1857,11 @@ static const struct of_device_id omap_mmc_of_match[] = {
>   	},
>   	{
>   		.compatible = "ti,omap4-hsmmc",
> -		.data = &omap4_reg_offset,
> +		.data = &omap4_data,
> +	},
> +	{
> +		.compatible = "ti,am33xx-hsmmc",
> +		.data = &am33xx_data,
>   	},
>   	{},
>   };
> @@ -1779,6 +1924,7 @@ static inline struct omap_mmc_platform_data
>   {
>   	return NULL;
>   }
> +#define omap_mmc_of_match	NULL
>   #endif
>
>   static int omap_hsmmc_probe(struct platform_device *pdev)
> @@ -1787,7 +1933,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, _wake_irq = 0;
>   	const struct of_device_id *match;
>   	dma_cap_mask_t mask;
>   	unsigned tx_req, rx_req;
> @@ -1801,8 +1947,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>   			return PTR_ERR(pdata);
>
>   		if (match->data) {
> -			const u16 *offsetp = match->data;
> -			pdata->reg_offset = *offsetp;
> +			const struct of_data *d = match->data;
> +			pdata->reg_offset = d->offset;
> +			pdata->controller_flags |= d->flags;
>   		}
>   	}
>
> @@ -1821,6 +1968,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>   	if (res == NULL || irq < 0)
>   		return -ENXIO;
>
> +	if (pdev->dev.of_node)
> +		_wake_irq = irq_of_parse_and_map(pdev->dev.of_node, 1);
> +

Moved this code further down to remove _wake_irq

>   	res = request_mem_region(res->start, resource_size(res), pdev->name);
>   	if (res == NULL)
>   		return -EBUSY;
> @@ -1842,6 +1992,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>   	host->use_dma	= 1;
>   	host->dma_ch	= -1;
>   	host->irq	= irq;
> +	host->wake_irq = _wake_irq;
>   	host->slot_id	= 0;
>   	host->mapbase	= res->start + pdata->reg_offset;
>   	host->base	= ioremap(host->mapbase, SZ_4K);
> @@ -2018,6 +2169,18 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>   		dev_warn(&pdev->dev,
>   			"pins are not configured from the driver\n");
>
> +	/*
> +	 * For now, only support SDIO interrupt if we have a separate
> +	 * wake-up interrupt configured from device tree. This is because
> +	 * the wake-up interrupt is needed for idle state and some
> +	 * platforms need special quirks. And we don't want to add new
> +	 * legacy mux platform init code callbacks any longer as we
> +	 * are moving to DT based booting anyways.
> +	 */
> +	ret = omap_hscmm_configure_wake_irq(host);

fixed the typo in hsmmc :-)

> +	if (!ret)
> +		mmc->caps |= MMC_CAP_SDIO_IRQ;
> +
>   	omap_hsmmc_protect_card(host);
>
>   	mmc_add_host(mmc);
> @@ -2042,7 +2205,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>
>   err_slot_name:
>   	mmc_remove_host(mmc);
> -	free_irq(mmc_slot(host).card_detect_irq, host);
> +	if (host->wake_irq)
> +		free_irq(host->wake_irq, host);
> +	if (mmc_slot(host).card_detect_irq)
> +		free_irq(mmc_slot(host).card_detect_irq, host);
>   err_irq_cd:
>   	if (host->use_reg)
>   		omap_hsmmc_reg_put(host);
> @@ -2087,6 +2253,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
>   	if (host->pdata->cleanup)
>   		host->pdata->cleanup(&pdev->dev);
>   	free_irq(host->irq, host);
> +	if (host->wake_irq)
> +		free_irq(host->wake_irq, host);
>   	if (mmc_slot(host).card_detect_irq)
>   		free_irq(mmc_slot(host).card_detect_irq, host);
>
> @@ -2149,6 +2317,8 @@ static int omap_hsmmc_suspend(struct device *dev)
>   				OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
>   	}
>
> +	hsmmc_disable_wake_irq(host);
> +

Made disable/enable_wake_irq conditional on MMC_PM_WAKE_SDIO_IRQ cap

>   	if (host->dbclk)
>   		clk_disable_unprepare(host->dbclk);
>
> @@ -2176,6 +2346,8 @@ static int omap_hsmmc_resume(struct device *dev)
>
>   	omap_hsmmc_protect_card(host);
>
> +	hsmmc_enable_wake_irq(host);
> +
>   	pm_runtime_mark_last_busy(host->dev);
>   	pm_runtime_put_autosuspend(host->dev);
>   	return 0;
> @@ -2191,23 +2363,38 @@ static int omap_hsmmc_resume(struct device *dev)
>   static int omap_hsmmc_runtime_suspend(struct device *dev)
>   {
>   	struct omap_hsmmc_host *host;
> +	int ret = 0;
>
>   	host = platform_get_drvdata(to_platform_device(dev));
>   	omap_hsmmc_context_save(host);
>   	dev_dbg(dev, "disabled\n");
>
> -	return 0;
> +	if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {
> +		OMAP_HSMMC_WRITE(host->base, ISE, 0);
> +		OMAP_HSMMC_WRITE(host->base, IE, 0);
> +		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
> +		hsmmc_enable_wake_irq(host);

here too.

> +	}
> +
> +	return ret;
>   }
>
>   static int omap_hsmmc_runtime_resume(struct device *dev)
>   {
>   	struct omap_hsmmc_host *host;
> +	int ret = 0;
>
>   	host = platform_get_drvdata(to_platform_device(dev));
>   	omap_hsmmc_context_restore(host);
>   	dev_dbg(dev, "enabled\n");
>
> -	return 0;
> +	if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {

This leads to unconditional re-enabling sdio_irq/wake_irq
on next runtime resume, so replaced the check with HSMMC_SDIO_IRQ_ENABLED

> +		hsmmc_disable_wake_irq(host);
> +		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
> +		OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
> +		OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);
> +	}
> +	return ret;
>   }
>
>   static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
> diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h
> index 2bf1b30..51e70cf 100644
> --- a/include/linux/platform_data/mmc-omap.h
> +++ b/include/linux/platform_data/mmc-omap.h
> @@ -28,6 +28,7 @@
>    */
>   #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
>   #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
> +#define OMAP_HSMMC_SWAKEUP_MISSING		BIT(2)
>
>   struct mmc_card;
>
>


  reply	other threads:[~2014-03-21 16:11 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-21 12:20 [PATCH v9 resend 0/3] mmc: omap_hsmmc: Enable SDIO IRQ Andreas Fenkart
2014-03-21 12:20 ` [PATCH v9 resend 1/3] mmc: omap_hsmmc: Enable SDIO interrupt Andreas Fenkart
2014-03-21 16:10   ` Balaji T K [this message]
2014-03-24  9:30     ` Dmitry Lifshitz
2014-04-18 16:46       ` Tony Lindgren
2014-03-21 16:17   ` [PATCH 0/9] mmc: omap_hsmmc: convert to use devm_* and enable sdio irq Balaji T K
2014-03-21 16:17     ` [PATCH 1/9] mmc: omap_hsmmc: use devm_clk_get Balaji T K
2014-03-21 16:17     ` [PATCH 2/9] mmc: omap_hsmmc: use devm_request_irq Balaji T K
2014-03-21 16:17     ` [PATCH 3/9] mmc: omap_hsmmc: use devm_request_threaded_irq Balaji T K
2014-03-21 16:17     ` [PATCH 4/9] mmc: omap_hsmmc: use devm_request_mem_region Balaji T K
2014-03-21 16:18       ` Felipe Balbi
2014-03-21 16:27         ` Balaji T K
2014-03-21 16:30           ` Felipe Balbi
2014-03-21 16:17     ` [PATCH 5/9] mmc: omap_hsmmc: use devm_ioremap Balaji T K
2014-03-21 16:17     ` [PATCH 6/9] mmc: omap_hsmmc: Enable SDIO interrupt Balaji T K
2014-03-24 12:43       ` Ulf Hansson
2014-03-24 14:59         ` Andreas Fenkart
2014-03-24 16:02           ` Ulf Hansson
2014-03-24 16:34             ` Andreas Fenkart
2014-03-25  8:07               ` Ulf Hansson
2014-03-25 15:19                 ` Balaji T K
2014-03-30 22:43                   ` Andreas Fenkart
2014-03-21 16:17     ` [PATCH 7/9] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Balaji T K
2014-03-21 16:17     ` [PATCH 8/9] mmc: omap_hsmmc: Extend debugfs for SDIO IRQ, GPIO and pinmux Balaji T K
2014-03-21 16:17     ` [PATCH 9/9] mmc: omap_hsmmc: enable wakeup event for sdio Balaji T K
2014-05-02 15:33       ` Balaji T K
2014-03-21 12:20 ` [PATCH v9 resend 2/3] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Andreas Fenkart
2014-03-21 12:20 ` [PATCH v9 resend 3/3] mmc: omap_hsmmc: Extend debugfs for SDIO IRQ, GPIO and pinmux Andreas Fenkart

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=532C6489.4050307@ti.com \
    --to=balajitk@ti.com \
    --cc=afenkart@gmail.com \
    --cc=balbi@ti.com \
    --cc=chris@printf.net \
    --cc=galak@codeaurora.org \
    --cc=grant.likely@secretlab.ca \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=tony@atomide.com \
    --cc=zonque@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).