Re: [PATCH v11 2/7] mmc: omap_hsmmc: Enable SDIO interrupt
On Friday 09 May 2014 04:50 AM, Andreas Fenkart wrote: There have been various patches floating around for enabling the SDIO IRQ for hsmmc, but none of them ever got merged. Probably the reason for not merging the SDIO interrupt patches has been the lack of wake-up path for SDIO on some omaps that has also needed remuxing the SDIO DAT1 line to a GPIO making the patches complex. This patch adds the minimal SDIO IRQ support to hsmmc for omaps that do have the wake-up path. For those omaps, the DAT1 line need to have the wake-up enable bit set, and the wake-up interrupt is the same as for the MMC controller. This patch has been tested on am3730 es1.2 with mwifiex connected to MMC3 with mwifiex waking to Ethernet traffic from off-idle mode. Note that for omaps that do not have the SDIO wake-up path, this patch will not work for idle modes and further patches for remuxing DAT1 to GPIO are needed. Based on earlier patches [1][2] by David Vrabel david.vra...@csr.com, Steve Sakoman st...@sakoman.com For now, only support SDIO interrupt if we are booted with a separate wake-irq configued via device tree. This is because omaps need the wake-irq for idle states, and some omaps need special quirks. And we don't want to add new legacy mux platform init code callbacks any longer as we are moving to DT based booting anyways. To use it, you need to specify the wake-irq using the interrupts-extended property. [1] http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux.git;a=commitdiff_plain;h=010810d22f6f49ac03da4ba384969432e0320453 [2] http://comments.gmane.org/gmane.linux.kernel.mmc/20446 Cc: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Tony Lindgren t...@atomide.com Hi Andreas, Thanks for the new patch series. Minor nit below, other than that Acked-by: Balaji T K balaj...@ti.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5042a15..f43a69e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -29,6 +29,7 @@ #include linux/timer.h #include linux/clk.h #include linux/of.h +#include linux/of_irq.h #include linux/of_gpio.h #include linux/of_device.h #include linux/omap-dma.h @@ -36,6 +37,7 @@ #include linux/mmc/core.h #include linux/mmc/mmc.h #include linux/io.h +#include linux/irq.h #include linux/gpio.h #include linux/regulator/consumer.h #include linux/pinctrl/consumer.h @@ -133,6 +135,7 @@ static void apply_clk_hack(struct device *dev) #define TC_EN (1 1) #define BWR_EN(1 4) #define BRR_EN(1 5) +#define CIRQ_EN(1 8) #define ERR_EN(1 15) #define CTO_EN(1 16) #define CCRC_EN (1 17) @@ -167,7 +170,6 @@ static void apply_clk_hack(struct device *dev) #define VDD_3V0 300 /* 30 uV */ #define VDD_165_195 (ffs(MMC_VDD_165_195) - 1) -#define AUTO_CMD23 (1 1) /* Auto CMD23 support */ /* * One controller can have multiple slots, like on some omap boards using * omap.c controller driver. Luckily this is not currently done on any known @@ -221,6 +223,7 @@ struct omap_hsmmc_host { u32 sysctl; u32 capa; int irq; + int wake_irq; int use_dma, dma_ch; struct dma_chan *tx_chan; struct dma_chan *rx_chan; @@ -233,6 +236,9 @@ struct omap_hsmmc_host { int req_in_progress; unsigned long clk_rate; unsigned intflags; +#define AUTO_CMD23 (1 0)/* Auto CMD23 support */ +#define HSMMC_SDIO_IRQ_ENABLED (1 1)/* SDIO irq enabled */ +#define HSMMC_WAKE_IRQ_ENABLED (1 2) struct omap_hsmmc_next next_data; struct omap_mmc_platform_data *pdata; }; @@ -537,27 +543,40 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, struct mmc_command *cmd) { - unsigned int irq_mask; + u32 irq_mask = INT_EN_MASK; + unsigned long flags; if (host-use_dma) - irq_mask = INT_EN_MASK ~(BRR_EN | BWR_EN); - else - irq_mask = INT_EN_MASK; + irq_mask = ~(BRR_EN | BWR_EN); /* Disable timeout for erases */ if (cmd-opcode == MMC_ERASE) irq_mask = ~DTO_EN; + spin_lock_irqsave(host-irq_lock, flags); OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host-base, ISE, irq_mask); + + /* latch pending CIRQ, but don't signal MMC core */ + if (host-flags HSMMC_SDIO_IRQ_ENABLED) + irq_mask |= CIRQ_EN; OMAP_HSMMC_WRITE(host-base,
[PATCH v11 2/7] mmc: omap_hsmmc: Enable SDIO interrupt
There have been various patches floating around for enabling the SDIO IRQ for hsmmc, but none of them ever got merged. Probably the reason for not merging the SDIO interrupt patches has been the lack of wake-up path for SDIO on some omaps that has also needed remuxing the SDIO DAT1 line to a GPIO making the patches complex. This patch adds the minimal SDIO IRQ support to hsmmc for omaps that do have the wake-up path. For those omaps, the DAT1 line need to have the wake-up enable bit set, and the wake-up interrupt is the same as for the MMC controller. This patch has been tested on am3730 es1.2 with mwifiex connected to MMC3 with mwifiex waking to Ethernet traffic from off-idle mode. Note that for omaps that do not have the SDIO wake-up path, this patch will not work for idle modes and further patches for remuxing DAT1 to GPIO are needed. Based on earlier patches [1][2] by David Vrabel david.vra...@csr.com, Steve Sakoman st...@sakoman.com For now, only support SDIO interrupt if we are booted with a separate wake-irq configued via device tree. This is because omaps need the wake-irq for idle states, and some omaps need special quirks. And we don't want to add new legacy mux platform init code callbacks any longer as we are moving to DT based booting anyways. To use it, you need to specify the wake-irq using the interrupts-extended property. [1] http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux.git;a=commitdiff_plain;h=010810d22f6f49ac03da4ba384969432e0320453 [2] http://comments.gmane.org/gmane.linux.kernel.mmc/20446 Cc: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Tony Lindgren t...@atomide.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5042a15..f43a69e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -29,6 +29,7 @@ #include linux/timer.h #include linux/clk.h #include linux/of.h +#include linux/of_irq.h #include linux/of_gpio.h #include linux/of_device.h #include linux/omap-dma.h @@ -36,6 +37,7 @@ #include linux/mmc/core.h #include linux/mmc/mmc.h #include linux/io.h +#include linux/irq.h #include linux/gpio.h #include linux/regulator/consumer.h #include linux/pinctrl/consumer.h @@ -133,6 +135,7 @@ static void apply_clk_hack(struct device *dev) #define TC_EN (1 1) #define BWR_EN (1 4) #define BRR_EN (1 5) +#define CIRQ_EN(1 8) #define ERR_EN (1 15) #define CTO_EN (1 16) #define CCRC_EN(1 17) @@ -167,7 +170,6 @@ static void apply_clk_hack(struct device *dev) #define VDD_3V0300 /* 30 uV */ #define VDD_165_195(ffs(MMC_VDD_165_195) - 1) -#define AUTO_CMD23 (1 1)/* Auto CMD23 support */ /* * One controller can have multiple slots, like on some omap boards using * omap.c controller driver. Luckily this is not currently done on any known @@ -221,6 +223,7 @@ struct omap_hsmmc_host { u32 sysctl; u32 capa; int irq; + int wake_irq; int use_dma, dma_ch; struct dma_chan *tx_chan; struct dma_chan *rx_chan; @@ -233,6 +236,9 @@ struct omap_hsmmc_host { int req_in_progress; unsigned long clk_rate; unsigned intflags; +#define AUTO_CMD23 (1 0)/* Auto CMD23 support */ +#define HSMMC_SDIO_IRQ_ENABLED (1 1)/* SDIO irq enabled */ +#define HSMMC_WAKE_IRQ_ENABLED (1 2) struct omap_hsmmc_next next_data; struct omap_mmc_platform_data *pdata; }; @@ -537,27 +543,40 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, struct mmc_command *cmd) { - unsigned int irq_mask; + u32 irq_mask = INT_EN_MASK; + unsigned long flags; if (host-use_dma) - irq_mask = INT_EN_MASK ~(BRR_EN | BWR_EN); - else - irq_mask = INT_EN_MASK; + irq_mask = ~(BRR_EN | BWR_EN); /* Disable timeout for erases */ if (cmd-opcode == MMC_ERASE) irq_mask = ~DTO_EN; + spin_lock_irqsave(host-irq_lock, flags); OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host-base, ISE, irq_mask); + + /* latch pending CIRQ, but don't signal MMC core */ + if (host-flags HSMMC_SDIO_IRQ_ENABLED) + irq_mask |= CIRQ_EN; OMAP_HSMMC_WRITE(host-base, IE, irq_mask); + spin_unlock_irqrestore(host-irq_lock, flags); } static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host) { - OMAP_HSMMC_WRITE(host-base, ISE, 0); -