From: Christer Weinigel <christer@weinigel.se>
To: ben-linux@fluff.org
Cc: linux-kernel@vger.kernel.org, christer@weinigel.se
Subject: [patch 3/3] s3cmci - add SDIO interrupt support
Date: Mon, 08 Sep 2008 14:48:51 +0200 [thread overview]
Message-ID: <20080908124910.107466441@zoo.weinigel.se> (raw)
In-Reply-To: <20080908124848.541807034@zoo.weinigel.se>
[-- Attachment #1: s3c_mci-sdio-irq.patch --]
[-- Type: text/plain, Size: 5611 bytes --]
This adds support for the SDIO irq to the s3cmci driver.
The driver calls to enable_irq and disable_irq are not matched
properly when doing SDIO, so I've worked around this by counting the
number of enables and disables. This is not the proper way to do it,
but makes things work for me the moment on a Samsung S3C24A0
processor. There are supposed to be issues with spurious interrupts
on some S3C processors, so this needs more investigation and testing,
but I thought this patch may be useful anyway.
Signed-off-by: Christer Weinigel <christer@weinigel.se>
Index: linux-2.6.26.2/drivers/mmc/host/s3cmci.c
===================================================================
--- linux-2.6.26.2.orig/drivers/mmc/host/s3cmci.c
+++ linux-2.6.26.2/drivers/mmc/host/s3cmci.c
@@ -187,7 +187,11 @@ static inline u32 disable_imask(struct s
static inline void clear_imask(struct s3cmci_host *host)
{
- writel(0, host->base + host->sdiimsk);
+ u32 newmask;
+
+ newmask = readl(host->base + host->sdiimsk);
+ newmask &= S3C2410_SDIIMSK_SDIOIRQ;
+ writel(newmask, host->base + host->sdiimsk);
}
static inline int get_data_buffer(struct s3cmci_host *host,
@@ -364,6 +368,7 @@ static void do_pio_write(struct s3cmci_h
static void pio_tasklet(struct s3cmci_host *host)
{
disable_irq(host->irq);
+ host->irq_disabled++;
if (host->pio_active == XFER_WRITE)
do_pio_write(host);
@@ -384,8 +389,12 @@ static void pio_tasklet(struct s3cmci_ho
}
finalize_request(host);
- } else
+ }
+
+ if (host->irq_disabled) {
enable_irq(host->irq);
+ host->irq_disabled--;
+ }
}
/*
@@ -422,6 +431,7 @@ static irqreturn_t s3cmci_irq(int irq, v
u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
u32 mci_cclear, mci_dclear;
unsigned long iflags;
+ int cardint = 0;
spin_lock_irqsave(&host->complete_lock, iflags);
@@ -433,6 +443,13 @@ static irqreturn_t s3cmci_irq(int irq, v
mci_cclear = 0;
mci_dclear = 0;
+ if (mci_dsta & S3C2410_SDIDSTA_SDIOIRQDETECT &&
+ mci_imsk & S3C2410_SDIIMSK_SDIOIRQ) {
+ cardint = 1;
+ mci_dclear = S3C2410_SDIDSTA_SDIOIRQDETECT;
+ goto clear_status_bits;
+ }
+
if ((host->complete_what == COMPLETION_NONE) ||
(host->complete_what == COMPLETION_FINALIZE)) {
host->status = "nothing to complete";
@@ -603,8 +620,12 @@ irq_out:
mci_csta, mci_dsta, mci_fsta, mci_dcnt, host->status);
spin_unlock_irqrestore(&host->complete_lock, iflags);
- return IRQ_HANDLED;
+ /* We have to delay this as it calls back into the driver. */
+ if (cardint)
+ mmc_signal_sdio_irq(host->mmc);
+
+ return IRQ_HANDLED;
}
/*
@@ -671,7 +692,7 @@ out:
fail_request:
host->mrq->data->error = -EINVAL;
host->complete_what = COMPLETION_FINALIZE;
- writel(0, host->base + host->sdiimsk);
+ clear_imask(host);
goto out;
}
@@ -716,7 +737,7 @@ static void finalize_request(struct s3cm
writel(0, host->base + S3C2410_SDICMDARG);
writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
writel(0, host->base + S3C2410_SDICMDCON);
- writel(0, host->base + host->sdiimsk);
+ clear_imask(host);
if (cmd->data && cmd->error)
cmd->data->error = cmd->error;
@@ -1026,7 +1047,10 @@ static void s3cmci_send_request(struct m
s3cmci_send_command(host, cmd);
/* Enable Interrupt */
- enable_irq(host->irq);
+ if (host->irq_disabled) {
+ enable_irq(host->irq);
+ host->irq_disabled--;
+ }
}
static int s3cmci_card_present(struct s3cmci_host *host)
@@ -1119,9 +1143,9 @@ static void s3cmci_set_ios(struct mmc_ho
/* Set CLOCK_ENABLE */
if (ios->clock)
- mci_con |= S3C2410_SDICON_CLOCKTYPE;
+ mci_con |= S3C2410_SDICON_CLOCKTYPE | S3C2410_SDICON_SDIOIRQ;
else
- mci_con &= ~S3C2410_SDICON_CLOCKTYPE;
+ mci_con &= ~(S3C2410_SDICON_CLOCKTYPE | S3C2410_SDICON_SDIOIRQ);
writel(mci_con, host->base + S3C2410_SDICON);
@@ -1161,10 +1185,26 @@ static int s3cmci_get_ro(struct mmc_host
return ret;
}
+static void s3cmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+ struct s3cmci_host *host = mmc_priv(mmc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->complete_lock, flags);
+
+ if (enable)
+ enable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
+ else
+ disable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
+
+ spin_unlock_irqrestore(&host->complete_lock, flags);
+}
+
static struct mmc_host_ops s3cmci_ops = {
.request = s3cmci_request,
.set_ios = s3cmci_set_ios,
.get_ro = s3cmci_get_ro,
+ .enable_sdio_irq = s3cmci_enable_sdio_irq,
};
static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
@@ -1256,6 +1296,7 @@ static int __devinit s3cmci_probe(struct
* ensure we don't lock the system with un-serviceable requests. */
disable_irq(host->irq);
+ host->irq_disabled++;
host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
@@ -1301,7 +1342,7 @@ static int __devinit s3cmci_probe(struct
mmc->ops = &s3cmci_ops;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- mmc->caps = MMC_CAP_4_BIT_DATA;
+ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
mmc->f_min = host->clk_rate / (host->clk_div * 256);
mmc->f_max = host->clk_rate / host->clk_div;
Index: linux-2.6.26.2/drivers/mmc/host/s3cmci.h
===================================================================
--- linux-2.6.26.2.orig/drivers/mmc/host/s3cmci.h
+++ linux-2.6.26.2/drivers/mmc/host/s3cmci.h
@@ -41,6 +41,7 @@ struct s3cmci_host {
unsigned sdidata;
int dodma;
int dmatogo;
+ int irq_disabled;
struct mmc_request *mrq;
int cmd_is_stop;
--
"Just how much can I get away with and still go to heaven?"
Christer Weinigel <christer@weinigel.se> http://www.weinigel.se
prev parent reply other threads:[~2008-09-08 12:59 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-08 12:48 [patch 0/3] s3cmci SDIO patches Christer Weinigel
2008-09-08 12:48 ` [patch 1/3] s3cmci -- support odd block transfers Christer Weinigel
2008-09-08 12:48 ` [patch 2/3] s3cmci - call pio_tasklet from IRQ Christer Weinigel
2008-09-08 13:46 ` Ben Dooks
2008-09-08 14:04 ` Christer Weinigel
2008-09-08 15:12 ` Christer Weinigel
2008-09-08 12:48 ` Christer Weinigel [this message]
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=20080908124910.107466441@zoo.weinigel.se \
--to=christer@weinigel.se \
--cc=ben-linux@fluff.org \
--cc=linux-kernel@vger.kernel.org \
/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
all inboxes | Powered by JetHome®