Skip to content

Commit

Permalink
ARM: 6311/2: mmci: work with only one irq
Browse files Browse the repository at this point in the history
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: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Linus Walleij authored and Russell King committed Nov 10, 2010
1 parent f6614b7 commit 2686b4b
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
50 changes: 41 additions & 9 deletions drivers/mmc/host/mmci.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,26 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
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)
{
writel(0, host->base + MMCIDATACTRL);
writel(0, host->base + MMCIMASK1);
mmci_set_mask1(host, 0);
host->data = NULL;
}

Expand Down Expand Up @@ -198,7 +214,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)

writel(datactrl, base + MMCIDATACTRL);
writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);
writel(irqmask, base + MMCIMASK1);
mmci_set_mask1(host, irqmask);
}

static void
Expand Down Expand Up @@ -437,7 +453,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
* "any data available" mode.
*/
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
Expand All @@ -446,7 +462,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
* stops us racing with our data end IRQ.
*/
if (host->size == 0) {
writel(0, base + MMCIMASK1);
mmci_set_mask1(host, 0);
writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
}

Expand All @@ -469,6 +485,14 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
struct mmc_data *data;

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);
writel(status, host->base + MMCICLEAR);

Expand Down Expand Up @@ -635,6 +659,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
struct variant_data *variant = id->data;
struct mmci_host *host;
struct mmc_host *mmc;
unsigned int mask;
int ret;

/* must have platform data */
Expand Down Expand Up @@ -806,11 +831,17 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
if (ret)
goto unmap;

ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, DRIVER_NAME " (pio)", host);
if (ret)
goto irq0_free;
if (dev->irq[1] == NO_IRQ)
host->singleirq = true;
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);

Expand Down Expand Up @@ -864,7 +895,8 @@ static int __devexit mmci_remove(struct amba_device *dev)
writel(0, host->base + MMCIDATACTRL);

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)
gpio_free(host->gpio_wp);
Expand Down
6 changes: 6 additions & 0 deletions drivers/mmc/host/mmci.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@
MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
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

struct clk;
Expand All @@ -154,6 +159,7 @@ struct mmci_host {
int gpio_cd;
int gpio_wp;
int gpio_cd_irq;
bool singleirq;

unsigned int data_xfered;

Expand Down

0 comments on commit 2686b4b

Please sign in to comment.