ENGR00118900 [Mx35]Unexpected messages when insert/extract cards.

The unexpected messages are printed by the kernel.
The root cause is that the I2C IO func can't be called in the
interrupt context, since the SD/MMC port and CD PIN is logically
walk through the MCU I2C bus.
Solution:Don't call the I2C IO func in the interrupt context in
card detection IRQ handler, move them to work-queue enviroment.

Signed-off-by: Richard Zhu <r65037@freescale.com>
This commit is contained in:
Richard Zhu
2009-12-03 15:25:37 +08:00
committed by Matt Sealey
parent 4d33a6263f
commit b6831dd13b
2 changed files with 31 additions and 24 deletions

View File

@@ -1243,6 +1243,7 @@ static void sdhci_cd_timer(unsigned long data)
struct sdhci_host *host;
host = (struct sdhci_host *)data;
host->flags |= SDHCI_CD_TIMEOUT;
schedule_work(&host->cd_wq);
}
@@ -1415,6 +1416,34 @@ static void esdhc_cd_callback(struct work_struct *work)
unsigned int cd_status = 0;
struct sdhci_host *host = container_of(work, struct sdhci_host, cd_wq);
do {
if (host->detect_irq == 0)
break;
cd_status = host->plat_data->status(host->mmc->parent);
if (cd_status)
set_irq_type(host->detect_irq, IRQF_TRIGGER_FALLING);
else
set_irq_type(host->detect_irq, IRQF_TRIGGER_RISING);
} while (cd_status != host->plat_data->status(host->mmc->parent));
cd_status = host->plat_data->status(host->mmc->parent);
DBG("cd_status=%d %s\n", cd_status, cd_status ? "removed" : "inserted");
/* If there is no card, call the card detection func
* immediately. */
if (!cd_status) {
/* If there is a card in the slot, the timer is start
* to work. Then the card detection would be carried
* after the timer is timeout.
* */
if (host->flags & SDHCI_CD_TIMEOUT)
host->flags &= ~SDHCI_CD_TIMEOUT;
else {
mod_timer(&host->cd_timer, jiffies + HZ / 4);
return;
}
}
cd_status = host->plat_data->status(host->mmc->parent);
if (cd_status)
host->flags &= ~SDHCI_CD_PRESENT;
@@ -1484,32 +1513,9 @@ static void esdhc_cd_callback(struct work_struct *work)
*/
static irqreturn_t sdhci_cd_irq(int irq, void *dev_id)
{
unsigned int cd_status = 0;
struct sdhci_host *host = dev_id;
do {
if (host->detect_irq == 0)
break;
cd_status = host->plat_data->status(host->mmc->parent);
if (cd_status)
set_irq_type(host->detect_irq, IRQF_TRIGGER_FALLING);
else
set_irq_type(host->detect_irq, IRQF_TRIGGER_RISING);
} while (cd_status != host->plat_data->status(host->mmc->parent));
DBG("cd_status=%d %s\n", cd_status, cd_status ? "removed" : "inserted");
cd_status = host->plat_data->status(host->mmc->parent);
if (!cd_status)
/* If there is a card in the slot, the timer is start
* to work. Then the card detection would be carried
* after the timer is timeout.
* */
mod_timer(&host->cd_timer, jiffies + HZ / 2);
else
/* If there is no card, call the card detection func
* immediately. */
schedule_work(&host->cd_wq);
schedule_work(&host->cd_wq);
return IRQ_HANDLED;
}

View File

@@ -220,6 +220,7 @@ struct sdhci_host {
#define SDHCI_USE_EXTERNAL_DMA (1<<2) /* Use the External DMA */
#define SDHCI_CD_PRESENT (1<<8) /* CD present */
#define SDHCI_WP_ENABLED (1<<9) /* Write protect */
#define SDHCI_CD_TIMEOUT (1<<10) /* cd timer is expired */
unsigned int max_clk; /* Max possible freq (MHz) */
unsigned int min_clk; /* Min possible freq (MHz) */