RE: [PATCH 3/3] mmc: omap_hsmmc: enable SDIO card interrupts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> -----Original Message-----
> From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc-
> owner@xxxxxxxxxxxxxxx] On Behalf Of Madhusudhan
> Sent: Friday, February 19, 2010 3:05 PM
> To: 'David Vrabel'; linux-mmc@xxxxxxxxxxxxxxx
> Cc: linux-omap@xxxxxxxxxxxxxxx
> Subject: RE: [PATCH 3/3] mmc: omap_hsmmc: enable SDIO card interrupts
> 
> 
> 
> > -----Original Message-----
> > From: David Vrabel [mailto:david.vrabel@xxxxxxx]
> > Sent: Wednesday, February 10, 2010 5:52 AM
> > To: linux-mmc@xxxxxxxxxxxxxxx
> > Cc: David Vrabel; linux-omap@xxxxxxxxxxxxxxx; madhu.cr@xxxxxx
> > Subject: [PATCH 3/3] mmc: omap_hsmmc: enable SDIO card interrupts
> >
> > Enable the use of SDIO card interrupts.  This requires setting ENAWAKEUP
> > in SYSCONFIG and IWE in HTCL to allow the MMC block to wake-up when in
> > smart-idle mode.
> >
> > FCLK must be enabled while SDIO interrupts are enabled or the MMC block
> > won't wake-up.
> >
> > The writes to STAT and ISE when starting a command are unnecessary and
> > have been removed.
> >
> > Signed-off-by: David Vrabel <david.vrabel@xxxxxxx>
> > ---
> > As noted in the FIXME comment, I think the correct thing to do is to
> > always leave FCLK enabled.  The clock/clockdomain subsystems should be
> > configuring smart-idle mode making explicit calls to disable FCLK
> > unnecessary.  I couldn't follow the clock subsystem to see if it was
> > actually doing this, though.
> 
> I Just noticed that SD cards stopped working on Zoom2 if I apply this
> patch.
> I will come back with details on what's going on in a bit unless someone
> else beats me on that.
> 

A little bit of rearranging the David's changes to the irq handler gets the
MMC/SD cards to work fine again. Changes are shown in the attached patch for
now and it should not hurt the CIRQ handling as well. 

Regards,
Madhu

> Regards,
> Madhu
> 
> 
> > ---
> >  drivers/mmc/host/omap_hsmmc.c |   94 ++++++++++++++++++++++++++++------
> --
> > -----
> >  1 files changed, 65 insertions(+), 29 deletions(-)
> >
> > diff --git a/drivers/mmc/host/omap_hsmmc.c
> b/drivers/mmc/host/omap_hsmmc.c
> > index e6d8cb3..ad0f867 100644
> > --- a/drivers/mmc/host/omap_hsmmc.c
> > +++ b/drivers/mmc/host/omap_hsmmc.c
> > @@ -64,6 +64,7 @@
> >  #define SDVS_MASK		0x00000E00
> >  #define SDVSCLR			0xFFFFF1FF
> >  #define SDVSDET			0x00000400
> > +#define ENAWAKEUP		(1 << 2)
> >  #define AUTOIDLE		0x1
> >  #define SDBP			(1 << 8)
> >  #define DTO			0xe
> > @@ -74,9 +75,11 @@
> >  #define CLKD_SHIFT		6
> >  #define DTO_MASK		0x000F0000
> >  #define DTO_SHIFT		16
> > +#define CIRQ_ENABLE		(1 << 8)
> >  #define INT_EN_MASK		0x307F0033
> >  #define BWR_ENABLE		(1 << 4)
> >  #define BRR_ENABLE		(1 << 5)
> > +#define CTPL			(1 << 11)
> >  #define INIT_STREAM		(1 << 1)
> >  #define DP_SELECT		(1 << 21)
> >  #define DDIR			(1 << 4)
> > @@ -84,10 +87,12 @@
> >  #define MSBS			(1 << 5)
> >  #define BCE			(1 << 1)
> >  #define FOUR_BIT		(1 << 1)
> > +#define IWE			(1 << 24)
> >  #define DW8			(1 << 5)
> >  #define CC			0x1
> >  #define TC			0x02
> >  #define OD			0x1
> > +#define CIRQ			(1 << 8)
> >  #define ERR			(1 << 15)
> >  #define CMD_TIMEOUT		(1 << 16)
> >  #define DATA_TIMEOUT		(1 << 20)
> > @@ -228,7 +233,7 @@ static int omap_hsmmc_context_restore(struct
> > omap_hsmmc_host *host)
> >  		;
> >
> >  	OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
> > -			OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
> > +			OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE |
> > ENAWAKEUP);
> >
> >  	if (host->id == OMAP_MMC1_DEVID) {
> >  		if (host->power_mode != MMC_POWER_OFF &&
> > @@ -243,7 +248,7 @@ static int omap_hsmmc_context_restore(struct
> > omap_hsmmc_host *host)
> >  	}
> >
> >  	OMAP_HSMMC_WRITE(host->base, HCTL,
> > -			OMAP_HSMMC_READ(host->base, HCTL) | hctl);
> > +			OMAP_HSMMC_READ(host->base, HCTL) | hctl | IWE);
> >
> >  	OMAP_HSMMC_WRITE(host->base, CAPA,
> >  			OMAP_HSMMC_READ(host->base, CAPA) | capa);
> > @@ -257,7 +262,7 @@ static int omap_hsmmc_context_restore(struct
> > omap_hsmmc_host *host)
> >  		;
> >
> >  	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
> > -	OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
> > +	OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK | CIRQ);
> >  	OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
> >
> >  	/* Do not initialize card-specific things if the power is off */
> > @@ -426,12 +431,6 @@ omap_hsmmc_start_command(struct omap_hsmmc_host
> > *host, struct mmc_command *cmd,
> >  		mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
> >  	host->cmd = cmd;
> >
> > -	/*
> > -	 * Clear status bits and enable interrupts
> > -	 */
> > -	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
> > -	OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
> > -
> >  	if (host->use_dma)
> >  		OMAP_HSMMC_WRITE(host->base, IE,
> >  				 INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE));
> > @@ -638,18 +637,21 @@ static irqreturn_t omap_hsmmc_irq(int irq, void
> > *dev_id)
> >  {
> >  	struct omap_hsmmc_host *host = dev_id;
> >  	struct mmc_data *data;
> > -	int end_cmd = 0, end_trans = 0, status;
> > +	u32 status;
> > +	int end_cmd = 0, end_trans = 0;
> > +	bool card_irq = false;
> >
> >  	spin_lock(&host->irq_lock);
> >
> > -	if (host->mrq == NULL) {
> > -		OMAP_HSMMC_WRITE(host->base, STAT,
> > -			OMAP_HSMMC_READ(host->base, STAT));
> > -		/* Flush posted write */
> > -		OMAP_HSMMC_READ(host->base, STAT);
> > -		spin_unlock(&host->irq_lock);
> > -		return IRQ_HANDLED;
> > -	}
> > +	status = OMAP_HSMMC_READ(host->base, STAT);
> > +	OMAP_HSMMC_WRITE(host->base, STAT, status);
> > +	OMAP_HSMMC_READ(host->base, STAT); /* Flush posted write. */
> > +
> > +	if (status & CIRQ)
> > +		card_irq = true;
> > +
> > +	if (host->mrq == NULL)
> > +		goto out;
> >
> >  	data = host->data;
> >  	status = OMAP_HSMMC_READ(host->base, STAT);
> > @@ -704,17 +706,16 @@ static irqreturn_t omap_hsmmc_irq(int irq, void
> > *dev_id)
> >  		}
> >  	}
> >
> > -	OMAP_HSMMC_WRITE(host->base, STAT, status);
> > -	/* Flush posted write */
> > -	OMAP_HSMMC_READ(host->base, STAT);
> > -
> >  	if (end_cmd || ((status & CC) && host->cmd))
> >  		omap_hsmmc_cmd_done(host, host->cmd);
> >  	if ((end_trans || (status & TC)) && host->mrq)
> >  		omap_hsmmc_xfer_done(host, data);
> > -
> > +out:
> >  	spin_unlock(&host->irq_lock);
> >
> > +	if (card_irq)
> > +		mmc_signal_sdio_irq(host->mmc);
> > +
> >  	return IRQ_HANDLED;
> >  }
> >
> > @@ -1248,6 +1249,41 @@ static int omap_hsmmc_get_ro(struct mmc_host
> *mmc)
> >  	return mmc_slot(host).get_ro(host->dev, 0);
> >  }
> >
> > +static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int
> enable)
> > +{
> > +	struct omap_hsmmc_host *host = mmc_priv(mmc);
> > +	u32 ie, con;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&host->irq_lock, flags);
> > +
> > +	/*
> > +	 * When interrupts are enabled, CTPL must be set to enable
> > +	 * DAT1 input buffer (or the card interrupt is always
> > +	 * asserted) and FCLK must be enabled else wakeup does not
> > +	 * work.
> > +	 *
> > +	 * FIXME: the power save code probably shouldn't be playing
> > +	 * with FCLK and allow the clock subsystem to put it into
> > +	 * smart-idle mode instead.
> > +	 */
> > +	con = OMAP_HSMMC_READ(host->base, CON);
> > +	ie = OMAP_HSMMC_READ(host->base, IE);
> > +	if (enable) {
> > +		clk_enable(host->fclk);
> > +		ie |= CIRQ_ENABLE;
> > +		con |= CTPL;
> > +	} else {
> > +		clk_disable(host->fclk);
> > +		ie &= ~CIRQ_ENABLE;
> > +		con &= ~CTPL;
> > +	}
> > +	OMAP_HSMMC_WRITE(host->base, CON, con);
> > +	OMAP_HSMMC_WRITE(host->base, IE, ie);
> > +
> > +	spin_unlock_irqrestore(&host->irq_lock, flags);
> > +}
> > +
> >  static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
> >  {
> >  	u32 hctl, capa, value;
> > @@ -1262,14 +1298,14 @@ static void omap_hsmmc_conf_bus_power(struct
> > omap_hsmmc_host *host)
> >  	}
> >
> >  	value = OMAP_HSMMC_READ(host->base, HCTL) & ~SDVS_MASK;
> > -	OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl);
> > +	OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl | IWE);
> >
> >  	value = OMAP_HSMMC_READ(host->base, CAPA);
> >  	OMAP_HSMMC_WRITE(host->base, CAPA, value | capa);
> >
> >  	/* Set the controller to AUTO IDLE mode */
> >  	value = OMAP_HSMMC_READ(host->base, SYSCONFIG);
> > -	OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE);
> > +	OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE |
> > ENAWAKEUP);
> >
> >  	/* Set SD bus power bit */
> >  	set_sd_bus_power(host);
> > @@ -1516,7 +1552,7 @@ static const struct mmc_host_ops omap_hsmmc_ops =
> {
> >  	.set_ios = omap_hsmmc_set_ios,
> >  	.get_cd = omap_hsmmc_get_cd,
> >  	.get_ro = omap_hsmmc_get_ro,
> > -	/* NYET -- enable_sdio_irq */
> > +	.enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
> >  };
> >
> >  static const struct mmc_host_ops omap_hsmmc_ps_ops = {
> > @@ -1526,7 +1562,7 @@ static const struct mmc_host_ops omap_hsmmc_ps_ops
> =
> > {
> >  	.set_ios = omap_hsmmc_set_ios,
> >  	.get_cd = omap_hsmmc_get_cd,
> >  	.get_ro = omap_hsmmc_get_ro,
> > -	/* NYET -- enable_sdio_irq */
> > +	.enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
> >  };
> >
> >  #ifdef CONFIG_DEBUG_FS
> > @@ -1731,7 +1767,7 @@ static int __init omap_hsmmc_probe(struct
> > platform_device *pdev)
> >  	mmc->max_seg_size = mmc->max_req_size;
> >
> >  	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
> > -		     MMC_CAP_WAIT_WHILE_BUSY;
> > +		     MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_SDIO_IRQ;
> >
> >  	if (mmc_slot(host).wires >= 8)
> >  		mmc->caps |= MMC_CAP_8_BIT_DATA;
> > @@ -1802,7 +1838,7 @@ static int __init omap_hsmmc_probe(struct
> > platform_device *pdev)
> >  		}
> >  	}
> >
> > -	OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
> > +	OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK | CIRQ);
> >  	OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
> >
> >  	mmc_host_lazy_disable(host->mmc);
> > --
> > 1.6.3.3
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Attachment: 0001-OMAP-Hsmmc-Get-the-SD-cards-to-work-again.patch
Description: Binary data


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux