diff options
author | Richard Zhu <Hong-Xing.Zhu@freescale.com> | 2011-03-25 09:18:27 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-03-25 10:30:50 -0400 |
commit | e149860d16d96aef1a8eb7dc1d0b9d4313479e61 (patch) | |
tree | ada702bf46750da48f165ffc49a18dd9dd870e63 /drivers/mmc/host/sdhci-esdhc-imx.c | |
parent | 574e3f5602d930a962f50dcc7124941c60c44084 (diff) |
mmc: sdhci-esdhc: use writel/readl as general APIs
Add one flag to indicate the GPIO CD/WP is enabled or not
on imx platforms, and reuse the writel/readl as the general
APIs for imx SOCs.
Signed-off-by: Richard Zhu <Hong-Xing.Zhu@freescale.com>
Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/sdhci-esdhc-imx.c')
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 3b5248567973..67a2da961bb5 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/mmc/host.h> | 20 | #include <linux/mmc/host.h> |
20 | #include <linux/mmc/sdhci-pltfm.h> | 21 | #include <linux/mmc/sdhci-pltfm.h> |
21 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
@@ -24,6 +25,13 @@ | |||
24 | #include "sdhci-pltfm.h" | 25 | #include "sdhci-pltfm.h" |
25 | #include "sdhci-esdhc.h" | 26 | #include "sdhci-esdhc.h" |
26 | 27 | ||
28 | #define ESDHC_FLAG_GPIO_FOR_CD_WP (1 << 0) | ||
29 | |||
30 | struct pltfm_imx_data { | ||
31 | int flags; | ||
32 | u32 scratchpad; | ||
33 | }; | ||
34 | |||
27 | static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) | 35 | static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) |
28 | { | 36 | { |
29 | void __iomem *base = host->ioaddr + (reg & ~0x3); | 37 | void __iomem *base = host->ioaddr + (reg & ~0x3); |
@@ -34,10 +42,14 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i | |||
34 | 42 | ||
35 | static u32 esdhc_readl_le(struct sdhci_host *host, int reg) | 43 | static u32 esdhc_readl_le(struct sdhci_host *host, int reg) |
36 | { | 44 | { |
45 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
46 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
47 | |||
37 | /* fake CARD_PRESENT flag on mx25/35 */ | 48 | /* fake CARD_PRESENT flag on mx25/35 */ |
38 | u32 val = readl(host->ioaddr + reg); | 49 | u32 val = readl(host->ioaddr + reg); |
39 | 50 | ||
40 | if (unlikely(reg == SDHCI_PRESENT_STATE)) { | 51 | if (unlikely((reg == SDHCI_PRESENT_STATE) |
52 | && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) { | ||
41 | struct esdhc_platform_data *boarddata = | 53 | struct esdhc_platform_data *boarddata = |
42 | host->mmc->parent->platform_data; | 54 | host->mmc->parent->platform_data; |
43 | 55 | ||
@@ -55,7 +67,11 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) | |||
55 | 67 | ||
56 | static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) | 68 | static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) |
57 | { | 69 | { |
58 | if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) | 70 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
71 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
72 | |||
73 | if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE) | ||
74 | && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) | ||
59 | /* | 75 | /* |
60 | * these interrupts won't work with a custom card_detect gpio | 76 | * these interrupts won't work with a custom card_detect gpio |
61 | * (only applied to mx25/35) | 77 | * (only applied to mx25/35) |
@@ -76,6 +92,7 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) | |||
76 | static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | 92 | static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) |
77 | { | 93 | { |
78 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 94 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
95 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
79 | 96 | ||
80 | switch (reg) { | 97 | switch (reg) { |
81 | case SDHCI_TRANSFER_MODE: | 98 | case SDHCI_TRANSFER_MODE: |
@@ -83,10 +100,10 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
83 | * Postpone this write, we must do it together with a | 100 | * Postpone this write, we must do it together with a |
84 | * command write that is down below. | 101 | * command write that is down below. |
85 | */ | 102 | */ |
86 | pltfm_host->scratchpad = val; | 103 | imx_data->scratchpad = val; |
87 | return; | 104 | return; |
88 | case SDHCI_COMMAND: | 105 | case SDHCI_COMMAND: |
89 | writel(val << 16 | pltfm_host->scratchpad, | 106 | writel(val << 16 | imx_data->scratchpad, |
90 | host->ioaddr + SDHCI_TRANSFER_MODE); | 107 | host->ioaddr + SDHCI_TRANSFER_MODE); |
91 | return; | 108 | return; |
92 | case SDHCI_BLOCK_SIZE: | 109 | case SDHCI_BLOCK_SIZE: |
@@ -146,7 +163,9 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) | |||
146 | } | 163 | } |
147 | 164 | ||
148 | static struct sdhci_ops sdhci_esdhc_ops = { | 165 | static struct sdhci_ops sdhci_esdhc_ops = { |
166 | .read_l = esdhc_readl_le, | ||
149 | .read_w = esdhc_readw_le, | 167 | .read_w = esdhc_readw_le, |
168 | .write_l = esdhc_writel_le, | ||
150 | .write_w = esdhc_writew_le, | 169 | .write_w = esdhc_writew_le, |
151 | .write_b = esdhc_writeb_le, | 170 | .write_b = esdhc_writeb_le, |
152 | .set_clock = esdhc_set_clock, | 171 | .set_clock = esdhc_set_clock, |
@@ -168,6 +187,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd | |||
168 | struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data; | 187 | struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data; |
169 | struct clk *clk; | 188 | struct clk *clk; |
170 | int err; | 189 | int err; |
190 | struct pltfm_imx_data *imx_data; | ||
171 | 191 | ||
172 | clk = clk_get(mmc_dev(host->mmc), NULL); | 192 | clk = clk_get(mmc_dev(host->mmc), NULL); |
173 | if (IS_ERR(clk)) { | 193 | if (IS_ERR(clk)) { |
@@ -177,7 +197,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd | |||
177 | clk_enable(clk); | 197 | clk_enable(clk); |
178 | pltfm_host->clk = clk; | 198 | pltfm_host->clk = clk; |
179 | 199 | ||
180 | if (cpu_is_mx35() || cpu_is_mx51()) | 200 | imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL); |
201 | if (!imx_data) { | ||
202 | clk_disable(pltfm_host->clk); | ||
203 | clk_put(pltfm_host->clk); | ||
204 | return -ENOMEM; | ||
205 | } | ||
206 | pltfm_host->priv = imx_data; | ||
207 | |||
208 | if (!cpu_is_mx25()) | ||
181 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; | 209 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; |
182 | 210 | ||
183 | if (cpu_is_mx25() || cpu_is_mx35()) { | 211 | if (cpu_is_mx25() || cpu_is_mx35()) { |
@@ -214,8 +242,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd | |||
214 | goto no_card_detect_irq; | 242 | goto no_card_detect_irq; |
215 | } | 243 | } |
216 | 244 | ||
217 | sdhci_esdhc_ops.write_l = esdhc_writel_le; | 245 | imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP; |
218 | sdhci_esdhc_ops.read_l = esdhc_readl_le; | ||
219 | /* Now we have a working card_detect again */ | 246 | /* Now we have a working card_detect again */ |
220 | host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; | 247 | host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; |
221 | } | 248 | } |
@@ -227,6 +254,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd | |||
227 | no_card_detect_pin: | 254 | no_card_detect_pin: |
228 | boarddata->cd_gpio = err; | 255 | boarddata->cd_gpio = err; |
229 | not_supported: | 256 | not_supported: |
257 | kfree(imx_data); | ||
230 | return 0; | 258 | return 0; |
231 | } | 259 | } |
232 | 260 | ||
@@ -234,6 +262,7 @@ static void esdhc_pltfm_exit(struct sdhci_host *host) | |||
234 | { | 262 | { |
235 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 263 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
236 | struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data; | 264 | struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data; |
265 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
237 | 266 | ||
238 | if (boarddata && gpio_is_valid(boarddata->wp_gpio)) | 267 | if (boarddata && gpio_is_valid(boarddata->wp_gpio)) |
239 | gpio_free(boarddata->wp_gpio); | 268 | gpio_free(boarddata->wp_gpio); |
@@ -247,6 +276,7 @@ static void esdhc_pltfm_exit(struct sdhci_host *host) | |||
247 | 276 | ||
248 | clk_disable(pltfm_host->clk); | 277 | clk_disable(pltfm_host->clk); |
249 | clk_put(pltfm_host->clk); | 278 | clk_put(pltfm_host->clk); |
279 | kfree(imx_data); | ||
250 | } | 280 | } |
251 | 281 | ||
252 | struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { | 282 | struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { |