16
16
#include <linux/err.h>
17
17
#include <linux/clk.h>
18
18
#include <linux/gpio.h>
19
+ #include <linux/slab.h>
19
20
#include <linux/mmc/host.h>
20
21
#include <linux/mmc/sdhci-pltfm.h>
21
22
#include <mach/hardware.h>
24
25
#include "sdhci-pltfm.h"
25
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
35
static inline void esdhc_clrset_le (struct sdhci_host * host , u32 mask , u32 val , int reg )
28
36
{
29
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
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
48
/* fake CARD_PRESENT flag on mx25/35 */
38
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
53
struct esdhc_platform_data * boarddata =
42
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
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
76
* these interrupts won't work with a custom card_detect gpio
61
77
* (only applied to mx25/35)
@@ -76,17 +92,18 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
76
92
static void esdhc_writew_le (struct sdhci_host * host , u16 val , int reg )
77
93
{
78
94
struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
95
+ struct pltfm_imx_data * imx_data = pltfm_host -> priv ;
79
96
80
97
switch (reg ) {
81
98
case SDHCI_TRANSFER_MODE :
82
99
/*
83
100
* Postpone this write, we must do it together with a
84
101
* command write that is down below.
85
102
*/
86
- pltfm_host -> scratchpad = val ;
103
+ imx_data -> scratchpad = val ;
87
104
return ;
88
105
case SDHCI_COMMAND :
89
- writel (val << 16 | pltfm_host -> scratchpad ,
106
+ writel (val << 16 | imx_data -> scratchpad ,
90
107
host -> ioaddr + SDHCI_TRANSFER_MODE );
91
108
return ;
92
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
165
static struct sdhci_ops sdhci_esdhc_ops = {
166
+ .read_l = esdhc_readl_le ,
149
167
.read_w = esdhc_readw_le ,
168
+ .write_l = esdhc_writel_le ,
150
169
.write_w = esdhc_writew_le ,
151
170
.write_b = esdhc_writeb_le ,
152
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
187
struct esdhc_platform_data * boarddata = host -> mmc -> parent -> platform_data ;
169
188
struct clk * clk ;
170
189
int err ;
190
+ struct pltfm_imx_data * imx_data ;
171
191
172
192
clk = clk_get (mmc_dev (host -> mmc ), NULL );
173
193
if (IS_ERR (clk )) {
@@ -177,7 +197,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
177
197
clk_enable (clk );
178
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
209
host -> quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL ;
182
210
183
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
242
goto no_card_detect_irq ;
215
243
}
216
244
217
- sdhci_esdhc_ops .write_l = esdhc_writel_le ;
218
- sdhci_esdhc_ops .read_l = esdhc_readl_le ;
245
+ imx_data -> flags |= ESDHC_FLAG_GPIO_FOR_CD_WP ;
219
246
/* Now we have a working card_detect again */
220
247
host -> quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION ;
221
248
}
@@ -227,13 +254,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
227
254
no_card_detect_pin :
228
255
boarddata -> cd_gpio = err ;
229
256
not_supported :
257
+ kfree (imx_data );
230
258
return 0 ;
231
259
}
232
260
233
261
static void esdhc_pltfm_exit (struct sdhci_host * host )
234
262
{
235
263
struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
236
264
struct esdhc_platform_data * boarddata = host -> mmc -> parent -> platform_data ;
265
+ struct pltfm_imx_data * imx_data = pltfm_host -> priv ;
237
266
238
267
if (boarddata && gpio_is_valid (boarddata -> wp_gpio ))
239
268
gpio_free (boarddata -> wp_gpio );
@@ -247,6 +276,7 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
247
276
248
277
clk_disable (pltfm_host -> clk );
249
278
clk_put (pltfm_host -> clk );
279
+ kfree (imx_data );
250
280
}
251
281
252
282
struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
0 commit comments