提交 2686b4b4 编写于 作者: L Linus Walleij 提交者: Russell King

ARM: 6311/2: mmci: work with only one irq

The DBx500 variants have only one IRQ line hooked up.  Allow these (and
any other implementations which choose to use only one irq) to work by
directing the PIO interrupts also to the first IRQ line.
Signed-off-by: NRabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: NLinus Walleij <linus.walleij@stericsson.com>
Signed-off-by: NRussell King <rmk+kernel@arm.linux.org.uk>
上级 f6614b7b
...@@ -129,10 +129,26 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) ...@@ -129,10 +129,26 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
spin_lock(&host->lock); spin_lock(&host->lock);
} }
static void mmci_set_mask1(struct mmci_host *host, unsigned int mask)
{
void __iomem *base = host->base;
if (host->singleirq) {
unsigned int mask0 = readl(base + MMCIMASK0);
mask0 &= ~MCI_IRQ1MASK;
mask0 |= mask;
writel(mask0, base + MMCIMASK0);
}
writel(mask, base + MMCIMASK1);
}
static void mmci_stop_data(struct mmci_host *host) static void mmci_stop_data(struct mmci_host *host)
{ {
writel(0, host->base + MMCIDATACTRL); writel(0, host->base + MMCIDATACTRL);
writel(0, host->base + MMCIMASK1); mmci_set_mask1(host, 0);
host->data = NULL; host->data = NULL;
} }
...@@ -198,7 +214,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) ...@@ -198,7 +214,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
writel(datactrl, base + MMCIDATACTRL); writel(datactrl, base + MMCIDATACTRL);
writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);
writel(irqmask, base + MMCIMASK1); mmci_set_mask1(host, irqmask);
} }
static void static void
...@@ -437,7 +453,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) ...@@ -437,7 +453,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
* "any data available" mode. * "any data available" mode.
*/ */
if (status & MCI_RXACTIVE && host->size < variant->fifosize) if (status & MCI_RXACTIVE && host->size < variant->fifosize)
writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); mmci_set_mask1(host, MCI_RXDATAAVLBLMASK);
/* /*
* If we run out of data, disable the data IRQs; this * If we run out of data, disable the data IRQs; this
...@@ -446,7 +462,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) ...@@ -446,7 +462,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
* stops us racing with our data end IRQ. * stops us racing with our data end IRQ.
*/ */
if (host->size == 0) { if (host->size == 0) {
writel(0, base + MMCIMASK1); mmci_set_mask1(host, 0);
writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0); writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
} }
...@@ -469,6 +485,14 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) ...@@ -469,6 +485,14 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
struct mmc_data *data; struct mmc_data *data;
status = readl(host->base + MMCISTATUS); status = readl(host->base + MMCISTATUS);
if (host->singleirq) {
if (status & readl(host->base + MMCIMASK1))
mmci_pio_irq(irq, dev_id);
status &= ~MCI_IRQ1MASK;
}
status &= readl(host->base + MMCIMASK0); status &= readl(host->base + MMCIMASK0);
writel(status, host->base + MMCICLEAR); writel(status, host->base + MMCICLEAR);
...@@ -635,6 +659,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) ...@@ -635,6 +659,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
struct variant_data *variant = id->data; struct variant_data *variant = id->data;
struct mmci_host *host; struct mmci_host *host;
struct mmc_host *mmc; struct mmc_host *mmc;
unsigned int mask;
int ret; int ret;
/* must have platform data */ /* must have platform data */
...@@ -806,11 +831,17 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) ...@@ -806,11 +831,17 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
if (ret) if (ret)
goto unmap; goto unmap;
ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, DRIVER_NAME " (pio)", host); if (dev->irq[1] == NO_IRQ)
if (ret) host->singleirq = true;
goto irq0_free; else {
ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED,
DRIVER_NAME " (pio)", host);
if (ret)
goto irq0_free;
}
writel(MCI_IRQENABLE, host->base + MMCIMASK0); mask = MCI_IRQENABLE;
writel(mask, host->base + MMCIMASK0);
amba_set_drvdata(dev, mmc); amba_set_drvdata(dev, mmc);
...@@ -864,7 +895,8 @@ static int __devexit mmci_remove(struct amba_device *dev) ...@@ -864,7 +895,8 @@ static int __devexit mmci_remove(struct amba_device *dev)
writel(0, host->base + MMCIDATACTRL); writel(0, host->base + MMCIDATACTRL);
free_irq(dev->irq[0], host); free_irq(dev->irq[0], host);
free_irq(dev->irq[1], host); if (!host->singleirq)
free_irq(dev->irq[1], host);
if (host->gpio_wp != -ENOSYS) if (host->gpio_wp != -ENOSYS)
gpio_free(host->gpio_wp); gpio_free(host->gpio_wp);
......
...@@ -139,6 +139,11 @@ ...@@ -139,6 +139,11 @@
MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK) MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
/* These interrupts are directed to IRQ1 when two IRQ lines are available */
#define MCI_IRQ1MASK \
(MCI_RXFIFOHALFFULLMASK | MCI_RXDATAAVLBLMASK | \
MCI_TXFIFOHALFEMPTYMASK)
#define NR_SG 16 #define NR_SG 16
struct clk; struct clk;
...@@ -154,6 +159,7 @@ struct mmci_host { ...@@ -154,6 +159,7 @@ struct mmci_host {
int gpio_cd; int gpio_cd;
int gpio_wp; int gpio_wp;
int gpio_cd_irq; int gpio_cd_irq;
bool singleirq;
unsigned int data_xfered; unsigned int data_xfered;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册