1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2019 Genesys Logic, Inc.
5 * Authors: Ben Chuang <ben.chuang@genesyslogic.com.tw>
7 * Version: v0.9.0 (2019-08-08)
10 #include <linux/bitfield.h>
11 #include <linux/bits.h>
12 #include <linux/pci.h>
13 #include <linux/mmc/mmc.h>
14 #include <linux/delay.h>
16 #include "sdhci-pci.h"
18 /* Genesys Logic extra registers */
19 #define SDHCI_GLI_9750_WT 0x800
20 #define SDHCI_GLI_9750_WT_EN BIT(0)
21 #define GLI_9750_WT_EN_ON 0x1
22 #define GLI_9750_WT_EN_OFF 0x0
24 #define SDHCI_GLI_9750_DRIVING 0x860
25 #define SDHCI_GLI_9750_DRIVING_1 GENMASK(11, 0)
26 #define SDHCI_GLI_9750_DRIVING_2 GENMASK(27, 26)
27 #define GLI_9750_DRIVING_1_VALUE 0xFFF
28 #define GLI_9750_DRIVING_2_VALUE 0x3
30 #define SDHCI_GLI_9750_PLL 0x864
31 #define SDHCI_GLI_9750_PLL_TX2_INV BIT(23)
32 #define SDHCI_GLI_9750_PLL_TX2_DLY GENMASK(22, 20)
33 #define GLI_9750_PLL_TX2_INV_VALUE 0x1
34 #define GLI_9750_PLL_TX2_DLY_VALUE 0x0
36 #define SDHCI_GLI_9750_SW_CTRL 0x874
37 #define SDHCI_GLI_9750_SW_CTRL_4 GENMASK(7, 6)
38 #define GLI_9750_SW_CTRL_4_VALUE 0x3
40 #define SDHCI_GLI_9750_MISC 0x878
41 #define SDHCI_GLI_9750_MISC_TX1_INV BIT(2)
42 #define SDHCI_GLI_9750_MISC_RX_INV BIT(3)
43 #define SDHCI_GLI_9750_MISC_TX1_DLY GENMASK(6, 4)
44 #define GLI_9750_MISC_TX1_INV_VALUE 0x0
45 #define GLI_9750_MISC_RX_INV_ON 0x1
46 #define GLI_9750_MISC_RX_INV_OFF 0x0
47 #define GLI_9750_MISC_RX_INV_VALUE GLI_9750_MISC_RX_INV_OFF
48 #define GLI_9750_MISC_TX1_DLY_VALUE 0x5
50 #define SDHCI_GLI_9750_TUNING_CONTROL 0x540
51 #define SDHCI_GLI_9750_TUNING_CONTROL_EN BIT(4)
52 #define GLI_9750_TUNING_CONTROL_EN_ON 0x1
53 #define GLI_9750_TUNING_CONTROL_EN_OFF 0x0
54 #define SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1 BIT(16)
55 #define SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2 GENMASK(20, 19)
56 #define GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE 0x1
57 #define GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE 0x2
59 #define SDHCI_GLI_9750_TUNING_PARAMETERS 0x544
60 #define SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY GENMASK(2, 0)
61 #define GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE 0x1
63 #define GLI_MAX_TUNING_LOOP 40
65 /* Genesys Logic chipset */
66 static inline void gl9750_wt_on(struct sdhci_host
*host
)
71 wt_value
= sdhci_readl(host
, SDHCI_GLI_9750_WT
);
72 wt_enable
= FIELD_GET(SDHCI_GLI_9750_WT_EN
, wt_value
);
74 if (wt_enable
== GLI_9750_WT_EN_ON
)
77 wt_value
&= ~SDHCI_GLI_9750_WT_EN
;
78 wt_value
|= FIELD_PREP(SDHCI_GLI_9750_WT_EN
, GLI_9750_WT_EN_ON
);
80 sdhci_writel(host
, wt_value
, SDHCI_GLI_9750_WT
);
83 static inline void gl9750_wt_off(struct sdhci_host
*host
)
88 wt_value
= sdhci_readl(host
, SDHCI_GLI_9750_WT
);
89 wt_enable
= FIELD_GET(SDHCI_GLI_9750_WT_EN
, wt_value
);
91 if (wt_enable
== GLI_9750_WT_EN_OFF
)
94 wt_value
&= ~SDHCI_GLI_9750_WT_EN
;
95 wt_value
|= FIELD_PREP(SDHCI_GLI_9750_WT_EN
, GLI_9750_WT_EN_OFF
);
97 sdhci_writel(host
, wt_value
, SDHCI_GLI_9750_WT
);
100 static void gli_set_9750(struct sdhci_host
*host
)
112 driving_value
= sdhci_readl(host
, SDHCI_GLI_9750_DRIVING
);
113 pll_value
= sdhci_readl(host
, SDHCI_GLI_9750_PLL
);
114 sw_ctrl_value
= sdhci_readl(host
, SDHCI_GLI_9750_SW_CTRL
);
115 misc_value
= sdhci_readl(host
, SDHCI_GLI_9750_MISC
);
116 parameter_value
= sdhci_readl(host
, SDHCI_GLI_9750_TUNING_PARAMETERS
);
117 control_value
= sdhci_readl(host
, SDHCI_GLI_9750_TUNING_CONTROL
);
119 driving_value
&= ~(SDHCI_GLI_9750_DRIVING_1
);
120 driving_value
&= ~(SDHCI_GLI_9750_DRIVING_2
);
121 driving_value
|= FIELD_PREP(SDHCI_GLI_9750_DRIVING_1
,
122 GLI_9750_DRIVING_1_VALUE
);
123 driving_value
|= FIELD_PREP(SDHCI_GLI_9750_DRIVING_2
,
124 GLI_9750_DRIVING_2_VALUE
);
125 sdhci_writel(host
, driving_value
, SDHCI_GLI_9750_DRIVING
);
127 sw_ctrl_value
&= ~SDHCI_GLI_9750_SW_CTRL_4
;
128 sw_ctrl_value
|= FIELD_PREP(SDHCI_GLI_9750_SW_CTRL_4
,
129 GLI_9750_SW_CTRL_4_VALUE
);
130 sdhci_writel(host
, sw_ctrl_value
, SDHCI_GLI_9750_SW_CTRL
);
132 /* reset the tuning flow after reinit and before starting tuning */
133 pll_value
&= ~SDHCI_GLI_9750_PLL_TX2_INV
;
134 pll_value
&= ~SDHCI_GLI_9750_PLL_TX2_DLY
;
135 pll_value
|= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_INV
,
136 GLI_9750_PLL_TX2_INV_VALUE
);
137 pll_value
|= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_DLY
,
138 GLI_9750_PLL_TX2_DLY_VALUE
);
140 misc_value
&= ~SDHCI_GLI_9750_MISC_TX1_INV
;
141 misc_value
&= ~SDHCI_GLI_9750_MISC_RX_INV
;
142 misc_value
&= ~SDHCI_GLI_9750_MISC_TX1_DLY
;
143 misc_value
|= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_INV
,
144 GLI_9750_MISC_TX1_INV_VALUE
);
145 misc_value
|= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV
,
146 GLI_9750_MISC_RX_INV_VALUE
);
147 misc_value
|= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_DLY
,
148 GLI_9750_MISC_TX1_DLY_VALUE
);
150 parameter_value
&= ~SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY
;
151 parameter_value
|= FIELD_PREP(SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY
,
152 GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE
);
154 control_value
&= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1
;
155 control_value
&= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2
;
156 control_value
|= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1
,
157 GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE
);
158 control_value
|= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2
,
159 GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE
);
161 sdhci_writel(host
, pll_value
, SDHCI_GLI_9750_PLL
);
162 sdhci_writel(host
, misc_value
, SDHCI_GLI_9750_MISC
);
164 /* disable tuned clk */
165 ctrl2
= sdhci_readw(host
, SDHCI_HOST_CONTROL2
);
166 ctrl2
&= ~SDHCI_CTRL_TUNED_CLK
;
167 sdhci_writew(host
, ctrl2
, SDHCI_HOST_CONTROL2
);
169 /* enable tuning parameters control */
170 control_value
&= ~SDHCI_GLI_9750_TUNING_CONTROL_EN
;
171 control_value
|= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN
,
172 GLI_9750_TUNING_CONTROL_EN_ON
);
173 sdhci_writel(host
, control_value
, SDHCI_GLI_9750_TUNING_CONTROL
);
175 /* write tuning parameters */
176 sdhci_writel(host
, parameter_value
, SDHCI_GLI_9750_TUNING_PARAMETERS
);
178 /* disable tuning parameters control */
179 control_value
&= ~SDHCI_GLI_9750_TUNING_CONTROL_EN
;
180 control_value
|= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN
,
181 GLI_9750_TUNING_CONTROL_EN_OFF
);
182 sdhci_writel(host
, control_value
, SDHCI_GLI_9750_TUNING_CONTROL
);
184 /* clear tuned clk */
185 ctrl2
= sdhci_readw(host
, SDHCI_HOST_CONTROL2
);
186 ctrl2
&= ~SDHCI_CTRL_TUNED_CLK
;
187 sdhci_writew(host
, ctrl2
, SDHCI_HOST_CONTROL2
);
192 static void gli_set_9750_rx_inv(struct sdhci_host
*host
, bool b
)
198 misc_value
= sdhci_readl(host
, SDHCI_GLI_9750_MISC
);
199 misc_value
&= ~SDHCI_GLI_9750_MISC_RX_INV
;
201 misc_value
|= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV
,
202 GLI_9750_MISC_RX_INV_ON
);
204 misc_value
|= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV
,
205 GLI_9750_MISC_RX_INV_OFF
);
207 sdhci_writel(host
, misc_value
, SDHCI_GLI_9750_MISC
);
212 static int __sdhci_execute_tuning_9750(struct sdhci_host
*host
, u32 opcode
)
217 for (rx_inv
= 0; rx_inv
< 2; rx_inv
++) {
218 gli_set_9750_rx_inv(host
, !!rx_inv
);
219 sdhci_start_tuning(host
);
221 for (i
= 0; i
< GLI_MAX_TUNING_LOOP
; i
++) {
224 sdhci_send_tuning(host
, opcode
);
226 if (!host
->tuning_done
) {
227 sdhci_abort_tuning(host
, opcode
);
231 ctrl
= sdhci_readw(host
, SDHCI_HOST_CONTROL2
);
232 if (!(ctrl
& SDHCI_CTRL_EXEC_TUNING
)) {
233 if (ctrl
& SDHCI_CTRL_TUNED_CLK
)
234 return 0; /* Success! */
239 if (!host
->tuning_done
) {
240 pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
241 mmc_hostname(host
->mmc
));
245 pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
246 mmc_hostname(host
->mmc
));
247 sdhci_reset_tuning(host
);
252 static int gl9750_execute_tuning(struct sdhci_host
*host
, u32 opcode
)
254 host
->mmc
->retune_period
= 0;
255 if (host
->tuning_mode
== SDHCI_TUNING_MODE_1
)
256 host
->mmc
->retune_period
= host
->tuning_count
;
259 host
->tuning_err
= __sdhci_execute_tuning_9750(host
, opcode
);
260 sdhci_end_tuning(host
);
265 static int gli_probe_slot_gl9750(struct sdhci_pci_slot
*slot
)
267 struct sdhci_host
*host
= slot
->host
;
269 slot
->host
->mmc
->caps2
|= MMC_CAP2_NO_SDIO
;
270 sdhci_enable_v4_mode(host
);
275 static int gli_probe_slot_gl9755(struct sdhci_pci_slot
*slot
)
277 struct sdhci_host
*host
= slot
->host
;
279 slot
->host
->mmc
->caps2
|= MMC_CAP2_NO_SDIO
;
280 sdhci_enable_v4_mode(host
);
285 static void sdhci_gli_voltage_switch(struct sdhci_host
*host
)
288 * According to Section 3.6.1 signal voltage switch procedure in
289 * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as
291 * (6) Set 1.8V Signal Enable in the Host Control 2 register.
292 * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this
294 * (8) If 1.8V Signal Enable is cleared by Host Controller, go to
297 * Wait 5ms after set 1.8V signal enable in Host Control 2 register
298 * to ensure 1.8V signal enable bit is set by GL9750/GL9755.
300 usleep_range(5000, 5500);
303 static void sdhci_gl9750_reset(struct sdhci_host
*host
, u8 mask
)
305 sdhci_reset(host
, mask
);
309 static u32
sdhci_gl9750_readl(struct sdhci_host
*host
, int reg
)
313 value
= readl(host
->ioaddr
+ reg
);
314 if (unlikely(reg
== SDHCI_MAX_CURRENT
&& !(value
& 0xff)))
320 static const struct sdhci_ops sdhci_gl9755_ops
= {
321 .set_clock
= sdhci_set_clock
,
322 .enable_dma
= sdhci_pci_enable_dma
,
323 .set_bus_width
= sdhci_set_bus_width
,
324 .reset
= sdhci_reset
,
325 .set_uhs_signaling
= sdhci_set_uhs_signaling
,
326 .voltage_switch
= sdhci_gli_voltage_switch
,
329 const struct sdhci_pci_fixes sdhci_gl9755
= {
330 .quirks
= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
,
331 .quirks2
= SDHCI_QUIRK2_BROKEN_DDR50
,
332 .probe_slot
= gli_probe_slot_gl9755
,
333 .ops
= &sdhci_gl9755_ops
,
336 static const struct sdhci_ops sdhci_gl9750_ops
= {
337 .read_l
= sdhci_gl9750_readl
,
338 .set_clock
= sdhci_set_clock
,
339 .enable_dma
= sdhci_pci_enable_dma
,
340 .set_bus_width
= sdhci_set_bus_width
,
341 .reset
= sdhci_gl9750_reset
,
342 .set_uhs_signaling
= sdhci_set_uhs_signaling
,
343 .voltage_switch
= sdhci_gli_voltage_switch
,
344 .platform_execute_tuning
= gl9750_execute_tuning
,
347 const struct sdhci_pci_fixes sdhci_gl9750
= {
348 .quirks
= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
,
349 .quirks2
= SDHCI_QUIRK2_BROKEN_DDR50
,
350 .probe_slot
= gli_probe_slot_gl9750
,
351 .ops
= &sdhci_gl9750_ops
,