9
9
#include <linux/mmc/host.h>
10
10
#include <linux/module.h>
11
11
#include <linux/of.h>
12
+ #include <linux/bitops.h>
12
13
13
14
#include "sdhci-pltfm.h"
14
15
16
+ #define SDHCI_VENDOR 0x78
17
+ #define SDHCI_VENDOR_ENHANCED_STRB 0x1
18
+
19
+ #define BRCMSTB_PRIV_FLAGS_NO_64BIT BIT(0)
20
+ #define BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT BIT(1)
21
+
22
+ struct sdhci_brcmstb_priv {
23
+ void __iomem * cfg_regs ;
24
+ };
25
+
26
+ struct brcmstb_match_priv {
27
+ void (* hs400es )(struct mmc_host * mmc , struct mmc_ios * ios );
28
+ unsigned int flags ;
29
+ };
30
+
31
+ static void sdhci_brcmstb_hs400es (struct mmc_host * mmc , struct mmc_ios * ios )
32
+ {
33
+ struct sdhci_host * host = mmc_priv (mmc );
34
+
35
+ u32 reg ;
36
+
37
+ dev_dbg (mmc_dev (mmc ), "%s(): Setting HS400-Enhanced-Strobe mode\n" ,
38
+ __func__ );
39
+ reg = readl (host -> ioaddr + SDHCI_VENDOR );
40
+ if (ios -> enhanced_strobe )
41
+ reg |= SDHCI_VENDOR_ENHANCED_STRB ;
42
+ else
43
+ reg &= ~SDHCI_VENDOR_ENHANCED_STRB ;
44
+ writel (reg , host -> ioaddr + SDHCI_VENDOR );
45
+ }
46
+
15
47
static const struct sdhci_ops sdhci_brcmstb_ops = {
16
48
.set_clock = sdhci_set_clock ,
17
49
.set_bus_width = sdhci_set_bus_width ,
@@ -23,13 +55,40 @@ static const struct sdhci_pltfm_data sdhci_brcmstb_pdata = {
23
55
.ops = & sdhci_brcmstb_ops ,
24
56
};
25
57
58
+ static const struct brcmstb_match_priv match_priv_7425 = {
59
+ .flags = BRCMSTB_PRIV_FLAGS_NO_64BIT |
60
+ BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT ,
61
+ };
62
+
63
+ static const struct brcmstb_match_priv match_priv_7445 = {
64
+ .flags = BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT ,
65
+ };
66
+
67
+ static const struct brcmstb_match_priv match_priv_7216 = {
68
+ .hs400es = sdhci_brcmstb_hs400es ,
69
+ };
70
+
71
+ static const struct of_device_id sdhci_brcm_of_match [] = {
72
+ { .compatible = "brcm,bcm7425-sdhci" , .data = & match_priv_7425 },
73
+ { .compatible = "brcm,bcm7445-sdhci" , .data = & match_priv_7445 },
74
+ { .compatible = "brcm,bcm7216-sdhci" , .data = & match_priv_7216 },
75
+ {},
76
+ };
77
+
26
78
static int sdhci_brcmstb_probe (struct platform_device * pdev )
27
79
{
28
- struct sdhci_host * host ;
80
+ const struct brcmstb_match_priv * match_priv ;
29
81
struct sdhci_pltfm_host * pltfm_host ;
82
+ const struct of_device_id * match ;
83
+ struct sdhci_brcmstb_priv * priv ;
84
+ struct sdhci_host * host ;
85
+ struct resource * iomem ;
30
86
struct clk * clk ;
31
87
int res ;
32
88
89
+ match = of_match_node (sdhci_brcm_of_match , pdev -> dev .of_node );
90
+ match_priv = match -> data ;
91
+
33
92
clk = devm_clk_get (& pdev -> dev , NULL );
34
93
if (IS_ERR (clk )) {
35
94
dev_err (& pdev -> dev , "Clock not found in Device Tree\n" );
@@ -39,36 +98,57 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
39
98
if (res )
40
99
return res ;
41
100
42
- host = sdhci_pltfm_init (pdev , & sdhci_brcmstb_pdata , 0 );
101
+ host = sdhci_pltfm_init (pdev , & sdhci_brcmstb_pdata ,
102
+ sizeof (struct sdhci_brcmstb_priv ));
43
103
if (IS_ERR (host )) {
44
104
res = PTR_ERR (host );
45
105
goto err_clk ;
46
106
}
47
107
108
+ pltfm_host = sdhci_priv (host );
109
+ priv = sdhci_pltfm_priv (pltfm_host );
110
+
111
+ /* Map in the non-standard CFG registers */
112
+ iomem = platform_get_resource (pdev , IORESOURCE_MEM , 1 );
113
+ priv -> cfg_regs = devm_ioremap_resource (& pdev -> dev , iomem );
114
+ if (IS_ERR (priv -> cfg_regs )) {
115
+ res = PTR_ERR (priv -> cfg_regs );
116
+ goto err ;
117
+ }
118
+
48
119
sdhci_get_of_property (pdev );
49
120
res = mmc_of_parse (host -> mmc );
50
121
if (res )
51
122
goto err ;
52
123
124
+ /*
125
+ * If the chip has enhanced strobe and it's enabled, add
126
+ * callback
127
+ */
128
+ if (match_priv -> hs400es &&
129
+ (host -> mmc -> caps2 & MMC_CAP2_HS400_ES ))
130
+ host -> mmc_host_ops .hs400_enhanced_strobe = match_priv -> hs400es ;
131
+
53
132
/*
54
133
* Supply the existing CAPS, but clear the UHS modes. This
55
134
* will allow these modes to be specified by device tree
56
135
* properties through mmc_of_parse().
57
136
*/
58
137
host -> caps = sdhci_readl (host , SDHCI_CAPABILITIES );
59
- if (of_device_is_compatible ( pdev -> dev . of_node , "brcm,bcm7425-sdhci" ) )
138
+ if (match_priv -> flags & BRCMSTB_PRIV_FLAGS_NO_64BIT )
60
139
host -> caps &= ~SDHCI_CAN_64BIT ;
61
140
host -> caps1 = sdhci_readl (host , SDHCI_CAPABILITIES_1 );
62
141
host -> caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
63
142
SDHCI_SUPPORT_DDR50 );
64
- host -> quirks |= SDHCI_QUIRK_MISSING_CAPS |
65
- SDHCI_QUIRK_BROKEN_TIMEOUT_VAL ;
143
+ host -> quirks |= SDHCI_QUIRK_MISSING_CAPS ;
144
+
145
+ if (match_priv -> flags & BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT )
146
+ host -> quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL ;
66
147
67
148
res = sdhci_add_host (host );
68
149
if (res )
69
150
goto err ;
70
151
71
- pltfm_host = sdhci_priv (host );
72
152
pltfm_host -> clk = clk ;
73
153
return res ;
74
154
@@ -79,11 +159,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
79
159
return res ;
80
160
}
81
161
82
- static const struct of_device_id sdhci_brcm_of_match [] = {
83
- { .compatible = "brcm,bcm7425-sdhci" },
84
- { .compatible = "brcm,bcm7445-sdhci" },
85
- {},
86
- };
87
162
MODULE_DEVICE_TABLE (of , sdhci_brcm_of_match );
88
163
89
164
static struct platform_driver sdhci_brcmstb_driver = {
0 commit comments