10
10
#include <linux/module.h>
11
11
#include <linux/of.h>
12
12
#include <linux/bitops.h>
13
+ #include <linux/delay.h>
13
14
14
15
#include "sdhci-pltfm.h"
16
+ #include "cqhci.h"
15
17
16
18
#define SDHCI_VENDOR 0x78
17
19
#define SDHCI_VENDOR_ENHANCED_STRB 0x1
18
20
19
21
#define BRCMSTB_PRIV_FLAGS_NO_64BIT BIT(0)
20
22
#define BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT BIT(1)
21
23
24
+ #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
25
+
22
26
struct sdhci_brcmstb_priv {
23
27
void __iomem * cfg_regs ;
28
+ bool has_cqe ;
24
29
};
25
30
26
31
struct brcmstb_match_priv {
27
32
void (* hs400es )(struct mmc_host * mmc , struct mmc_ios * ios );
33
+ struct sdhci_ops * ops ;
28
34
unsigned int flags ;
29
35
};
30
36
@@ -44,28 +50,74 @@ static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
44
50
writel (reg , host -> ioaddr + SDHCI_VENDOR );
45
51
}
46
52
47
- static const struct sdhci_ops sdhci_brcmstb_ops = {
53
+ static void sdhci_brcmstb_set_clock (struct sdhci_host * host , unsigned int clock )
54
+ {
55
+ u16 clk ;
56
+
57
+ host -> mmc -> actual_clock = 0 ;
58
+
59
+ clk = sdhci_calc_clk (host , clock , & host -> mmc -> actual_clock );
60
+ sdhci_writew (host , clk , SDHCI_CLOCK_CONTROL );
61
+
62
+ if (clock == 0 )
63
+ return ;
64
+
65
+ sdhci_enable_clk (host , clk );
66
+ }
67
+
68
+ static void sdhci_brcmstb_dumpregs (struct mmc_host * mmc )
69
+ {
70
+ sdhci_dumpregs (mmc_priv (mmc ));
71
+ }
72
+
73
+ static void sdhci_brcmstb_cqe_enable (struct mmc_host * mmc )
74
+ {
75
+ struct sdhci_host * host = mmc_priv (mmc );
76
+ u32 reg ;
77
+
78
+ reg = sdhci_readl (host , SDHCI_PRESENT_STATE );
79
+ while (reg & SDHCI_DATA_AVAILABLE ) {
80
+ sdhci_readl (host , SDHCI_BUFFER );
81
+ reg = sdhci_readl (host , SDHCI_PRESENT_STATE );
82
+ }
83
+
84
+ sdhci_cqe_enable (mmc );
85
+ }
86
+
87
+ static const struct cqhci_host_ops sdhci_brcmstb_cqhci_ops = {
88
+ .enable = sdhci_brcmstb_cqe_enable ,
89
+ .disable = sdhci_cqe_disable ,
90
+ .dumpregs = sdhci_brcmstb_dumpregs ,
91
+ };
92
+
93
+ static struct sdhci_ops sdhci_brcmstb_ops = {
48
94
.set_clock = sdhci_set_clock ,
49
95
.set_bus_width = sdhci_set_bus_width ,
50
96
.reset = sdhci_reset ,
51
97
.set_uhs_signaling = sdhci_set_uhs_signaling ,
52
98
};
53
99
54
- static const struct sdhci_pltfm_data sdhci_brcmstb_pdata = {
55
- .ops = & sdhci_brcmstb_ops ,
100
+ static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
101
+ .set_clock = sdhci_brcmstb_set_clock ,
102
+ .set_bus_width = sdhci_set_bus_width ,
103
+ .reset = sdhci_reset ,
104
+ .set_uhs_signaling = sdhci_set_uhs_signaling ,
56
105
};
57
106
58
- static const struct brcmstb_match_priv match_priv_7425 = {
107
+ static struct brcmstb_match_priv match_priv_7425 = {
59
108
.flags = BRCMSTB_PRIV_FLAGS_NO_64BIT |
60
109
BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT ,
110
+ .ops = & sdhci_brcmstb_ops ,
61
111
};
62
112
63
- static const struct brcmstb_match_priv match_priv_7445 = {
113
+ static struct brcmstb_match_priv match_priv_7445 = {
64
114
.flags = BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT ,
115
+ .ops = & sdhci_brcmstb_ops ,
65
116
};
66
117
67
118
static const struct brcmstb_match_priv match_priv_7216 = {
68
119
.hs400es = sdhci_brcmstb_hs400es ,
120
+ .ops = & sdhci_brcmstb_ops_7216 ,
69
121
};
70
122
71
123
static const struct of_device_id sdhci_brcm_of_match [] = {
@@ -75,20 +127,85 @@ static const struct of_device_id sdhci_brcm_of_match[] = {
75
127
{},
76
128
};
77
129
130
+ static u32 sdhci_brcmstb_cqhci_irq (struct sdhci_host * host , u32 intmask )
131
+ {
132
+ int cmd_error = 0 ;
133
+ int data_error = 0 ;
134
+
135
+ if (!sdhci_cqe_irq (host , intmask , & cmd_error , & data_error ))
136
+ return intmask ;
137
+
138
+ cqhci_irq (host -> mmc , intmask , cmd_error , data_error );
139
+
140
+ return 0 ;
141
+ }
142
+
143
+ static int sdhci_brcmstb_add_host (struct sdhci_host * host ,
144
+ struct sdhci_brcmstb_priv * priv )
145
+ {
146
+ struct cqhci_host * cq_host ;
147
+ bool dma64 ;
148
+ int ret ;
149
+
150
+ if (!priv -> has_cqe )
151
+ return sdhci_add_host (host );
152
+
153
+ dev_dbg (mmc_dev (host -> mmc ), "CQE is enabled\n" );
154
+ host -> mmc -> caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD ;
155
+ ret = sdhci_setup_host (host );
156
+ if (ret )
157
+ return ret ;
158
+
159
+ cq_host = devm_kzalloc (mmc_dev (host -> mmc ),
160
+ sizeof (* cq_host ), GFP_KERNEL );
161
+ if (!cq_host ) {
162
+ ret = - ENOMEM ;
163
+ goto cleanup ;
164
+ }
165
+
166
+ cq_host -> mmio = host -> ioaddr + SDHCI_ARASAN_CQE_BASE_ADDR ;
167
+ cq_host -> ops = & sdhci_brcmstb_cqhci_ops ;
168
+
169
+ dma64 = host -> flags & SDHCI_USE_64_BIT_DMA ;
170
+ if (dma64 ) {
171
+ dev_dbg (mmc_dev (host -> mmc ), "Using 64 bit DMA\n" );
172
+ cq_host -> caps |= CQHCI_TASK_DESC_SZ_128 ;
173
+ cq_host -> quirks |= CQHCI_QUIRK_SHORT_TXFR_DESC_SZ ;
174
+ }
175
+
176
+ ret = cqhci_init (cq_host , host -> mmc , dma64 );
177
+ if (ret )
178
+ goto cleanup ;
179
+
180
+ ret = __sdhci_add_host (host );
181
+ if (ret )
182
+ goto cleanup ;
183
+
184
+ return 0 ;
185
+
186
+ cleanup :
187
+ sdhci_cleanup_host (host );
188
+ return ret ;
189
+ }
190
+
78
191
static int sdhci_brcmstb_probe (struct platform_device * pdev )
79
192
{
80
193
const struct brcmstb_match_priv * match_priv ;
194
+ struct sdhci_pltfm_data brcmstb_pdata ;
81
195
struct sdhci_pltfm_host * pltfm_host ;
82
196
const struct of_device_id * match ;
83
197
struct sdhci_brcmstb_priv * priv ;
84
198
struct sdhci_host * host ;
85
199
struct resource * iomem ;
200
+ bool has_cqe = false;
86
201
struct clk * clk ;
87
202
int res ;
88
203
89
204
match = of_match_node (sdhci_brcm_of_match , pdev -> dev .of_node );
90
205
match_priv = match -> data ;
91
206
207
+ dev_dbg (& pdev -> dev , "Probe found match for %s\n" , match -> compatible );
208
+
92
209
clk = devm_clk_get (& pdev -> dev , NULL );
93
210
if (IS_ERR (clk )) {
94
211
if (PTR_ERR (clk ) == - EPROBE_DEFER )
@@ -100,7 +217,13 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
100
217
if (res )
101
218
return res ;
102
219
103
- host = sdhci_pltfm_init (pdev , & sdhci_brcmstb_pdata ,
220
+ memset (& brcmstb_pdata , 0 , sizeof (brcmstb_pdata ));
221
+ if (device_property_read_bool (& pdev -> dev , "supports-cqe" )) {
222
+ has_cqe = true;
223
+ match_priv -> ops -> irq = sdhci_brcmstb_cqhci_irq ;
224
+ }
225
+ brcmstb_pdata .ops = match_priv -> ops ;
226
+ host = sdhci_pltfm_init (pdev , & brcmstb_pdata ,
104
227
sizeof (struct sdhci_brcmstb_priv ));
105
228
if (IS_ERR (host )) {
106
229
res = PTR_ERR (host );
@@ -109,6 +232,7 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
109
232
110
233
pltfm_host = sdhci_priv (host );
111
234
priv = sdhci_pltfm_priv (pltfm_host );
235
+ priv -> has_cqe = has_cqe ;
112
236
113
237
/* Map in the non-standard CFG registers */
114
238
iomem = platform_get_resource (pdev , IORESOURCE_MEM , 1 );
@@ -141,13 +265,13 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
141
265
host -> caps &= ~SDHCI_CAN_64BIT ;
142
266
host -> caps1 = sdhci_readl (host , SDHCI_CAPABILITIES_1 );
143
267
host -> caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
144
- SDHCI_SUPPORT_DDR50 );
268
+ SDHCI_SUPPORT_DDR50 );
145
269
host -> quirks |= SDHCI_QUIRK_MISSING_CAPS ;
146
270
147
271
if (match_priv -> flags & BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT )
148
272
host -> quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL ;
149
273
150
- res = sdhci_add_host (host );
274
+ res = sdhci_brcmstb_add_host (host , priv );
151
275
if (res )
152
276
goto err ;
153
277
0 commit comments