Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Arnd Hannemann and committed by
Chris Ball
845ecd20 39a65a0d

+83
+79
drivers/mmc/host/tmio_mmc.c
··· 53 53 #define CTL_SD_ERROR_DETAIL_STATUS 0x2c 54 54 #define CTL_SD_DATA_PORT 0x30 55 55 #define CTL_TRANSACTION_CTL 0x34 56 + #define CTL_SDIO_STATUS 0x36 57 + #define CTL_SDIO_IRQ_MASK 0x38 56 58 #define CTL_RESET_SD 0xe0 57 59 #define CTL_SDIO_REGS 0x100 58 60 #define CTL_CLK_AND_WAIT_CTL 0x138 ··· 82 80 #define TMIO_STAT_ILL_FUNC 0x20000000 83 81 #define TMIO_STAT_CMD_BUSY 0x40000000 84 82 #define TMIO_STAT_ILL_ACCESS 0x80000000 83 + 84 + /* Definitions for values the CTRL_SDIO_STATUS register can take. */ 85 + #define TMIO_SDIO_STAT_IOIRQ 0x0001 86 + #define TMIO_SDIO_STAT_EXPUB52 0x4000 87 + #define TMIO_SDIO_STAT_EXWT 0x8000 88 + #define TMIO_SDIO_MASK_ALL 0xc007 85 89 86 90 /* Define some IRQ masks */ 87 91 /* This is the mask used at reset by the chip */ ··· 130 122 struct mmc_data *data; 131 123 struct mmc_host *mmc; 132 124 int irq; 125 + unsigned int sdio_irq_enabled; 133 126 134 127 /* Callbacks for clock / power control */ 135 128 void (*set_pwr)(struct platform_device *host, int state); ··· 258 249 #define pr_debug_status(s) do { } while (0) 259 250 #endif 260 251 252 + static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) 253 + { 254 + struct tmio_mmc_host *host = mmc_priv(mmc); 255 + 256 + if (enable) { 257 + host->sdio_irq_enabled = 1; 258 + sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); 259 + sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, 260 + (TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ)); 261 + } else { 262 + sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL); 263 + sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000); 264 + host->sdio_irq_enabled = 0; 265 + } 266 + } 267 + 261 268 static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) 262 269 { 263 270 u32 clk = 0, clock; ··· 293 268 294 269 static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) 295 270 { 271 + struct mfd_cell *cell = host->pdev->dev.platform_data; 272 + struct tmio_mmc_data *pdata = cell->driver_data; 273 + 274 + /* 275 + * Testing on sh-mobile showed that SDIO IRQs are unmasked when 276 + * CTL_CLK_AND_WAIT_CTL gets written, so we have to disable the 277 + * device IRQ here and restore the SDIO IRQ mask before 278 + * re-enabling the device IRQ. 279 + */ 280 + if (pdata->flags & TMIO_MMC_SDIO_IRQ) 281 + disable_irq(host->irq); 296 282 sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000); 297 283 msleep(10); 284 + if (pdata->flags & TMIO_MMC_SDIO_IRQ) { 285 + tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled); 286 + enable_irq(host->irq); 287 + } 298 288 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 & 299 289 sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); 300 290 msleep(10); ··· 317 277 318 278 static void tmio_mmc_clk_start(struct tmio_mmc_host *host) 319 279 { 280 + struct mfd_cell *cell = host->pdev->dev.platform_data; 281 + struct tmio_mmc_data *pdata = cell->driver_data; 282 + 320 283 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | 321 284 sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); 322 285 msleep(10); 286 + /* see comment in tmio_mmc_clk_stop above */ 287 + if (pdata->flags & TMIO_MMC_SDIO_IRQ) 288 + disable_irq(host->irq); 323 289 sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); 324 290 msleep(10); 291 + if (pdata->flags & TMIO_MMC_SDIO_IRQ) { 292 + tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled); 293 + enable_irq(host->irq); 294 + } 325 295 } 326 296 327 297 static void reset(struct tmio_mmc_host *host) ··· 604 554 static irqreturn_t tmio_mmc_irq(int irq, void *devid) 605 555 { 606 556 struct tmio_mmc_host *host = devid; 557 + struct mfd_cell *cell = host->pdev->dev.platform_data; 558 + struct tmio_mmc_data *pdata = cell->driver_data; 607 559 unsigned int ireg, irq_mask, status; 560 + unsigned int sdio_ireg, sdio_irq_mask, sdio_status; 608 561 609 562 pr_debug("MMC IRQ begin\n"); 610 563 611 564 status = sd_ctrl_read32(host, CTL_STATUS); 612 565 irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK); 613 566 ireg = status & TMIO_MASK_IRQ & ~irq_mask; 567 + 568 + sdio_ireg = 0; 569 + if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) { 570 + sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS); 571 + sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK); 572 + sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask; 573 + 574 + sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL); 575 + 576 + if (sdio_ireg && !host->sdio_irq_enabled) { 577 + pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n", 578 + sdio_status, sdio_irq_mask, sdio_ireg); 579 + tmio_mmc_enable_sdio_irq(host->mmc, 0); 580 + goto out; 581 + } 582 + 583 + if (host->mmc->caps & MMC_CAP_SDIO_IRQ && 584 + sdio_ireg & TMIO_SDIO_STAT_IOIRQ) 585 + mmc_signal_sdio_irq(host->mmc); 586 + 587 + if (sdio_ireg) 588 + goto out; 589 + } 614 590 615 591 pr_debug_status(status); 616 592 pr_debug_status(ireg); ··· 1123 1047 .set_ios = tmio_mmc_set_ios, 1124 1048 .get_ro = tmio_mmc_get_ro, 1125 1049 .get_cd = tmio_mmc_get_cd, 1050 + .enable_sdio_irq = tmio_mmc_enable_sdio_irq, 1126 1051 }; 1127 1052 1128 1053 #ifdef CONFIG_PM ··· 1239 1162 goto cell_disable; 1240 1163 1241 1164 disable_mmc_irqs(host, TMIO_MASK_ALL); 1165 + if (pdata->flags & TMIO_MMC_SDIO_IRQ) 1166 + tmio_mmc_enable_sdio_irq(mmc, 0); 1242 1167 1243 1168 ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | 1244 1169 IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
+4
include/linux/mfd/tmio.h
··· 57 57 * is configured in 4-bit mode. 58 58 */ 59 59 #define TMIO_MMC_BLKSZ_2BYTES (1 << 1) 60 + /* 61 + * Some controllers can support SDIO IRQ signalling. 62 + */ 63 + #define TMIO_MMC_SDIO_IRQ (1 << 2) 60 64 61 65 int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base); 62 66 int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);