mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-09-21 22:24:11 +00:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) */
|
||||
|
||||
Reference in New Issue
Block a user