aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorArnd Hannemann <arnd@arndnet.de>2010-12-28 17:22:31 -0500
committerChris Ball <cjb@laptop.org>2011-01-08 23:52:30 -0500
commit845ecd20239c28e97e766ff54078a58be19f3a91 (patch)
treeac25a1b5e5769c9207c9fd886acd4380a3184701 /drivers/mmc
parent39a65a0dbbf73403daa9f4cc0ab30957ba61e60f (diff)
mmc: tmio_mmc: implement SDIO IRQ support
This patch implements SDIO IRQ support for mfds which announce the TMIO_MMC_SDIO_IRQ flag for tmio_mmc. If MMC_CAP_SDIO_IRQ is also set SDIO IRQ signalling is activated. Tested with a b43-based wireless SDIO card and sh_mobile_sdhi. Signed-off-by: Arnd Hannemann <arnd@arndnet.de> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/tmio_mmc.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index f442c8205b0a..81bed310ddcd 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -53,6 +53,8 @@
53#define CTL_SD_ERROR_DETAIL_STATUS 0x2c 53#define CTL_SD_ERROR_DETAIL_STATUS 0x2c
54#define CTL_SD_DATA_PORT 0x30 54#define CTL_SD_DATA_PORT 0x30
55#define CTL_TRANSACTION_CTL 0x34 55#define CTL_TRANSACTION_CTL 0x34
56#define CTL_SDIO_STATUS 0x36
57#define CTL_SDIO_IRQ_MASK 0x38
56#define CTL_RESET_SD 0xe0 58#define CTL_RESET_SD 0xe0
57#define CTL_SDIO_REGS 0x100 59#define CTL_SDIO_REGS 0x100
58#define CTL_CLK_AND_WAIT_CTL 0x138 60#define CTL_CLK_AND_WAIT_CTL 0x138
@@ -81,6 +83,12 @@
81#define TMIO_STAT_CMD_BUSY 0x40000000 83#define TMIO_STAT_CMD_BUSY 0x40000000
82#define TMIO_STAT_ILL_ACCESS 0x80000000 84#define TMIO_STAT_ILL_ACCESS 0x80000000
83 85
86/* Definitions for values the CTRL_SDIO_STATUS register can take. */
87#define TMIO_SDIO_STAT_IOIRQ 0x0001
88#define TMIO_SDIO_STAT_EXPUB52 0x4000
89#define TMIO_SDIO_STAT_EXWT 0x8000
90#define TMIO_SDIO_MASK_ALL 0xc007
91
84/* Define some IRQ masks */ 92/* Define some IRQ masks */
85/* This is the mask used at reset by the chip */ 93/* This is the mask used at reset by the chip */
86#define TMIO_MASK_ALL 0x837f031d 94#define TMIO_MASK_ALL 0x837f031d
@@ -122,6 +130,7 @@ struct tmio_mmc_host {
122 struct mmc_data *data; 130 struct mmc_data *data;
123 struct mmc_host *mmc; 131 struct mmc_host *mmc;
124 int irq; 132 int irq;
133 unsigned int sdio_irq_enabled;
125 134
126 /* Callbacks for clock / power control */ 135 /* Callbacks for clock / power control */
127 void (*set_pwr)(struct platform_device *host, int state); 136 void (*set_pwr)(struct platform_device *host, int state);
@@ -249,6 +258,22 @@ void pr_debug_status(u32 status)
249#define pr_debug_status(s) do { } while (0) 258#define pr_debug_status(s) do { } while (0)
250#endif 259#endif
251 260
261static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
262{
263 struct tmio_mmc_host *host = mmc_priv(mmc);
264
265 if (enable) {
266 host->sdio_irq_enabled = 1;
267 sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
268 sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK,
269 (TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ));
270 } else {
271 sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL);
272 sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
273 host->sdio_irq_enabled = 0;
274 }
275}
276
252static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) 277static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
253{ 278{
254 u32 clk = 0, clock; 279 u32 clk = 0, clock;
@@ -268,8 +293,23 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
268 293
269static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) 294static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
270{ 295{
296 struct mfd_cell *cell = host->pdev->dev.platform_data;
297 struct tmio_mmc_data *pdata = cell->driver_data;
298
299 /*
300 * Testing on sh-mobile showed that SDIO IRQs are unmasked when
301 * CTL_CLK_AND_WAIT_CTL gets written, so we have to disable the
302 * device IRQ here and restore the SDIO IRQ mask before
303 * re-enabling the device IRQ.
304 */
305 if (pdata->flags & TMIO_MMC_SDIO_IRQ)
306 disable_irq(host->irq);
271 sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000); 307 sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
272 msleep(10); 308 msleep(10);
309 if (pdata->flags & TMIO_MMC_SDIO_IRQ) {
310 tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled);
311 enable_irq(host->irq);
312 }
273 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 & 313 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 &
274 sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); 314 sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
275 msleep(10); 315 msleep(10);
@@ -277,11 +317,21 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
277 317
278static void tmio_mmc_clk_start(struct tmio_mmc_host *host) 318static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
279{ 319{
320 struct mfd_cell *cell = host->pdev->dev.platform_data;
321 struct tmio_mmc_data *pdata = cell->driver_data;
322
280 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | 323 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
281 sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); 324 sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
282 msleep(10); 325 msleep(10);
326 /* see comment in tmio_mmc_clk_stop above */
327 if (pdata->flags & TMIO_MMC_SDIO_IRQ)
328 disable_irq(host->irq);
283 sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); 329 sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
284 msleep(10); 330 msleep(10);
331 if (pdata->flags & TMIO_MMC_SDIO_IRQ) {
332 tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled);
333 enable_irq(host->irq);
334 }
285} 335}
286 336
287static void reset(struct tmio_mmc_host *host) 337static void reset(struct tmio_mmc_host *host)
@@ -554,7 +604,10 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
554static irqreturn_t tmio_mmc_irq(int irq, void *devid) 604static irqreturn_t tmio_mmc_irq(int irq, void *devid)
555{ 605{
556 struct tmio_mmc_host *host = devid; 606 struct tmio_mmc_host *host = devid;
607 struct mfd_cell *cell = host->pdev->dev.platform_data;
608 struct tmio_mmc_data *pdata = cell->driver_data;
557 unsigned int ireg, irq_mask, status; 609 unsigned int ireg, irq_mask, status;
610 unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
558 611
559 pr_debug("MMC IRQ begin\n"); 612 pr_debug("MMC IRQ begin\n");
560 613
@@ -562,6 +615,29 @@ static irqreturn_t tmio_mmc_irq(int irq, void *devid)
562 irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK); 615 irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
563 ireg = status & TMIO_MASK_IRQ & ~irq_mask; 616 ireg = status & TMIO_MASK_IRQ & ~irq_mask;
564 617
618 sdio_ireg = 0;
619 if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) {
620 sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
621 sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK);
622 sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask;
623
624 sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL);
625
626 if (sdio_ireg && !host->sdio_irq_enabled) {
627 pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
628 sdio_status, sdio_irq_mask, sdio_ireg);
629 tmio_mmc_enable_sdio_irq(host->mmc, 0);
630 goto out;
631 }
632
633 if (host->mmc->caps & MMC_CAP_SDIO_IRQ &&
634 sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
635 mmc_signal_sdio_irq(host->mmc);
636
637 if (sdio_ireg)
638 goto out;
639 }
640
565 pr_debug_status(status); 641 pr_debug_status(status);
566 pr_debug_status(ireg); 642 pr_debug_status(ireg);
567 643
@@ -1047,6 +1123,7 @@ static const struct mmc_host_ops tmio_mmc_ops = {
1047 .set_ios = tmio_mmc_set_ios, 1123 .set_ios = tmio_mmc_set_ios,
1048 .get_ro = tmio_mmc_get_ro, 1124 .get_ro = tmio_mmc_get_ro,
1049 .get_cd = tmio_mmc_get_cd, 1125 .get_cd = tmio_mmc_get_cd,
1126 .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
1050}; 1127};
1051 1128
1052#ifdef CONFIG_PM 1129#ifdef CONFIG_PM
@@ -1162,6 +1239,8 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
1162 goto cell_disable; 1239 goto cell_disable;
1163 1240
1164 disable_mmc_irqs(host, TMIO_MASK_ALL); 1241 disable_mmc_irqs(host, TMIO_MASK_ALL);
1242 if (pdata->flags & TMIO_MMC_SDIO_IRQ)
1243 tmio_mmc_enable_sdio_irq(mmc, 0);
1165 1244
1166 ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | 1245 ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
1167 IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host); 1246 IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);