6
6
*/
7
7
8
8
#include <linux/io.h>
9
+ #include <linux/iopoll.h>
9
10
#include <linux/mmc/host.h>
10
11
#include <linux/module.h>
11
12
#include <linux/of.h>
@@ -44,23 +45,67 @@ struct brcmstb_match_priv {
44
45
45
46
static inline void enable_clock_gating (struct sdhci_host * host )
46
47
{
48
+ struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
49
+ struct sdhci_brcmstb_priv * priv = sdhci_pltfm_priv (pltfm_host );
47
50
u32 reg ;
48
51
52
+ if (!(priv -> flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK ))
53
+ return ;
54
+
49
55
reg = sdhci_readl (host , SDHCI_VENDOR );
50
56
reg |= SDHCI_VENDOR_GATE_SDCLK_EN ;
51
57
sdhci_writel (host , reg , SDHCI_VENDOR );
52
58
}
53
59
54
60
static void brcmstb_reset (struct sdhci_host * host , u8 mask )
55
61
{
56
- struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
57
- struct sdhci_brcmstb_priv * priv = sdhci_pltfm_priv (pltfm_host );
58
-
59
62
sdhci_and_cqhci_reset (host , mask );
60
63
61
64
/* Reset will clear this, so re-enable it */
62
- if (priv -> flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK )
63
- enable_clock_gating (host );
65
+ enable_clock_gating (host );
66
+ }
67
+
68
+ static void brcmstb_sdhci_reset_cmd_data (struct sdhci_host * host , u8 mask )
69
+ {
70
+ u32 new_mask = (mask & (SDHCI_RESET_CMD | SDHCI_RESET_DATA )) << 24 ;
71
+ int ret ;
72
+ u32 reg ;
73
+
74
+ /*
75
+ * SDHCI_CLOCK_CONTROL register CARD_EN and CLOCK_INT_EN bits shall
76
+ * be set along with SOFTWARE_RESET register RESET_CMD or RESET_DATA
77
+ * bits, hence access SDHCI_CLOCK_CONTROL register as 32-bit register
78
+ */
79
+ new_mask |= SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN ;
80
+ reg = sdhci_readl (host , SDHCI_CLOCK_CONTROL );
81
+ sdhci_writel (host , reg | new_mask , SDHCI_CLOCK_CONTROL );
82
+
83
+ reg = sdhci_readb (host , SDHCI_SOFTWARE_RESET );
84
+
85
+ ret = read_poll_timeout_atomic (sdhci_readb , reg , !(reg & mask ),
86
+ 10 , 10000 , false,
87
+ host , SDHCI_SOFTWARE_RESET );
88
+
89
+ if (ret ) {
90
+ pr_err ("%s: Reset 0x%x never completed.\n" ,
91
+ mmc_hostname (host -> mmc ), (int )mask );
92
+ sdhci_err_stats_inc (host , CTRL_TIMEOUT );
93
+ sdhci_dumpregs (host );
94
+ }
95
+ }
96
+
97
+ static void brcmstb_reset_74165b0 (struct sdhci_host * host , u8 mask )
98
+ {
99
+ /* take care of RESET_ALL as usual */
100
+ if (mask & SDHCI_RESET_ALL )
101
+ sdhci_and_cqhci_reset (host , SDHCI_RESET_ALL );
102
+
103
+ /* cmd and/or data treated differently on this core */
104
+ if (mask & (SDHCI_RESET_CMD | SDHCI_RESET_DATA ))
105
+ brcmstb_sdhci_reset_cmd_data (host , mask );
106
+
107
+ /* Reset will clear this, so re-enable it */
108
+ enable_clock_gating (host );
64
109
}
65
110
66
111
static void sdhci_brcmstb_hs400es (struct mmc_host * mmc , struct mmc_ios * ios )
@@ -162,6 +207,13 @@ static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
162
207
.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling ,
163
208
};
164
209
210
+ static struct sdhci_ops sdhci_brcmstb_ops_74165b0 = {
211
+ .set_clock = sdhci_brcmstb_set_clock ,
212
+ .set_bus_width = sdhci_set_bus_width ,
213
+ .reset = brcmstb_reset_74165b0 ,
214
+ .set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling ,
215
+ };
216
+
165
217
static struct brcmstb_match_priv match_priv_7425 = {
166
218
.flags = BRCMSTB_MATCH_FLAGS_NO_64BIT |
167
219
BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT ,
@@ -179,10 +231,17 @@ static const struct brcmstb_match_priv match_priv_7216 = {
179
231
.ops = & sdhci_brcmstb_ops_7216 ,
180
232
};
181
233
234
+ static struct brcmstb_match_priv match_priv_74165b0 = {
235
+ .flags = BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE ,
236
+ .hs400es = sdhci_brcmstb_hs400es ,
237
+ .ops = & sdhci_brcmstb_ops_74165b0 ,
238
+ };
239
+
182
240
static const struct of_device_id __maybe_unused sdhci_brcm_of_match [] = {
183
241
{ .compatible = "brcm,bcm7425-sdhci" , .data = & match_priv_7425 },
184
242
{ .compatible = "brcm,bcm7445-sdhci" , .data = & match_priv_7445 },
185
243
{ .compatible = "brcm,bcm7216-sdhci" , .data = & match_priv_7216 },
244
+ { .compatible = "brcm,bcm74165b0-sdhci" , .data = & match_priv_74165b0 },
186
245
{},
187
246
};
188
247
0 commit comments