diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2009-03-16 17:13:48 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2009-03-24 16:30:08 -0400 |
commit | 7260cf5e12393536ce61d184c3fc750fb2ba635a (patch) | |
tree | d5ffc4ed3d4051670dc93581cdbd22b2091ceee7 | |
parent | 4e4141a526dd7f5ac3ce1458ae79ea6e5a515b06 (diff) |
sdhci: Split card-detection IRQs management from sdhci_init()
Card detection interrupts should be handled separately as they should
not be enabled before mmc_add_host() returns and should be disabled
before calling mmc_remove_host(). The same is for suspend and resume
routines.
sdhci_init() no longer enables card-detection irqs. Instead, two new
functions implemented: sdhci_enable_card_detection() and
sdhci_disable_card_detection().
New sdhci_reinit() call implemented to behave the same way as the old
sdhci_init().
Also, this patch implements and uses few new helpers to manage IRQs in
a more conveinient way, that is:
- sdhci_clear_set_irqs()
- sdhci_unmask_irqs()
- sdhci_mask_irqs()
- SDHCI_INT_ALL_MASK constant
sdhci_enable_sdio_irq() converted to these new helpers, plus the
helpers will be used by the subsequent patches.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
-rw-r--r-- | drivers/mmc/host/sdhci.c | 78 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 1 |
2 files changed, 62 insertions, 17 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index fd36b822f809..bd5acfb0c1b8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -87,6 +87,47 @@ static void sdhci_dumpregs(struct sdhci_host *host) | |||
87 | * * | 87 | * * |
88 | \*****************************************************************************/ | 88 | \*****************************************************************************/ |
89 | 89 | ||
90 | static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) | ||
91 | { | ||
92 | u32 ier; | ||
93 | |||
94 | ier = sdhci_readl(host, SDHCI_INT_ENABLE); | ||
95 | ier &= ~clear; | ||
96 | ier |= set; | ||
97 | sdhci_writel(host, ier, SDHCI_INT_ENABLE); | ||
98 | sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); | ||
99 | } | ||
100 | |||
101 | static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs) | ||
102 | { | ||
103 | sdhci_clear_set_irqs(host, 0, irqs); | ||
104 | } | ||
105 | |||
106 | static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs) | ||
107 | { | ||
108 | sdhci_clear_set_irqs(host, irqs, 0); | ||
109 | } | ||
110 | |||
111 | static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) | ||
112 | { | ||
113 | u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT; | ||
114 | |||
115 | if (enable) | ||
116 | sdhci_unmask_irqs(host, irqs); | ||
117 | else | ||
118 | sdhci_mask_irqs(host, irqs); | ||
119 | } | ||
120 | |||
121 | static void sdhci_enable_card_detection(struct sdhci_host *host) | ||
122 | { | ||
123 | sdhci_set_card_detection(host, true); | ||
124 | } | ||
125 | |||
126 | static void sdhci_disable_card_detection(struct sdhci_host *host) | ||
127 | { | ||
128 | sdhci_set_card_detection(host, false); | ||
129 | } | ||
130 | |||
90 | static void sdhci_reset(struct sdhci_host *host, u8 mask) | 131 | static void sdhci_reset(struct sdhci_host *host, u8 mask) |
91 | { | 132 | { |
92 | unsigned long timeout; | 133 | unsigned long timeout; |
@@ -120,20 +161,21 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) | |||
120 | 161 | ||
121 | static void sdhci_init(struct sdhci_host *host) | 162 | static void sdhci_init(struct sdhci_host *host) |
122 | { | 163 | { |
123 | u32 intmask; | ||
124 | |||
125 | sdhci_reset(host, SDHCI_RESET_ALL); | 164 | sdhci_reset(host, SDHCI_RESET_ALL); |
126 | 165 | ||
127 | intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | | 166 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, |
167 | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | | ||
128 | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | | 168 | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | |
129 | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | | 169 | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | |
130 | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT | | ||
131 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | | 170 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | |
132 | SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE | | 171 | SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE | |
133 | SDHCI_INT_ADMA_ERROR; | 172 | SDHCI_INT_ADMA_ERROR); |
173 | } | ||
134 | 174 | ||
135 | sdhci_writel(host, intmask, SDHCI_INT_ENABLE); | 175 | static void sdhci_reinit(struct sdhci_host *host) |
136 | sdhci_writel(host, intmask, SDHCI_SIGNAL_ENABLE); | 176 | { |
177 | sdhci_init(host); | ||
178 | sdhci_enable_card_detection(host); | ||
137 | } | 179 | } |
138 | 180 | ||
139 | static void sdhci_activate_led(struct sdhci_host *host) | 181 | static void sdhci_activate_led(struct sdhci_host *host) |
@@ -1032,7 +1074,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1032 | */ | 1074 | */ |
1033 | if (ios->power_mode == MMC_POWER_OFF) { | 1075 | if (ios->power_mode == MMC_POWER_OFF) { |
1034 | sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); | 1076 | sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); |
1035 | sdhci_init(host); | 1077 | sdhci_reinit(host); |
1036 | } | 1078 | } |
1037 | 1079 | ||
1038 | sdhci_set_clock(host, ios->clock); | 1080 | sdhci_set_clock(host, ios->clock); |
@@ -1093,7 +1135,6 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
1093 | { | 1135 | { |
1094 | struct sdhci_host *host; | 1136 | struct sdhci_host *host; |
1095 | unsigned long flags; | 1137 | unsigned long flags; |
1096 | u32 ier; | ||
1097 | 1138 | ||
1098 | host = mmc_priv(mmc); | 1139 | host = mmc_priv(mmc); |
1099 | 1140 | ||
@@ -1102,15 +1143,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
1102 | if (host->flags & SDHCI_DEVICE_DEAD) | 1143 | if (host->flags & SDHCI_DEVICE_DEAD) |
1103 | goto out; | 1144 | goto out; |
1104 | 1145 | ||
1105 | ier = sdhci_readl(host, SDHCI_INT_ENABLE); | ||
1106 | |||
1107 | ier &= ~SDHCI_INT_CARD_INT; | ||
1108 | if (enable) | 1146 | if (enable) |
1109 | ier |= SDHCI_INT_CARD_INT; | 1147 | sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); |
1110 | 1148 | else | |
1111 | sdhci_writel(host, ier, SDHCI_INT_ENABLE); | 1149 | sdhci_mask_irqs(host, SDHCI_INT_CARD_INT); |
1112 | sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); | ||
1113 | |||
1114 | out: | 1150 | out: |
1115 | mmiowb(); | 1151 | mmiowb(); |
1116 | 1152 | ||
@@ -1452,6 +1488,8 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) | |||
1452 | { | 1488 | { |
1453 | int ret; | 1489 | int ret; |
1454 | 1490 | ||
1491 | sdhci_disable_card_detection(host); | ||
1492 | |||
1455 | ret = mmc_suspend_host(host->mmc, state); | 1493 | ret = mmc_suspend_host(host->mmc, state); |
1456 | if (ret) | 1494 | if (ret) |
1457 | return ret; | 1495 | return ret; |
@@ -1484,6 +1522,8 @@ int sdhci_resume_host(struct sdhci_host *host) | |||
1484 | if (ret) | 1522 | if (ret) |
1485 | return ret; | 1523 | return ret; |
1486 | 1524 | ||
1525 | sdhci_enable_card_detection(host); | ||
1526 | |||
1487 | return 0; | 1527 | return 0; |
1488 | } | 1528 | } |
1489 | 1529 | ||
@@ -1743,6 +1783,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1743 | (host->flags & SDHCI_USE_ADMA)?"A":"", | 1783 | (host->flags & SDHCI_USE_ADMA)?"A":"", |
1744 | (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); | 1784 | (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); |
1745 | 1785 | ||
1786 | sdhci_enable_card_detection(host); | ||
1787 | |||
1746 | return 0; | 1788 | return 0; |
1747 | 1789 | ||
1748 | #ifdef SDHCI_USE_LEDS_CLASS | 1790 | #ifdef SDHCI_USE_LEDS_CLASS |
@@ -1779,6 +1821,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) | |||
1779 | spin_unlock_irqrestore(&host->lock, flags); | 1821 | spin_unlock_irqrestore(&host->lock, flags); |
1780 | } | 1822 | } |
1781 | 1823 | ||
1824 | sdhci_disable_card_detection(host); | ||
1825 | |||
1782 | mmc_remove_host(host->mmc); | 1826 | mmc_remove_host(host->mmc); |
1783 | 1827 | ||
1784 | #ifdef SDHCI_USE_LEDS_CLASS | 1828 | #ifdef SDHCI_USE_LEDS_CLASS |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index d9733f841061..a9e25c6c0c0e 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -126,6 +126,7 @@ | |||
126 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ | 126 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ |
127 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ | 127 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ |
128 | SDHCI_INT_DATA_END_BIT) | 128 | SDHCI_INT_DATA_END_BIT) |
129 | #define SDHCI_INT_ALL_MASK ((unsigned int)-1) | ||
129 | 130 | ||
130 | #define SDHCI_ACMD12_ERR 0x3C | 131 | #define SDHCI_ACMD12_ERR 0x3C |
131 | 132 | ||