]>
Commit | Line | Data |
---|---|---|
a6e7e407 | 1 | // SPDX-License-Identifier: GPL-2.0 |
95f25efe WS |
2 | /* |
3 | * Freescale eSDHC i.MX controller driver for the platform bus. | |
4 | * | |
5 | * derived from the OF-version. | |
6 | * | |
7 | * Copyright (c) 2010 Pengutronix e.K. | |
035ff831 | 8 | * Author: Wolfram Sang <kernel@pengutronix.de> |
95f25efe WS |
9 | */ |
10 | ||
a8e809ec | 11 | #include <linux/bitfield.h> |
95f25efe | 12 | #include <linux/io.h> |
f581e909 | 13 | #include <linux/iopoll.h> |
95f25efe WS |
14 | #include <linux/delay.h> |
15 | #include <linux/err.h> | |
16 | #include <linux/clk.h> | |
66506f76 | 17 | #include <linux/module.h> |
e149860d | 18 | #include <linux/slab.h> |
1c4989b0 | 19 | #include <linux/pm_qos.h> |
95f25efe | 20 | #include <linux/mmc/host.h> |
58ac8177 RZ |
21 | #include <linux/mmc/mmc.h> |
22 | #include <linux/mmc/sdio.h> | |
fbe5fdd1 | 23 | #include <linux/mmc/slot-gpio.h> |
abfafc2d SG |
24 | #include <linux/of.h> |
25 | #include <linux/of_device.h> | |
e62d8b8f | 26 | #include <linux/pinctrl/consumer.h> |
82906b13 | 27 | #include <linux/platform_data/mmc-esdhc-imx.h> |
89d7e5c1 | 28 | #include <linux/pm_runtime.h> |
95f25efe WS |
29 | #include "sdhci-pltfm.h" |
30 | #include "sdhci-esdhc.h" | |
bb6e3581 | 31 | #include "cqhci.h" |
95f25efe | 32 | |
a215186d | 33 | #define ESDHC_SYS_CTRL_DTOCV_MASK 0x0f |
60bf6396 | 34 | #define ESDHC_CTRL_D3CD 0x08 |
fd44954e | 35 | #define ESDHC_BURST_LEN_EN_INCR (1 << 27) |
58ac8177 | 36 | /* VENDOR SPEC register */ |
60bf6396 SG |
37 | #define ESDHC_VENDOR_SPEC 0xc0 |
38 | #define ESDHC_VENDOR_SPEC_SDIO_QUIRK (1 << 1) | |
0322191e | 39 | #define ESDHC_VENDOR_SPEC_VSELECT (1 << 1) |
fed2f6e2 | 40 | #define ESDHC_VENDOR_SPEC_FRC_SDCLK_ON (1 << 8) |
3722c74c HC |
41 | #define ESDHC_DEBUG_SEL_AND_STATUS_REG 0xc2 |
42 | #define ESDHC_DEBUG_SEL_REG 0xc3 | |
43 | #define ESDHC_DEBUG_SEL_MASK 0xf | |
44 | #define ESDHC_DEBUG_SEL_CMD_STATE 1 | |
45 | #define ESDHC_DEBUG_SEL_DATA_STATE 2 | |
46 | #define ESDHC_DEBUG_SEL_TRANS_STATE 3 | |
47 | #define ESDHC_DEBUG_SEL_DMA_STATE 4 | |
48 | #define ESDHC_DEBUG_SEL_ADMA_STATE 5 | |
49 | #define ESDHC_DEBUG_SEL_FIFO_STATE 6 | |
50 | #define ESDHC_DEBUG_SEL_ASYNC_FIFO_STATE 7 | |
60bf6396 | 51 | #define ESDHC_WTMK_LVL 0x44 |
cc17e129 | 52 | #define ESDHC_WTMK_DEFAULT_VAL 0x10401040 |
3fbd4322 AG |
53 | #define ESDHC_WTMK_LVL_RD_WML_MASK 0x000000FF |
54 | #define ESDHC_WTMK_LVL_RD_WML_SHIFT 0 | |
55 | #define ESDHC_WTMK_LVL_WR_WML_MASK 0x00FF0000 | |
56 | #define ESDHC_WTMK_LVL_WR_WML_SHIFT 16 | |
57 | #define ESDHC_WTMK_LVL_WML_VAL_DEF 64 | |
58 | #define ESDHC_WTMK_LVL_WML_VAL_MAX 128 | |
60bf6396 | 59 | #define ESDHC_MIX_CTRL 0x48 |
de5bdbff | 60 | #define ESDHC_MIX_CTRL_DDREN (1 << 3) |
2a15f981 | 61 | #define ESDHC_MIX_CTRL_AC23EN (1 << 7) |
0322191e DA |
62 | #define ESDHC_MIX_CTRL_EXE_TUNE (1 << 22) |
63 | #define ESDHC_MIX_CTRL_SMPCLK_SEL (1 << 23) | |
0b330e38 | 64 | #define ESDHC_MIX_CTRL_AUTO_TUNE_EN (1 << 24) |
0322191e | 65 | #define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25) |
28b07674 | 66 | #define ESDHC_MIX_CTRL_HS400_EN (1 << 26) |
029e2476 | 67 | #define ESDHC_MIX_CTRL_HS400_ES_EN (1 << 27) |
2a15f981 SG |
68 | /* Bits 3 and 6 are not SDHCI standard definitions */ |
69 | #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 | |
d131a71c DA |
70 | /* Tuning bits */ |
71 | #define ESDHC_MIX_CTRL_TUNING_MASK 0x03c00000 | |
58ac8177 | 72 | |
602519b2 DA |
73 | /* dll control register */ |
74 | #define ESDHC_DLL_CTRL 0x60 | |
75 | #define ESDHC_DLL_OVERRIDE_VAL_SHIFT 9 | |
76 | #define ESDHC_DLL_OVERRIDE_EN_SHIFT 8 | |
77 | ||
0322191e DA |
78 | /* tune control register */ |
79 | #define ESDHC_TUNE_CTRL_STATUS 0x68 | |
80 | #define ESDHC_TUNE_CTRL_STEP 1 | |
81 | #define ESDHC_TUNE_CTRL_MIN 0 | |
82 | #define ESDHC_TUNE_CTRL_MAX ((1 << 7) - 1) | |
83 | ||
28b07674 HC |
84 | /* strobe dll register */ |
85 | #define ESDHC_STROBE_DLL_CTRL 0x70 | |
86 | #define ESDHC_STROBE_DLL_CTRL_ENABLE (1 << 0) | |
87 | #define ESDHC_STROBE_DLL_CTRL_RESET (1 << 1) | |
5bd2acdc | 88 | #define ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT 0x7 |
28b07674 | 89 | #define ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT 3 |
2eaf5a53 | 90 | #define ESDHC_STROBE_DLL_CTRL_SLV_UPDATE_INT_DEFAULT (4 << 20) |
28b07674 HC |
91 | |
92 | #define ESDHC_STROBE_DLL_STATUS 0x74 | |
93 | #define ESDHC_STROBE_DLL_STS_REF_LOCK (1 << 1) | |
94 | #define ESDHC_STROBE_DLL_STS_SLV_LOCK 0x1 | |
95 | ||
bcdb5301 BC |
96 | #define ESDHC_VEND_SPEC2 0xc8 |
97 | #define ESDHC_VEND_SPEC2_EN_BUSY_IRQ (1 << 8) | |
98 | ||
6e9fd28e DA |
99 | #define ESDHC_TUNING_CTRL 0xcc |
100 | #define ESDHC_STD_TUNING_EN (1 << 24) | |
101 | /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */ | |
d87fc966 | 102 | #define ESDHC_TUNING_START_TAP_DEFAULT 0x1 |
1194be8c | 103 | #define ESDHC_TUNING_START_TAP_MASK 0x7f |
16e40e5b | 104 | #define ESDHC_TUNING_CMD_CRC_CHECK_DISABLE (1 << 7) |
260ecb3c | 105 | #define ESDHC_TUNING_STEP_MASK 0x00070000 |
d407e30b | 106 | #define ESDHC_TUNING_STEP_SHIFT 16 |
6e9fd28e | 107 | |
ad93220d DA |
108 | /* pinctrl state */ |
109 | #define ESDHC_PINCTRL_STATE_100MHZ "state_100mhz" | |
110 | #define ESDHC_PINCTRL_STATE_200MHZ "state_200mhz" | |
111 | ||
af51079e SH |
112 | /* |
113 | * Our interpretation of the SDHCI_HOST_CONTROL register | |
114 | */ | |
115 | #define ESDHC_CTRL_4BITBUS (0x1 << 1) | |
116 | #define ESDHC_CTRL_8BITBUS (0x2 << 1) | |
117 | #define ESDHC_CTRL_BUSWIDTH_MASK (0x3 << 1) | |
118 | ||
97e4ba6a | 119 | /* |
d04f8d5b | 120 | * There is an INT DMA ERR mismatch between eSDHC and STD SDHC SPEC: |
97e4ba6a RZ |
121 | * Bit25 is used in STD SPEC, and is reserved in fsl eSDHC design, |
122 | * but bit28 is used as the INT DMA ERR in fsl eSDHC design. | |
123 | * Define this macro DMA error INT for fsl eSDHC | |
124 | */ | |
60bf6396 | 125 | #define ESDHC_INT_VENDOR_SPEC_DMA_ERR (1 << 28) |
97e4ba6a | 126 | |
bb6e3581 BC |
127 | /* the address offset of CQHCI */ |
128 | #define ESDHC_CQHCI_ADDR_OFFSET 0x100 | |
129 | ||
58ac8177 RZ |
130 | /* |
131 | * The CMDTYPE of the CMD register (offset 0xE) should be set to | |
132 | * "11" when the STOP CMD12 is issued on imx53 to abort one | |
133 | * open ended multi-blk IO. Otherwise the TC INT wouldn't | |
134 | * be generated. | |
135 | * In exact block transfer, the controller doesn't complete the | |
136 | * operations automatically as required at the end of the | |
137 | * transfer and remains on hold if the abort command is not sent. | |
d04f8d5b BT |
138 | * As a result, the TC flag is not asserted and SW received timeout |
139 | * exception. Bit1 of Vendor Spec register is used to fix it. | |
58ac8177 | 140 | */ |
31fbb301 | 141 | #define ESDHC_FLAG_MULTIBLK_NO_INT BIT(1) |
9d61c009 SG |
142 | /* |
143 | * The flag tells that the ESDHC controller is an USDHC block that is | |
144 | * integrated on the i.MX6 series. | |
145 | */ | |
146 | #define ESDHC_FLAG_USDHC BIT(3) | |
6e9fd28e DA |
147 | /* The IP supports manual tuning process */ |
148 | #define ESDHC_FLAG_MAN_TUNING BIT(4) | |
149 | /* The IP supports standard tuning process */ | |
150 | #define ESDHC_FLAG_STD_TUNING BIT(5) | |
151 | /* The IP has SDHCI_CAPABILITIES_1 register */ | |
152 | #define ESDHC_FLAG_HAVE_CAP1 BIT(6) | |
18094430 | 153 | /* |
d04f8d5b | 154 | * The IP has erratum ERR004536 |
18094430 DA |
155 | * uSDHC: ADMA Length Mismatch Error occurs if the AHB read access is slow, |
156 | * when reading data from the card | |
667123f6 BT |
157 | * This flag is also set for i.MX25 and i.MX35 in order to get |
158 | * SDHCI_QUIRK_BROKEN_ADMA, but for different reasons (ADMA capability bits). | |
18094430 DA |
159 | */ |
160 | #define ESDHC_FLAG_ERR004536 BIT(7) | |
4245afff DA |
161 | /* The IP supports HS200 mode */ |
162 | #define ESDHC_FLAG_HS200 BIT(8) | |
28b07674 HC |
163 | /* The IP supports HS400 mode */ |
164 | #define ESDHC_FLAG_HS400 BIT(9) | |
af6a50d4 BC |
165 | /* |
166 | * The IP has errata ERR010450 | |
167 | * uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't | |
168 | * exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz. | |
169 | */ | |
170 | #define ESDHC_FLAG_ERR010450 BIT(10) | |
029e2476 BC |
171 | /* The IP supports HS400ES mode */ |
172 | #define ESDHC_FLAG_HS400_ES BIT(11) | |
bb6e3581 BC |
173 | /* The IP has Host Controller Interface for Command Queuing */ |
174 | #define ESDHC_FLAG_CQHCI BIT(12) | |
1c4989b0 BC |
175 | /* need request pmqos during low power */ |
176 | #define ESDHC_FLAG_PMQOS BIT(13) | |
a26a4f1b HC |
177 | /* The IP state got lost in low power mode */ |
178 | #define ESDHC_FLAG_STATE_LOST_IN_LPMODE BIT(14) | |
5c11f1ff HC |
179 | /* The IP lost clock rate in PM_RUNTIME */ |
180 | #define ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME BIT(15) | |
74898cbc HC |
181 | /* |
182 | * The IP do not support the ACMD23 feature completely when use ADMA mode. | |
183 | * In ADMA mode, it only use the 16 bit block count of the register 0x4 | |
184 | * (BLOCK_ATT) as the CMD23's argument for ACMD23 mode, which means it will | |
185 | * ignore the upper 16 bit of the CMD23's argument. This will block the reliable | |
186 | * write operation in RPMB, because RPMB reliable write need to set the bit31 | |
187 | * of the CMD23's argument. | |
188 | * imx6qpdl/imx6sx/imx6sl/imx7d has this limitation only for ADMA mode, SDMA | |
189 | * do not has this limitation. so when these SoC use ADMA mode, it need to | |
190 | * disable the ACMD23 feature. | |
191 | */ | |
192 | #define ESDHC_FLAG_BROKEN_AUTO_CMD23 BIT(16) | |
e149860d | 193 | |
f47c4bbf SG |
194 | struct esdhc_soc_data { |
195 | u32 flags; | |
196 | }; | |
197 | ||
4f100012 | 198 | static const struct esdhc_soc_data esdhc_imx25_data = { |
667123f6 | 199 | .flags = ESDHC_FLAG_ERR004536, |
f47c4bbf SG |
200 | }; |
201 | ||
4f100012 | 202 | static const struct esdhc_soc_data esdhc_imx35_data = { |
667123f6 | 203 | .flags = ESDHC_FLAG_ERR004536, |
f47c4bbf SG |
204 | }; |
205 | ||
4f100012 | 206 | static const struct esdhc_soc_data esdhc_imx51_data = { |
f47c4bbf SG |
207 | .flags = 0, |
208 | }; | |
209 | ||
4f100012 | 210 | static const struct esdhc_soc_data esdhc_imx53_data = { |
f47c4bbf SG |
211 | .flags = ESDHC_FLAG_MULTIBLK_NO_INT, |
212 | }; | |
213 | ||
4f100012 | 214 | static const struct esdhc_soc_data usdhc_imx6q_data = { |
74898cbc HC |
215 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING |
216 | | ESDHC_FLAG_BROKEN_AUTO_CMD23, | |
6e9fd28e DA |
217 | }; |
218 | ||
4f100012 | 219 | static const struct esdhc_soc_data usdhc_imx6sl_data = { |
6e9fd28e | 220 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
4245afff | 221 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_ERR004536 |
74898cbc HC |
222 | | ESDHC_FLAG_HS200 |
223 | | ESDHC_FLAG_BROKEN_AUTO_CMD23, | |
57ed3314 SG |
224 | }; |
225 | ||
74898cbc | 226 | static const struct esdhc_soc_data usdhc_imx6sll_data = { |
913d4951 | 227 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
a26a4f1b | 228 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
86b59671 | 229 | | ESDHC_FLAG_HS400 |
a26a4f1b | 230 | | ESDHC_FLAG_STATE_LOST_IN_LPMODE, |
57ed3314 SG |
231 | }; |
232 | ||
4f100012 | 233 | static const struct esdhc_soc_data usdhc_imx6sx_data = { |
913d4951 | 234 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
74898cbc HC |
235 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
236 | | ESDHC_FLAG_STATE_LOST_IN_LPMODE | |
237 | | ESDHC_FLAG_BROKEN_AUTO_CMD23, | |
913d4951 DA |
238 | }; |
239 | ||
af6a50d4 BC |
240 | static const struct esdhc_soc_data usdhc_imx6ull_data = { |
241 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | |
242 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | |
a26a4f1b HC |
243 | | ESDHC_FLAG_ERR010450 |
244 | | ESDHC_FLAG_STATE_LOST_IN_LPMODE, | |
af6a50d4 BC |
245 | }; |
246 | ||
4f100012 | 247 | static const struct esdhc_soc_data usdhc_imx7d_data = { |
28b07674 HC |
248 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
249 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | |
a26a4f1b | 250 | | ESDHC_FLAG_HS400 |
74898cbc HC |
251 | | ESDHC_FLAG_STATE_LOST_IN_LPMODE |
252 | | ESDHC_FLAG_BROKEN_AUTO_CMD23, | |
28b07674 HC |
253 | }; |
254 | ||
1c4989b0 BC |
255 | static struct esdhc_soc_data usdhc_imx7ulp_data = { |
256 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | |
257 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | |
a26a4f1b HC |
258 | | ESDHC_FLAG_PMQOS | ESDHC_FLAG_HS400 |
259 | | ESDHC_FLAG_STATE_LOST_IN_LPMODE, | |
1c4989b0 BC |
260 | }; |
261 | ||
029e2476 BC |
262 | static struct esdhc_soc_data usdhc_imx8qxp_data = { |
263 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | |
264 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | |
bb6e3581 | 265 | | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES |
a26a4f1b | 266 | | ESDHC_FLAG_CQHCI |
5c11f1ff HC |
267 | | ESDHC_FLAG_STATE_LOST_IN_LPMODE |
268 | | ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME, | |
029e2476 BC |
269 | }; |
270 | ||
cde5e8e9 HC |
271 | static struct esdhc_soc_data usdhc_imx8mm_data = { |
272 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | |
273 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | |
274 | | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES | |
275 | | ESDHC_FLAG_CQHCI | |
276 | | ESDHC_FLAG_STATE_LOST_IN_LPMODE, | |
029e2476 BC |
277 | }; |
278 | ||
e149860d | 279 | struct pltfm_imx_data { |
e149860d | 280 | u32 scratchpad; |
e62d8b8f | 281 | struct pinctrl *pinctrl; |
ad93220d DA |
282 | struct pinctrl_state *pins_100mhz; |
283 | struct pinctrl_state *pins_200mhz; | |
f47c4bbf | 284 | const struct esdhc_soc_data *socdata; |
842afc02 | 285 | struct esdhc_platform_data boarddata; |
52dac615 SH |
286 | struct clk *clk_ipg; |
287 | struct clk *clk_ahb; | |
288 | struct clk *clk_per; | |
3602785b | 289 | unsigned int actual_clock; |
361b8482 | 290 | enum { |
d04f8d5b | 291 | NO_CMD_PENDING, /* no multiblock command pending */ |
361b8482 LS |
292 | MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */ |
293 | WAIT_FOR_INT, /* sent CMD12, waiting for response INT */ | |
294 | } multiblock_status; | |
de5bdbff | 295 | u32 is_ddr; |
1c4989b0 | 296 | struct pm_qos_request pm_qos_req; |
e149860d RZ |
297 | }; |
298 | ||
f8cbf461 | 299 | static const struct platform_device_id imx_esdhc_devtype[] = { |
57ed3314 SG |
300 | { |
301 | .name = "sdhci-esdhc-imx25", | |
f47c4bbf | 302 | .driver_data = (kernel_ulong_t) &esdhc_imx25_data, |
57ed3314 SG |
303 | }, { |
304 | .name = "sdhci-esdhc-imx35", | |
f47c4bbf | 305 | .driver_data = (kernel_ulong_t) &esdhc_imx35_data, |
57ed3314 SG |
306 | }, { |
307 | .name = "sdhci-esdhc-imx51", | |
f47c4bbf | 308 | .driver_data = (kernel_ulong_t) &esdhc_imx51_data, |
57ed3314 SG |
309 | }, { |
310 | /* sentinel */ | |
311 | } | |
312 | }; | |
313 | MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype); | |
314 | ||
abfafc2d | 315 | static const struct of_device_id imx_esdhc_dt_ids[] = { |
f47c4bbf SG |
316 | { .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_data, }, |
317 | { .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, }, | |
318 | { .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, }, | |
319 | { .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, }, | |
913d4951 | 320 | { .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, }, |
6e9fd28e | 321 | { .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, }, |
74898cbc | 322 | { .compatible = "fsl,imx6sll-usdhc", .data = &usdhc_imx6sll_data, }, |
f47c4bbf | 323 | { .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, }, |
af6a50d4 | 324 | { .compatible = "fsl,imx6ull-usdhc", .data = &usdhc_imx6ull_data, }, |
28b07674 | 325 | { .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, }, |
1c4989b0 | 326 | { .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, }, |
029e2476 | 327 | { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, }, |
cde5e8e9 | 328 | { .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, }, |
abfafc2d SG |
329 | { /* sentinel */ } |
330 | }; | |
331 | MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); | |
332 | ||
57ed3314 SG |
333 | static inline int is_imx25_esdhc(struct pltfm_imx_data *data) |
334 | { | |
f47c4bbf | 335 | return data->socdata == &esdhc_imx25_data; |
57ed3314 SG |
336 | } |
337 | ||
338 | static inline int is_imx53_esdhc(struct pltfm_imx_data *data) | |
339 | { | |
f47c4bbf | 340 | return data->socdata == &esdhc_imx53_data; |
57ed3314 SG |
341 | } |
342 | ||
95a2482a SG |
343 | static inline int is_imx6q_usdhc(struct pltfm_imx_data *data) |
344 | { | |
f47c4bbf | 345 | return data->socdata == &usdhc_imx6q_data; |
95a2482a SG |
346 | } |
347 | ||
9d61c009 SG |
348 | static inline int esdhc_is_usdhc(struct pltfm_imx_data *data) |
349 | { | |
f47c4bbf | 350 | return !!(data->socdata->flags & ESDHC_FLAG_USDHC); |
9d61c009 SG |
351 | } |
352 | ||
95f25efe WS |
353 | static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) |
354 | { | |
355 | void __iomem *base = host->ioaddr + (reg & ~0x3); | |
356 | u32 shift = (reg & 0x3) * 8; | |
357 | ||
358 | writel(((readl(base) & ~(mask << shift)) | (val << shift)), base); | |
359 | } | |
360 | ||
3722c74c HC |
361 | #define DRIVER_NAME "sdhci-esdhc-imx" |
362 | #define ESDHC_IMX_DUMP(f, x...) \ | |
363 | pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) | |
364 | static void esdhc_dump_debug_regs(struct sdhci_host *host) | |
365 | { | |
366 | int i; | |
367 | char *debug_status[7] = { | |
368 | "cmd debug status", | |
369 | "data debug status", | |
370 | "trans debug status", | |
371 | "dma debug status", | |
372 | "adma debug status", | |
373 | "fifo debug status", | |
374 | "async fifo debug status" | |
375 | }; | |
376 | ||
377 | ESDHC_IMX_DUMP("========= ESDHC IMX DEBUG STATUS DUMP =========\n"); | |
378 | for (i = 0; i < 7; i++) { | |
379 | esdhc_clrset_le(host, ESDHC_DEBUG_SEL_MASK, | |
380 | ESDHC_DEBUG_SEL_CMD_STATE + i, ESDHC_DEBUG_SEL_REG); | |
381 | ESDHC_IMX_DUMP("%s: 0x%04x\n", debug_status[i], | |
382 | readw(host->ioaddr + ESDHC_DEBUG_SEL_AND_STATUS_REG)); | |
383 | } | |
384 | ||
385 | esdhc_clrset_le(host, ESDHC_DEBUG_SEL_MASK, 0, ESDHC_DEBUG_SEL_REG); | |
386 | ||
387 | } | |
388 | ||
f581e909 HC |
389 | static inline void esdhc_wait_for_card_clock_gate_off(struct sdhci_host *host) |
390 | { | |
391 | u32 present_state; | |
392 | int ret; | |
393 | ||
394 | ret = readl_poll_timeout(host->ioaddr + ESDHC_PRSSTAT, present_state, | |
395 | (present_state & ESDHC_CLOCK_GATE_OFF), 2, 100); | |
396 | if (ret == -ETIMEDOUT) | |
397 | dev_warn(mmc_dev(host->mmc), "%s: card clock still not gate off in 100us!.\n", __func__); | |
398 | } | |
399 | ||
7e29c306 WS |
400 | static u32 esdhc_readl_le(struct sdhci_host *host, int reg) |
401 | { | |
361b8482 | 402 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
070e6d3f | 403 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
7e29c306 WS |
404 | u32 val = readl(host->ioaddr + reg); |
405 | ||
0322191e DA |
406 | if (unlikely(reg == SDHCI_PRESENT_STATE)) { |
407 | u32 fsl_prss = val; | |
408 | /* save the least 20 bits */ | |
409 | val = fsl_prss & 0x000FFFFF; | |
410 | /* move dat[0-3] bits */ | |
411 | val |= (fsl_prss & 0x0F000000) >> 4; | |
412 | /* move cmd line bit */ | |
413 | val |= (fsl_prss & 0x00800000) << 1; | |
414 | } | |
415 | ||
97e4ba6a | 416 | if (unlikely(reg == SDHCI_CAPABILITIES)) { |
6b4fb671 DA |
417 | /* ignore bit[0-15] as it stores cap_1 register val for mx6sl */ |
418 | if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1) | |
419 | val &= 0xffff0000; | |
420 | ||
97e4ba6a RZ |
421 | /* In FSL esdhc IC module, only bit20 is used to indicate the |
422 | * ADMA2 capability of esdhc, but this bit is messed up on | |
423 | * some SOCs (e.g. on MX25, MX35 this bit is set, but they | |
424 | * don't actually support ADMA2). So set the BROKEN_ADMA | |
d04f8d5b | 425 | * quirk on MX25/35 platforms. |
97e4ba6a RZ |
426 | */ |
427 | ||
428 | if (val & SDHCI_CAN_DO_ADMA1) { | |
429 | val &= ~SDHCI_CAN_DO_ADMA1; | |
430 | val |= SDHCI_CAN_DO_ADMA2; | |
431 | } | |
432 | } | |
433 | ||
6e9fd28e DA |
434 | if (unlikely(reg == SDHCI_CAPABILITIES_1)) { |
435 | if (esdhc_is_usdhc(imx_data)) { | |
436 | if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1) | |
437 | val = readl(host->ioaddr + SDHCI_CAPABILITIES) & 0xFFFF; | |
438 | else | |
439 | /* imx6q/dl does not have cap_1 register, fake one */ | |
440 | val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104 | |
888824bb | 441 | | SDHCI_SUPPORT_SDR50 |
da0295ff | 442 | | SDHCI_USE_SDR50_TUNING |
a8e809ec MY |
443 | | FIELD_PREP(SDHCI_RETUNING_MODE_MASK, |
444 | SDHCI_TUNING_MODE_3); | |
28b07674 HC |
445 | |
446 | if (imx_data->socdata->flags & ESDHC_FLAG_HS400) | |
447 | val |= SDHCI_SUPPORT_HS400; | |
92748bea SA |
448 | |
449 | /* | |
450 | * Do not advertise faster UHS modes if there are no | |
451 | * pinctrl states for 100MHz/200MHz. | |
452 | */ | |
453 | if (IS_ERR_OR_NULL(imx_data->pins_100mhz) || | |
454 | IS_ERR_OR_NULL(imx_data->pins_200mhz)) | |
455 | val &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50 | |
456 | | SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_HS400); | |
6e9fd28e DA |
457 | } |
458 | } | |
0322191e | 459 | |
9d61c009 | 460 | if (unlikely(reg == SDHCI_MAX_CURRENT) && esdhc_is_usdhc(imx_data)) { |
0322191e | 461 | val = 0; |
804a65b3 MY |
462 | val |= FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, 0xFF); |
463 | val |= FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, 0xFF); | |
464 | val |= FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, 0xFF); | |
0322191e DA |
465 | } |
466 | ||
97e4ba6a | 467 | if (unlikely(reg == SDHCI_INT_STATUS)) { |
60bf6396 SG |
468 | if (val & ESDHC_INT_VENDOR_SPEC_DMA_ERR) { |
469 | val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR; | |
97e4ba6a RZ |
470 | val |= SDHCI_INT_ADMA_ERROR; |
471 | } | |
361b8482 LS |
472 | |
473 | /* | |
474 | * mask off the interrupt we get in response to the manually | |
475 | * sent CMD12 | |
476 | */ | |
477 | if ((imx_data->multiblock_status == WAIT_FOR_INT) && | |
478 | ((val & SDHCI_INT_RESPONSE) == SDHCI_INT_RESPONSE)) { | |
479 | val &= ~SDHCI_INT_RESPONSE; | |
480 | writel(SDHCI_INT_RESPONSE, host->ioaddr + | |
481 | SDHCI_INT_STATUS); | |
482 | imx_data->multiblock_status = NO_CMD_PENDING; | |
483 | } | |
97e4ba6a RZ |
484 | } |
485 | ||
7e29c306 WS |
486 | return val; |
487 | } | |
488 | ||
489 | static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) | |
490 | { | |
e149860d | 491 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
070e6d3f | 492 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
0d58864b TL |
493 | u32 data; |
494 | ||
77da3da0 AB |
495 | if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE || |
496 | reg == SDHCI_INT_STATUS)) { | |
b7321042 | 497 | if ((val & SDHCI_INT_CARD_INT) && !esdhc_is_usdhc(imx_data)) { |
0d58864b TL |
498 | /* |
499 | * Clear and then set D3CD bit to avoid missing the | |
d04f8d5b | 500 | * card interrupt. This is an eSDHC controller problem |
0d58864b TL |
501 | * so we need to apply the following workaround: clear |
502 | * and set D3CD bit will make eSDHC re-sample the card | |
503 | * interrupt. In case a card interrupt was lost, | |
504 | * re-sample it by the following steps. | |
505 | */ | |
506 | data = readl(host->ioaddr + SDHCI_HOST_CONTROL); | |
60bf6396 | 507 | data &= ~ESDHC_CTRL_D3CD; |
0d58864b | 508 | writel(data, host->ioaddr + SDHCI_HOST_CONTROL); |
60bf6396 | 509 | data |= ESDHC_CTRL_D3CD; |
0d58864b TL |
510 | writel(data, host->ioaddr + SDHCI_HOST_CONTROL); |
511 | } | |
915be485 DA |
512 | |
513 | if (val & SDHCI_INT_ADMA_ERROR) { | |
514 | val &= ~SDHCI_INT_ADMA_ERROR; | |
515 | val |= ESDHC_INT_VENDOR_SPEC_DMA_ERR; | |
516 | } | |
0d58864b | 517 | } |
7e29c306 | 518 | |
f47c4bbf | 519 | if (unlikely((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) |
58ac8177 RZ |
520 | && (reg == SDHCI_INT_STATUS) |
521 | && (val & SDHCI_INT_DATA_END))) { | |
522 | u32 v; | |
60bf6396 SG |
523 | v = readl(host->ioaddr + ESDHC_VENDOR_SPEC); |
524 | v &= ~ESDHC_VENDOR_SPEC_SDIO_QUIRK; | |
525 | writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); | |
361b8482 LS |
526 | |
527 | if (imx_data->multiblock_status == MULTIBLK_IN_PROCESS) | |
528 | { | |
529 | /* send a manual CMD12 with RESPTYP=none */ | |
530 | data = MMC_STOP_TRANSMISSION << 24 | | |
531 | SDHCI_CMD_ABORTCMD << 16; | |
532 | writel(data, host->ioaddr + SDHCI_TRANSFER_MODE); | |
533 | imx_data->multiblock_status = WAIT_FOR_INT; | |
534 | } | |
58ac8177 RZ |
535 | } |
536 | ||
7e29c306 WS |
537 | writel(val, host->ioaddr + reg); |
538 | } | |
539 | ||
95f25efe WS |
540 | static u16 esdhc_readw_le(struct sdhci_host *host, int reg) |
541 | { | |
ef4d0888 | 542 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
070e6d3f | 543 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
0322191e DA |
544 | u16 ret = 0; |
545 | u32 val; | |
ef4d0888 | 546 | |
95a2482a | 547 | if (unlikely(reg == SDHCI_HOST_VERSION)) { |
ef4d0888 | 548 | reg ^= 2; |
9d61c009 | 549 | if (esdhc_is_usdhc(imx_data)) { |
ef4d0888 SG |
550 | /* |
551 | * The usdhc register returns a wrong host version. | |
552 | * Correct it here. | |
553 | */ | |
554 | return SDHCI_SPEC_300; | |
555 | } | |
95a2482a | 556 | } |
95f25efe | 557 | |
0322191e DA |
558 | if (unlikely(reg == SDHCI_HOST_CONTROL2)) { |
559 | val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | |
560 | if (val & ESDHC_VENDOR_SPEC_VSELECT) | |
561 | ret |= SDHCI_CTRL_VDD_180; | |
562 | ||
9d61c009 | 563 | if (esdhc_is_usdhc(imx_data)) { |
6e9fd28e DA |
564 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) |
565 | val = readl(host->ioaddr + ESDHC_MIX_CTRL); | |
566 | else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) | |
567 | /* the std tuning bits is in ACMD12_ERR for imx6sl */ | |
869f8a69 | 568 | val = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
0322191e DA |
569 | } |
570 | ||
6e9fd28e DA |
571 | if (val & ESDHC_MIX_CTRL_EXE_TUNE) |
572 | ret |= SDHCI_CTRL_EXEC_TUNING; | |
573 | if (val & ESDHC_MIX_CTRL_SMPCLK_SEL) | |
574 | ret |= SDHCI_CTRL_TUNED_CLK; | |
575 | ||
0322191e DA |
576 | ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; |
577 | ||
578 | return ret; | |
579 | } | |
580 | ||
7dd109ef DA |
581 | if (unlikely(reg == SDHCI_TRANSFER_MODE)) { |
582 | if (esdhc_is_usdhc(imx_data)) { | |
583 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); | |
584 | ret = m & ESDHC_MIX_CTRL_SDHCI_MASK; | |
585 | /* Swap AC23 bit */ | |
586 | if (m & ESDHC_MIX_CTRL_AC23EN) { | |
587 | ret &= ~ESDHC_MIX_CTRL_AC23EN; | |
588 | ret |= SDHCI_TRNS_AUTO_CMD23; | |
589 | } | |
590 | } else { | |
591 | ret = readw(host->ioaddr + SDHCI_TRANSFER_MODE); | |
592 | } | |
593 | ||
594 | return ret; | |
595 | } | |
596 | ||
95f25efe WS |
597 | return readw(host->ioaddr + reg); |
598 | } | |
599 | ||
600 | static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |
601 | { | |
602 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
070e6d3f | 603 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
0322191e | 604 | u32 new_val = 0; |
95f25efe WS |
605 | |
606 | switch (reg) { | |
0322191e DA |
607 | case SDHCI_CLOCK_CONTROL: |
608 | new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | |
609 | if (val & SDHCI_CLOCK_CARD_EN) | |
610 | new_val |= ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; | |
611 | else | |
612 | new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; | |
eeed7026 | 613 | writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); |
f581e909 HC |
614 | if (!(new_val & ESDHC_VENDOR_SPEC_FRC_SDCLK_ON)) |
615 | esdhc_wait_for_card_clock_gate_off(host); | |
0322191e DA |
616 | return; |
617 | case SDHCI_HOST_CONTROL2: | |
618 | new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | |
619 | if (val & SDHCI_CTRL_VDD_180) | |
620 | new_val |= ESDHC_VENDOR_SPEC_VSELECT; | |
621 | else | |
622 | new_val &= ~ESDHC_VENDOR_SPEC_VSELECT; | |
623 | writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); | |
6e9fd28e DA |
624 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { |
625 | new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); | |
da0295ff | 626 | if (val & SDHCI_CTRL_TUNED_CLK) { |
6e9fd28e | 627 | new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL; |
da0295ff DA |
628 | new_val |= ESDHC_MIX_CTRL_AUTO_TUNE_EN; |
629 | } else { | |
6e9fd28e | 630 | new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; |
da0295ff DA |
631 | new_val &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN; |
632 | } | |
6e9fd28e DA |
633 | writel(new_val , host->ioaddr + ESDHC_MIX_CTRL); |
634 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { | |
869f8a69 | 635 | u32 v = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
6e9fd28e | 636 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); |
8b2bb0ad DA |
637 | if (val & SDHCI_CTRL_TUNED_CLK) { |
638 | v |= ESDHC_MIX_CTRL_SMPCLK_SEL; | |
639 | } else { | |
640 | v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; | |
641 | m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; | |
0b330e38 | 642 | m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN; |
8b2bb0ad DA |
643 | } |
644 | ||
6e9fd28e | 645 | if (val & SDHCI_CTRL_EXEC_TUNING) { |
6e9fd28e DA |
646 | v |= ESDHC_MIX_CTRL_EXE_TUNE; |
647 | m |= ESDHC_MIX_CTRL_FBCLK_SEL; | |
0b330e38 | 648 | m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN; |
6e9fd28e | 649 | } else { |
6e9fd28e | 650 | v &= ~ESDHC_MIX_CTRL_EXE_TUNE; |
6e9fd28e DA |
651 | } |
652 | ||
869f8a69 | 653 | writel(v, host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
6e9fd28e DA |
654 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); |
655 | } | |
0322191e | 656 | return; |
95f25efe | 657 | case SDHCI_TRANSFER_MODE: |
f47c4bbf | 658 | if ((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) |
58ac8177 RZ |
659 | && (host->cmd->opcode == SD_IO_RW_EXTENDED) |
660 | && (host->cmd->data->blocks > 1) | |
661 | && (host->cmd->data->flags & MMC_DATA_READ)) { | |
662 | u32 v; | |
60bf6396 SG |
663 | v = readl(host->ioaddr + ESDHC_VENDOR_SPEC); |
664 | v |= ESDHC_VENDOR_SPEC_SDIO_QUIRK; | |
665 | writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); | |
58ac8177 | 666 | } |
69f54698 | 667 | |
9d61c009 | 668 | if (esdhc_is_usdhc(imx_data)) { |
3fbd4322 | 669 | u32 wml; |
69f54698 | 670 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); |
2a15f981 SG |
671 | /* Swap AC23 bit */ |
672 | if (val & SDHCI_TRNS_AUTO_CMD23) { | |
673 | val &= ~SDHCI_TRNS_AUTO_CMD23; | |
674 | val |= ESDHC_MIX_CTRL_AC23EN; | |
675 | } | |
676 | m = val | (m & ~ESDHC_MIX_CTRL_SDHCI_MASK); | |
69f54698 | 677 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); |
3fbd4322 AG |
678 | |
679 | /* Set watermark levels for PIO access to maximum value | |
680 | * (128 words) to accommodate full 512 bytes buffer. | |
681 | * For DMA access restore the levels to default value. | |
682 | */ | |
683 | m = readl(host->ioaddr + ESDHC_WTMK_LVL); | |
e534b82f | 684 | if (val & SDHCI_TRNS_DMA) { |
3fbd4322 | 685 | wml = ESDHC_WTMK_LVL_WML_VAL_DEF; |
e534b82f HC |
686 | } else { |
687 | u8 ctrl; | |
3fbd4322 | 688 | wml = ESDHC_WTMK_LVL_WML_VAL_MAX; |
e534b82f HC |
689 | |
690 | /* | |
691 | * Since already disable DMA mode, so also need | |
692 | * to clear the DMASEL. Otherwise, for standard | |
693 | * tuning, when send tuning command, usdhc will | |
694 | * still prefetch the ADMA script from wrong | |
695 | * DMA address, then we will see IOMMU report | |
696 | * some error which show lack of TLB mapping. | |
697 | */ | |
698 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | |
699 | ctrl &= ~SDHCI_CTRL_DMA_MASK; | |
700 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); | |
701 | } | |
3fbd4322 AG |
702 | m &= ~(ESDHC_WTMK_LVL_RD_WML_MASK | |
703 | ESDHC_WTMK_LVL_WR_WML_MASK); | |
704 | m |= (wml << ESDHC_WTMK_LVL_RD_WML_SHIFT) | | |
705 | (wml << ESDHC_WTMK_LVL_WR_WML_SHIFT); | |
706 | writel(m, host->ioaddr + ESDHC_WTMK_LVL); | |
69f54698 SG |
707 | } else { |
708 | /* | |
709 | * Postpone this write, we must do it together with a | |
710 | * command write that is down below. | |
711 | */ | |
712 | imx_data->scratchpad = val; | |
713 | } | |
95f25efe WS |
714 | return; |
715 | case SDHCI_COMMAND: | |
361b8482 | 716 | if (host->cmd->opcode == MMC_STOP_TRANSMISSION) |
58ac8177 | 717 | val |= SDHCI_CMD_ABORTCMD; |
95a2482a | 718 | |
361b8482 | 719 | if ((host->cmd->opcode == MMC_SET_BLOCK_COUNT) && |
f47c4bbf | 720 | (imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) |
361b8482 LS |
721 | imx_data->multiblock_status = MULTIBLK_IN_PROCESS; |
722 | ||
9d61c009 | 723 | if (esdhc_is_usdhc(imx_data)) |
95a2482a SG |
724 | writel(val << 16, |
725 | host->ioaddr + SDHCI_TRANSFER_MODE); | |
69f54698 | 726 | else |
95a2482a SG |
727 | writel(val << 16 | imx_data->scratchpad, |
728 | host->ioaddr + SDHCI_TRANSFER_MODE); | |
95f25efe WS |
729 | return; |
730 | case SDHCI_BLOCK_SIZE: | |
731 | val &= ~SDHCI_MAKE_BLKSZ(0x7, 0); | |
732 | break; | |
733 | } | |
734 | esdhc_clrset_le(host, 0xffff, val, reg); | |
735 | } | |
736 | ||
77da3da0 AB |
737 | static u8 esdhc_readb_le(struct sdhci_host *host, int reg) |
738 | { | |
739 | u8 ret; | |
740 | u32 val; | |
741 | ||
742 | switch (reg) { | |
743 | case SDHCI_HOST_CONTROL: | |
744 | val = readl(host->ioaddr + reg); | |
745 | ||
746 | ret = val & SDHCI_CTRL_LED; | |
747 | ret |= (val >> 5) & SDHCI_CTRL_DMA_MASK; | |
748 | ret |= (val & ESDHC_CTRL_4BITBUS); | |
749 | ret |= (val & ESDHC_CTRL_8BITBUS) << 3; | |
750 | return ret; | |
751 | } | |
752 | ||
753 | return readb(host->ioaddr + reg); | |
754 | } | |
755 | ||
95f25efe WS |
756 | static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) |
757 | { | |
9a0985b7 | 758 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
070e6d3f | 759 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
81a0a8bc | 760 | u32 new_val = 0; |
af51079e | 761 | u32 mask; |
95f25efe WS |
762 | |
763 | switch (reg) { | |
764 | case SDHCI_POWER_CONTROL: | |
765 | /* | |
766 | * FSL put some DMA bits here | |
767 | * If your board has a regulator, code should be here | |
768 | */ | |
769 | return; | |
770 | case SDHCI_HOST_CONTROL: | |
6b40d182 | 771 | /* FSL messed up here, so we need to manually compose it. */ |
af51079e | 772 | new_val = val & SDHCI_CTRL_LED; |
7122bbb0 | 773 | /* ensure the endianness */ |
95f25efe | 774 | new_val |= ESDHC_HOST_CONTROL_LE; |
9a0985b7 WC |
775 | /* bits 8&9 are reserved on mx25 */ |
776 | if (!is_imx25_esdhc(imx_data)) { | |
777 | /* DMA mode bits are shifted */ | |
778 | new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5; | |
779 | } | |
95f25efe | 780 | |
af51079e SH |
781 | /* |
782 | * Do not touch buswidth bits here. This is done in | |
783 | * esdhc_pltfm_bus_width. | |
f6825748 | 784 | * Do not touch the D3CD bit either which is used for the |
d04f8d5b | 785 | * SDIO interrupt erratum workaround. |
af51079e | 786 | */ |
f6825748 | 787 | mask = 0xffff & ~(ESDHC_CTRL_BUSWIDTH_MASK | ESDHC_CTRL_D3CD); |
af51079e SH |
788 | |
789 | esdhc_clrset_le(host, mask, new_val, reg); | |
95f25efe | 790 | return; |
81a0a8bc BT |
791 | case SDHCI_SOFTWARE_RESET: |
792 | if (val & SDHCI_RESET_DATA) | |
793 | new_val = readl(host->ioaddr + SDHCI_HOST_CONTROL); | |
794 | break; | |
95f25efe WS |
795 | } |
796 | esdhc_clrset_le(host, 0xff, val, reg); | |
913413c3 | 797 | |
81a0a8bc BT |
798 | if (reg == SDHCI_SOFTWARE_RESET) { |
799 | if (val & SDHCI_RESET_ALL) { | |
800 | /* | |
801 | * The esdhc has a design violation to SDHC spec which | |
802 | * tells that software reset should not affect card | |
803 | * detection circuit. But esdhc clears its SYSCTL | |
804 | * register bits [0..2] during the software reset. This | |
805 | * will stop those clocks that card detection circuit | |
806 | * relies on. To work around it, we turn the clocks on | |
807 | * back to keep card detection circuit functional. | |
808 | */ | |
809 | esdhc_clrset_le(host, 0x7, 0x7, ESDHC_SYSTEM_CONTROL); | |
810 | /* | |
811 | * The reset on usdhc fails to clear MIX_CTRL register. | |
812 | * Do it manually here. | |
813 | */ | |
814 | if (esdhc_is_usdhc(imx_data)) { | |
815 | /* | |
816 | * the tuning bits should be kept during reset | |
817 | */ | |
818 | new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); | |
819 | writel(new_val & ESDHC_MIX_CTRL_TUNING_MASK, | |
820 | host->ioaddr + ESDHC_MIX_CTRL); | |
821 | imx_data->is_ddr = 0; | |
822 | } | |
823 | } else if (val & SDHCI_RESET_DATA) { | |
824 | /* | |
825 | * The eSDHC DAT line software reset clears at least the | |
826 | * data transfer width on i.MX25, so make sure that the | |
827 | * Host Control register is unaffected. | |
828 | */ | |
829 | esdhc_clrset_le(host, 0xff, new_val, | |
830 | SDHCI_HOST_CONTROL); | |
de5bdbff | 831 | } |
58c8c4fb | 832 | } |
95f25efe WS |
833 | } |
834 | ||
0ddf03c9 LS |
835 | static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) |
836 | { | |
837 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
0ddf03c9 | 838 | |
a3bd4f98 | 839 | return pltfm_host->clock; |
0ddf03c9 LS |
840 | } |
841 | ||
95f25efe WS |
842 | static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) |
843 | { | |
844 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
845 | ||
a974862f | 846 | return pltfm_host->clock / 256 / 16; |
95f25efe WS |
847 | } |
848 | ||
8ba9580a LS |
849 | static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, |
850 | unsigned int clock) | |
851 | { | |
852 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
070e6d3f | 853 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
a974862f | 854 | unsigned int host_clock = pltfm_host->clock; |
5143c953 BT |
855 | int ddr_pre_div = imx_data->is_ddr ? 2 : 1; |
856 | int pre_div = 1; | |
d31fc00a | 857 | int div = 1; |
f581e909 | 858 | int ret; |
fed2f6e2 | 859 | u32 temp, val; |
d31fc00a | 860 | |
73e736f8 SA |
861 | if (esdhc_is_usdhc(imx_data)) { |
862 | val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | |
863 | writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, | |
864 | host->ioaddr + ESDHC_VENDOR_SPEC); | |
f581e909 | 865 | esdhc_wait_for_card_clock_gate_off(host); |
73e736f8 SA |
866 | } |
867 | ||
fed2f6e2 | 868 | if (clock == 0) { |
1650d0c7 | 869 | host->mmc->actual_clock = 0; |
373073ef | 870 | return; |
fed2f6e2 | 871 | } |
d31fc00a | 872 | |
499ed50f BT |
873 | /* For i.MX53 eSDHCv3, SYSCTL.SDCLKFS may not be set to 0. */ |
874 | if (is_imx53_esdhc(imx_data)) { | |
875 | /* | |
876 | * According to the i.MX53 reference manual, if DLLCTRL[10] can | |
877 | * be set, then the controller is eSDHCv3, else it is eSDHCv2. | |
878 | */ | |
879 | val = readl(host->ioaddr + ESDHC_DLL_CTRL); | |
880 | writel(val | BIT(10), host->ioaddr + ESDHC_DLL_CTRL); | |
881 | temp = readl(host->ioaddr + ESDHC_DLL_CTRL); | |
882 | writel(val, host->ioaddr + ESDHC_DLL_CTRL); | |
883 | if (temp & BIT(10)) | |
884 | pre_div = 2; | |
885 | } | |
886 | ||
d31fc00a DA |
887 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); |
888 | temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | |
889 | | ESDHC_CLOCK_MASK); | |
890 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | |
891 | ||
af6a50d4 BC |
892 | if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) { |
893 | unsigned int max_clock; | |
894 | ||
895 | max_clock = imx_data->is_ddr ? 45000000 : 150000000; | |
896 | ||
897 | clock = min(clock, max_clock); | |
898 | } | |
899 | ||
5143c953 BT |
900 | while (host_clock / (16 * pre_div * ddr_pre_div) > clock && |
901 | pre_div < 256) | |
d31fc00a DA |
902 | pre_div *= 2; |
903 | ||
5143c953 | 904 | while (host_clock / (div * pre_div * ddr_pre_div) > clock && div < 16) |
d31fc00a DA |
905 | div++; |
906 | ||
5143c953 | 907 | host->mmc->actual_clock = host_clock / (div * pre_div * ddr_pre_div); |
d31fc00a | 908 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", |
e76b8559 | 909 | clock, host->mmc->actual_clock); |
d31fc00a | 910 | |
5143c953 | 911 | pre_div >>= 1; |
d31fc00a DA |
912 | div--; |
913 | ||
914 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | |
915 | temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | |
916 | | (div << ESDHC_DIVIDER_SHIFT) | |
917 | | (pre_div << ESDHC_PREDIV_SHIFT)); | |
918 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | |
fed2f6e2 | 919 | |
f581e909 HC |
920 | /* need to wait the bit 3 of the PRSSTAT to be set, make sure card clock is stable */ |
921 | ret = readl_poll_timeout(host->ioaddr + ESDHC_PRSSTAT, temp, | |
922 | (temp & ESDHC_CLOCK_STABLE), 2, 100); | |
923 | if (ret == -ETIMEDOUT) | |
924 | dev_warn(mmc_dev(host->mmc), "card clock still not stable in 100us!.\n"); | |
925 | ||
9d61c009 | 926 | if (esdhc_is_usdhc(imx_data)) { |
fed2f6e2 DA |
927 | val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); |
928 | writel(val | ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, | |
d47b0586 | 929 | host->ioaddr + ESDHC_VENDOR_SPEC); |
fed2f6e2 DA |
930 | } |
931 | ||
8ba9580a LS |
932 | } |
933 | ||
913413c3 SG |
934 | static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) |
935 | { | |
842afc02 | 936 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
070e6d3f | 937 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
842afc02 | 938 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; |
913413c3 SG |
939 | |
940 | switch (boarddata->wp_type) { | |
941 | case ESDHC_WP_GPIO: | |
fbe5fdd1 | 942 | return mmc_gpio_get_ro(host->mmc); |
913413c3 SG |
943 | case ESDHC_WP_CONTROLLER: |
944 | return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) & | |
945 | SDHCI_WRITE_PROTECT); | |
946 | case ESDHC_WP_NONE: | |
947 | break; | |
948 | } | |
949 | ||
950 | return -ENOSYS; | |
951 | } | |
952 | ||
2317f56c | 953 | static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) |
af51079e SH |
954 | { |
955 | u32 ctrl; | |
956 | ||
957 | switch (width) { | |
958 | case MMC_BUS_WIDTH_8: | |
959 | ctrl = ESDHC_CTRL_8BITBUS; | |
960 | break; | |
961 | case MMC_BUS_WIDTH_4: | |
962 | ctrl = ESDHC_CTRL_4BITBUS; | |
963 | break; | |
964 | default: | |
965 | ctrl = 0; | |
966 | break; | |
967 | } | |
968 | ||
969 | esdhc_clrset_le(host, ESDHC_CTRL_BUSWIDTH_MASK, ctrl, | |
970 | SDHCI_HOST_CONTROL); | |
af51079e SH |
971 | } |
972 | ||
de3e1dd0 BC |
973 | static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) |
974 | { | |
975 | struct sdhci_host *host = mmc_priv(mmc); | |
976 | ||
977 | /* | |
978 | * i.MX uSDHC internally already uses a fixed optimized timing for | |
979 | * DDR50, normally does not require tuning for DDR50 mode. | |
980 | */ | |
981 | if (host->timing == MMC_TIMING_UHS_DDR50) | |
982 | return 0; | |
983 | ||
984 | return sdhci_execute_tuning(mmc, opcode); | |
985 | } | |
986 | ||
0322191e DA |
987 | static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) |
988 | { | |
989 | u32 reg; | |
990 | ||
991 | /* FIXME: delay a bit for card to be ready for next tuning due to errors */ | |
992 | mdelay(1); | |
993 | ||
994 | reg = readl(host->ioaddr + ESDHC_MIX_CTRL); | |
995 | reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | | |
996 | ESDHC_MIX_CTRL_FBCLK_SEL; | |
997 | writel(reg, host->ioaddr + ESDHC_MIX_CTRL); | |
998 | writel(val << 8, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); | |
999 | dev_dbg(mmc_dev(host->mmc), | |
d04f8d5b | 1000 | "tuning with delay 0x%x ESDHC_TUNE_CTRL_STATUS 0x%x\n", |
0322191e DA |
1001 | val, readl(host->ioaddr + ESDHC_TUNE_CTRL_STATUS)); |
1002 | } | |
1003 | ||
0322191e DA |
1004 | static void esdhc_post_tuning(struct sdhci_host *host) |
1005 | { | |
1006 | u32 reg; | |
1007 | ||
1008 | reg = readl(host->ioaddr + ESDHC_MIX_CTRL); | |
1009 | reg &= ~ESDHC_MIX_CTRL_EXE_TUNE; | |
da0295ff | 1010 | reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN; |
0322191e DA |
1011 | writel(reg, host->ioaddr + ESDHC_MIX_CTRL); |
1012 | } | |
1013 | ||
1014 | static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode) | |
1015 | { | |
1016 | int min, max, avg, ret; | |
1017 | ||
1018 | /* find the mininum delay first which can pass tuning */ | |
1019 | min = ESDHC_TUNE_CTRL_MIN; | |
1020 | while (min < ESDHC_TUNE_CTRL_MAX) { | |
1021 | esdhc_prepare_tuning(host, min); | |
9979dbe5 | 1022 | if (!mmc_send_tuning(host->mmc, opcode, NULL)) |
0322191e DA |
1023 | break; |
1024 | min += ESDHC_TUNE_CTRL_STEP; | |
1025 | } | |
1026 | ||
1027 | /* find the maxinum delay which can not pass tuning */ | |
1028 | max = min + ESDHC_TUNE_CTRL_STEP; | |
1029 | while (max < ESDHC_TUNE_CTRL_MAX) { | |
1030 | esdhc_prepare_tuning(host, max); | |
9979dbe5 | 1031 | if (mmc_send_tuning(host->mmc, opcode, NULL)) { |
0322191e DA |
1032 | max -= ESDHC_TUNE_CTRL_STEP; |
1033 | break; | |
1034 | } | |
1035 | max += ESDHC_TUNE_CTRL_STEP; | |
1036 | } | |
1037 | ||
1038 | /* use average delay to get the best timing */ | |
1039 | avg = (min + max) / 2; | |
1040 | esdhc_prepare_tuning(host, avg); | |
9979dbe5 | 1041 | ret = mmc_send_tuning(host->mmc, opcode, NULL); |
0322191e DA |
1042 | esdhc_post_tuning(host); |
1043 | ||
d04f8d5b | 1044 | dev_dbg(mmc_dev(host->mmc), "tuning %s at 0x%x ret %d\n", |
0322191e DA |
1045 | ret ? "failed" : "passed", avg, ret); |
1046 | ||
1047 | return ret; | |
1048 | } | |
1049 | ||
029e2476 BC |
1050 | static void esdhc_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios) |
1051 | { | |
1052 | struct sdhci_host *host = mmc_priv(mmc); | |
1053 | u32 m; | |
1054 | ||
1055 | m = readl(host->ioaddr + ESDHC_MIX_CTRL); | |
1056 | if (ios->enhanced_strobe) | |
1057 | m |= ESDHC_MIX_CTRL_HS400_ES_EN; | |
1058 | else | |
1059 | m &= ~ESDHC_MIX_CTRL_HS400_ES_EN; | |
1060 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); | |
1061 | } | |
1062 | ||
ad93220d DA |
1063 | static int esdhc_change_pinstate(struct sdhci_host *host, |
1064 | unsigned int uhs) | |
1065 | { | |
1066 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
070e6d3f | 1067 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
ad93220d DA |
1068 | struct pinctrl_state *pinctrl; |
1069 | ||
1070 | dev_dbg(mmc_dev(host->mmc), "change pinctrl state for uhs %d\n", uhs); | |
1071 | ||
1072 | if (IS_ERR(imx_data->pinctrl) || | |
ad93220d DA |
1073 | IS_ERR(imx_data->pins_100mhz) || |
1074 | IS_ERR(imx_data->pins_200mhz)) | |
1075 | return -EINVAL; | |
1076 | ||
1077 | switch (uhs) { | |
1078 | case MMC_TIMING_UHS_SDR50: | |
9f327845 | 1079 | case MMC_TIMING_UHS_DDR50: |
ad93220d DA |
1080 | pinctrl = imx_data->pins_100mhz; |
1081 | break; | |
1082 | case MMC_TIMING_UHS_SDR104: | |
429a5b45 | 1083 | case MMC_TIMING_MMC_HS200: |
28b07674 | 1084 | case MMC_TIMING_MMC_HS400: |
ad93220d DA |
1085 | pinctrl = imx_data->pins_200mhz; |
1086 | break; | |
1087 | default: | |
1088 | /* back to default state for other legacy timing */ | |
2480b720 | 1089 | return pinctrl_select_default_state(mmc_dev(host->mmc)); |
ad93220d DA |
1090 | } |
1091 | ||
1092 | return pinctrl_select_state(imx_data->pinctrl, pinctrl); | |
1093 | } | |
1094 | ||
28b07674 | 1095 | /* |
d04f8d5b | 1096 | * For HS400 eMMC, there is a data_strobe line. This signal is generated |
28b07674 HC |
1097 | * by the device and used for data output and CRC status response output |
1098 | * in HS400 mode. The frequency of this signal follows the frequency of | |
d04f8d5b | 1099 | * CLK generated by host. The host receives the data which is aligned to the |
28b07674 HC |
1100 | * edge of data_strobe line. Due to the time delay between CLK line and |
1101 | * data_strobe line, if the delay time is larger than one clock cycle, | |
d04f8d5b | 1102 | * then CLK and data_strobe line will be misaligned, read error shows up. |
28b07674 HC |
1103 | */ |
1104 | static void esdhc_set_strobe_dll(struct sdhci_host *host) | |
1105 | { | |
5bd2acdc HC |
1106 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
1107 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); | |
1108 | u32 strobe_delay; | |
28b07674 | 1109 | u32 v; |
373e800b | 1110 | int ret; |
28b07674 | 1111 | |
2b0efe82 BC |
1112 | /* disable clock before enabling strobe dll */ |
1113 | writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) & | |
1114 | ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, | |
1115 | host->ioaddr + ESDHC_VENDOR_SPEC); | |
f581e909 | 1116 | esdhc_wait_for_card_clock_gate_off(host); |
7ac6da26 | 1117 | |
2b0efe82 BC |
1118 | /* force a reset on strobe dll */ |
1119 | writel(ESDHC_STROBE_DLL_CTRL_RESET, | |
1120 | host->ioaddr + ESDHC_STROBE_DLL_CTRL); | |
2eaf5a53 BC |
1121 | /* clear the reset bit on strobe dll before any setting */ |
1122 | writel(0, host->ioaddr + ESDHC_STROBE_DLL_CTRL); | |
1123 | ||
2b0efe82 BC |
1124 | /* |
1125 | * enable strobe dll ctrl and adjust the delay target | |
1126 | * for the uSDHC loopback read clock | |
1127 | */ | |
5bd2acdc HC |
1128 | if (imx_data->boarddata.strobe_dll_delay_target) |
1129 | strobe_delay = imx_data->boarddata.strobe_dll_delay_target; | |
1130 | else | |
1131 | strobe_delay = ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT; | |
2b0efe82 | 1132 | v = ESDHC_STROBE_DLL_CTRL_ENABLE | |
2eaf5a53 | 1133 | ESDHC_STROBE_DLL_CTRL_SLV_UPDATE_INT_DEFAULT | |
5bd2acdc | 1134 | (strobe_delay << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); |
2b0efe82 | 1135 | writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL); |
373e800b HC |
1136 | |
1137 | /* wait max 50us to get the REF/SLV lock */ | |
1138 | ret = readl_poll_timeout(host->ioaddr + ESDHC_STROBE_DLL_STATUS, v, | |
1139 | ((v & ESDHC_STROBE_DLL_STS_REF_LOCK) && (v & ESDHC_STROBE_DLL_STS_SLV_LOCK)), 1, 50); | |
1140 | if (ret == -ETIMEDOUT) | |
2b0efe82 | 1141 | dev_warn(mmc_dev(host->mmc), |
373e800b | 1142 | "warning! HS400 strobe DLL status REF/SLV not lock in 50us, STROBE DLL status is %x!\n", v); |
28b07674 HC |
1143 | } |
1144 | ||
d9370424 HC |
1145 | static void esdhc_reset_tuning(struct sdhci_host *host) |
1146 | { | |
1147 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
1148 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); | |
1149 | u32 ctrl; | |
1150 | ||
d04f8d5b | 1151 | /* Reset the tuning circuit */ |
d9370424 HC |
1152 | if (esdhc_is_usdhc(imx_data)) { |
1153 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { | |
1154 | ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL); | |
1155 | ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; | |
1156 | ctrl &= ~ESDHC_MIX_CTRL_FBCLK_SEL; | |
1157 | writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL); | |
1158 | writel(0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); | |
1159 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { | |
869f8a69 | 1160 | ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
d9370424 | 1161 | ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; |
869f8a69 | 1162 | writel(ctrl, host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
d9370424 HC |
1163 | } |
1164 | } | |
1165 | } | |
1166 | ||
850a29b8 | 1167 | static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) |
ad93220d | 1168 | { |
28b07674 | 1169 | u32 m; |
ad93220d | 1170 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
070e6d3f | 1171 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
602519b2 | 1172 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; |
ad93220d | 1173 | |
28b07674 HC |
1174 | /* disable ddr mode and disable HS400 mode */ |
1175 | m = readl(host->ioaddr + ESDHC_MIX_CTRL); | |
1176 | m &= ~(ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN); | |
1177 | imx_data->is_ddr = 0; | |
1178 | ||
850a29b8 | 1179 | switch (timing) { |
ad93220d | 1180 | case MMC_TIMING_UHS_SDR12: |
ad93220d | 1181 | case MMC_TIMING_UHS_SDR25: |
ad93220d | 1182 | case MMC_TIMING_UHS_SDR50: |
ad93220d | 1183 | case MMC_TIMING_UHS_SDR104: |
de0a0dec | 1184 | case MMC_TIMING_MMC_HS: |
429a5b45 | 1185 | case MMC_TIMING_MMC_HS200: |
28b07674 | 1186 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); |
ad93220d DA |
1187 | break; |
1188 | case MMC_TIMING_UHS_DDR50: | |
69f5bf38 | 1189 | case MMC_TIMING_MMC_DDR52: |
28b07674 HC |
1190 | m |= ESDHC_MIX_CTRL_DDREN; |
1191 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); | |
de5bdbff | 1192 | imx_data->is_ddr = 1; |
602519b2 DA |
1193 | if (boarddata->delay_line) { |
1194 | u32 v; | |
1195 | v = boarddata->delay_line << | |
1196 | ESDHC_DLL_OVERRIDE_VAL_SHIFT | | |
1197 | (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT); | |
1198 | if (is_imx53_esdhc(imx_data)) | |
1199 | v <<= 1; | |
1200 | writel(v, host->ioaddr + ESDHC_DLL_CTRL); | |
1201 | } | |
ad93220d | 1202 | break; |
28b07674 HC |
1203 | case MMC_TIMING_MMC_HS400: |
1204 | m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN; | |
1205 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); | |
1206 | imx_data->is_ddr = 1; | |
7ac6da26 DA |
1207 | /* update clock after enable DDR for strobe DLL lock */ |
1208 | host->ops->set_clock(host, host->clock); | |
28b07674 HC |
1209 | esdhc_set_strobe_dll(host); |
1210 | break; | |
d9370424 HC |
1211 | case MMC_TIMING_LEGACY: |
1212 | default: | |
1213 | esdhc_reset_tuning(host); | |
1214 | break; | |
ad93220d DA |
1215 | } |
1216 | ||
850a29b8 | 1217 | esdhc_change_pinstate(host, timing); |
ad93220d DA |
1218 | } |
1219 | ||
0718e59a RK |
1220 | static void esdhc_reset(struct sdhci_host *host, u8 mask) |
1221 | { | |
1222 | sdhci_reset(host, mask); | |
1223 | ||
1224 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | |
1225 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | |
1226 | } | |
1227 | ||
10fd0ad9 AD |
1228 | static unsigned int esdhc_get_max_timeout_count(struct sdhci_host *host) |
1229 | { | |
1230 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
070e6d3f | 1231 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
10fd0ad9 | 1232 | |
d04f8d5b | 1233 | /* Doc Erratum: the uSDHC actual maximum timeout count is 1 << 29 */ |
2fb0b02b | 1234 | return esdhc_is_usdhc(imx_data) ? 1 << 29 : 1 << 27; |
10fd0ad9 AD |
1235 | } |
1236 | ||
e33eb8e2 AD |
1237 | static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) |
1238 | { | |
1239 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
070e6d3f | 1240 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
e33eb8e2 AD |
1241 | |
1242 | /* use maximum timeout counter */ | |
a215186d HC |
1243 | esdhc_clrset_le(host, ESDHC_SYS_CTRL_DTOCV_MASK, |
1244 | esdhc_is_usdhc(imx_data) ? 0xF : 0xE, | |
e33eb8e2 AD |
1245 | SDHCI_TIMEOUT_CONTROL); |
1246 | } | |
1247 | ||
bb6e3581 BC |
1248 | static u32 esdhc_cqhci_irq(struct sdhci_host *host, u32 intmask) |
1249 | { | |
1250 | int cmd_error = 0; | |
1251 | int data_error = 0; | |
1252 | ||
1253 | if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) | |
1254 | return intmask; | |
1255 | ||
1256 | cqhci_irq(host->mmc, intmask, cmd_error, data_error); | |
1257 | ||
1258 | return 0; | |
1259 | } | |
1260 | ||
6e9fd28e | 1261 | static struct sdhci_ops sdhci_esdhc_ops = { |
e149860d | 1262 | .read_l = esdhc_readl_le, |
0c6d49ce | 1263 | .read_w = esdhc_readw_le, |
77da3da0 | 1264 | .read_b = esdhc_readb_le, |
e149860d | 1265 | .write_l = esdhc_writel_le, |
0c6d49ce WS |
1266 | .write_w = esdhc_writew_le, |
1267 | .write_b = esdhc_writeb_le, | |
8ba9580a | 1268 | .set_clock = esdhc_pltfm_set_clock, |
0ddf03c9 | 1269 | .get_max_clock = esdhc_pltfm_get_max_clock, |
0c6d49ce | 1270 | .get_min_clock = esdhc_pltfm_get_min_clock, |
10fd0ad9 | 1271 | .get_max_timeout_count = esdhc_get_max_timeout_count, |
913413c3 | 1272 | .get_ro = esdhc_pltfm_get_ro, |
e33eb8e2 | 1273 | .set_timeout = esdhc_set_timeout, |
2317f56c | 1274 | .set_bus_width = esdhc_pltfm_set_bus_width, |
ad93220d | 1275 | .set_uhs_signaling = esdhc_set_uhs_signaling, |
0718e59a | 1276 | .reset = esdhc_reset, |
bb6e3581 | 1277 | .irq = esdhc_cqhci_irq, |
3722c74c | 1278 | .dump_vendor_regs = esdhc_dump_debug_regs, |
0c6d49ce WS |
1279 | }; |
1280 | ||
1db5eebf | 1281 | static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { |
97e4ba6a RZ |
1282 | .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT |
1283 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
1284 | | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | |
85d6509d | 1285 | | SDHCI_QUIRK_BROKEN_CARD_DETECTION, |
85d6509d SG |
1286 | .ops = &sdhci_esdhc_ops, |
1287 | }; | |
1288 | ||
f3f5cf3d DA |
1289 | static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host) |
1290 | { | |
1291 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
1292 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); | |
982cf37d | 1293 | struct cqhci_host *cq_host = host->mmc->cqe_private; |
2b16cf32 | 1294 | int tmp; |
f3f5cf3d DA |
1295 | |
1296 | if (esdhc_is_usdhc(imx_data)) { | |
1297 | /* | |
1298 | * The imx6q ROM code will change the default watermark | |
1299 | * level setting to something insane. Change it back here. | |
1300 | */ | |
1301 | writel(ESDHC_WTMK_DEFAULT_VAL, host->ioaddr + ESDHC_WTMK_LVL); | |
1302 | ||
1303 | /* | |
1304 | * ROM code will change the bit burst_length_enable setting | |
d04f8d5b | 1305 | * to zero if this usdhc is chosen to boot system. Change |
f3f5cf3d DA |
1306 | * it back here, otherwise it will impact the performance a |
1307 | * lot. This bit is used to enable/disable the burst length | |
d04f8d5b | 1308 | * for the external AHB2AXI bridge. It's useful especially |
f3f5cf3d DA |
1309 | * for INCR transfer because without burst length indicator, |
1310 | * the AHB2AXI bridge does not know the burst length in | |
1311 | * advance. And without burst length indicator, AHB INCR | |
1312 | * transfer can only be converted to singles on the AXI side. | |
1313 | */ | |
1314 | writel(readl(host->ioaddr + SDHCI_HOST_CONTROL) | |
1315 | | ESDHC_BURST_LEN_EN_INCR, | |
1316 | host->ioaddr + SDHCI_HOST_CONTROL); | |
e30be063 | 1317 | |
f3f5cf3d | 1318 | /* |
e30be063 BC |
1319 | * erratum ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL |
1320 | * TO1.1, it's harmless for MX6SL | |
1321 | */ | |
1322 | writel(readl(host->ioaddr + 0x6c) & ~BIT(7), | |
f3f5cf3d DA |
1323 | host->ioaddr + 0x6c); |
1324 | ||
1325 | /* disable DLL_CTRL delay line settings */ | |
1326 | writel(0x0, host->ioaddr + ESDHC_DLL_CTRL); | |
2b16cf32 | 1327 | |
bcdb5301 BC |
1328 | /* |
1329 | * For the case of command with busy, if set the bit | |
1330 | * ESDHC_VEND_SPEC2_EN_BUSY_IRQ, USDHC will generate a | |
1331 | * transfer complete interrupt when busy is deasserted. | |
1332 | * When CQHCI use DCMD to send a CMD need R1b respons, | |
1333 | * CQHCI require to set ESDHC_VEND_SPEC2_EN_BUSY_IRQ, | |
1334 | * otherwise DCMD will always meet timeout waiting for | |
1335 | * hardware interrupt issue. | |
1336 | */ | |
1337 | if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) { | |
1338 | tmp = readl(host->ioaddr + ESDHC_VEND_SPEC2); | |
1339 | tmp |= ESDHC_VEND_SPEC2_EN_BUSY_IRQ; | |
1340 | writel(tmp, host->ioaddr + ESDHC_VEND_SPEC2); | |
1341 | ||
1342 | host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; | |
1343 | } | |
1344 | ||
2b16cf32 DA |
1345 | if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { |
1346 | tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL); | |
1347 | tmp |= ESDHC_STD_TUNING_EN | | |
1348 | ESDHC_TUNING_START_TAP_DEFAULT; | |
1349 | if (imx_data->boarddata.tuning_start_tap) { | |
1350 | tmp &= ~ESDHC_TUNING_START_TAP_MASK; | |
1351 | tmp |= imx_data->boarddata.tuning_start_tap; | |
1352 | } | |
1353 | ||
1354 | if (imx_data->boarddata.tuning_step) { | |
1355 | tmp &= ~ESDHC_TUNING_STEP_MASK; | |
1356 | tmp |= imx_data->boarddata.tuning_step | |
1357 | << ESDHC_TUNING_STEP_SHIFT; | |
1358 | } | |
16e40e5b HC |
1359 | |
1360 | /* Disable the CMD CRC check for tuning, if not, need to | |
1361 | * add some delay after every tuning command, because | |
1362 | * hardware standard tuning logic will directly go to next | |
1363 | * step once it detect the CMD CRC error, will not wait for | |
1364 | * the card side to finally send out the tuning data, trigger | |
1365 | * the buffer read ready interrupt immediately. If usdhc send | |
1366 | * the next tuning command some eMMC card will stuck, can't | |
1367 | * response, block the tuning procedure or the first command | |
1368 | * after the whole tuning procedure always can't get any response. | |
1369 | */ | |
1370 | tmp |= ESDHC_TUNING_CMD_CRC_CHECK_DISABLE; | |
2b16cf32 | 1371 | writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL); |
a98c557e BC |
1372 | } else if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { |
1373 | /* | |
1374 | * ESDHC_STD_TUNING_EN may be configed in bootloader | |
1375 | * or ROM code, so clear this bit here to make sure | |
1376 | * the manual tuning can work. | |
1377 | */ | |
1378 | tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL); | |
1379 | tmp &= ~ESDHC_STD_TUNING_EN; | |
1380 | writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL); | |
2b16cf32 | 1381 | } |
982cf37d HC |
1382 | |
1383 | /* | |
1384 | * On i.MX8MM, we are running Dual Linux OS, with 1st Linux using SD Card | |
1385 | * as rootfs storage, 2nd Linux using eMMC as rootfs storage. We let the | |
1386 | * the 1st linux configure power/clock for the 2nd Linux. | |
1387 | * | |
1388 | * When the 2nd Linux is booting into rootfs stage, we let the 1st Linux | |
1389 | * to destroy the 2nd linux, then restart the 2nd linux, we met SDHCI dump. | |
1390 | * After we clear the pending interrupt and halt CQCTL, issue gone. | |
1391 | */ | |
1392 | if (cq_host) { | |
1393 | tmp = cqhci_readl(cq_host, CQHCI_IS); | |
1394 | cqhci_writel(cq_host, tmp, CQHCI_IS); | |
1395 | cqhci_writel(cq_host, CQHCI_HALT, CQHCI_CTL); | |
1396 | } | |
f3f5cf3d DA |
1397 | } |
1398 | } | |
1399 | ||
bb6e3581 BC |
1400 | static void esdhc_cqe_enable(struct mmc_host *mmc) |
1401 | { | |
1402 | struct sdhci_host *host = mmc_priv(mmc); | |
85236d2b | 1403 | struct cqhci_host *cq_host = mmc->cqe_private; |
bb6e3581 BC |
1404 | u32 reg; |
1405 | u16 mode; | |
1406 | int count = 10; | |
1407 | ||
1408 | /* | |
1409 | * CQE gets stuck if it sees Buffer Read Enable bit set, which can be | |
1410 | * the case after tuning, so ensure the buffer is drained. | |
1411 | */ | |
1412 | reg = sdhci_readl(host, SDHCI_PRESENT_STATE); | |
1413 | while (reg & SDHCI_DATA_AVAILABLE) { | |
1414 | sdhci_readl(host, SDHCI_BUFFER); | |
1415 | reg = sdhci_readl(host, SDHCI_PRESENT_STATE); | |
1416 | if (count-- == 0) { | |
1417 | dev_warn(mmc_dev(host->mmc), | |
1418 | "CQE may get stuck because the Buffer Read Enable bit is set\n"); | |
1419 | break; | |
1420 | } | |
1421 | mdelay(1); | |
1422 | } | |
1423 | ||
1424 | /* | |
1425 | * Runtime resume will reset the entire host controller, which | |
1426 | * will also clear the DMAEN/BCEN of register ESDHC_MIX_CTRL. | |
1427 | * Here set DMAEN and BCEN when enable CMDQ. | |
1428 | */ | |
1429 | mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); | |
1430 | if (host->flags & SDHCI_REQ_USE_DMA) | |
1431 | mode |= SDHCI_TRNS_DMA; | |
1432 | if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) | |
1433 | mode |= SDHCI_TRNS_BLK_CNT_EN; | |
1434 | sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); | |
1435 | ||
85236d2b BC |
1436 | /* |
1437 | * Though Runtime resume reset the entire host controller, | |
1438 | * but do not impact the CQHCI side, need to clear the | |
1439 | * HALT bit, avoid CQHCI stuck in the first request when | |
1440 | * system resume back. | |
1441 | */ | |
1442 | cqhci_writel(cq_host, 0, CQHCI_CTL); | |
1443 | if (cqhci_readl(cq_host, CQHCI_CTL) && CQHCI_HALT) | |
1444 | dev_err(mmc_dev(host->mmc), | |
1445 | "failed to exit halt state when enable CQE\n"); | |
1446 | ||
1447 | ||
bb6e3581 BC |
1448 | sdhci_cqe_enable(mmc); |
1449 | } | |
1450 | ||
1451 | static void esdhc_sdhci_dumpregs(struct mmc_host *mmc) | |
1452 | { | |
1453 | sdhci_dumpregs(mmc_priv(mmc)); | |
1454 | } | |
1455 | ||
1456 | static const struct cqhci_host_ops esdhc_cqhci_ops = { | |
1457 | .enable = esdhc_cqe_enable, | |
1458 | .disable = sdhci_cqe_disable, | |
1459 | .dumpregs = esdhc_sdhci_dumpregs, | |
1460 | }; | |
1461 | ||
abfafc2d | 1462 | #ifdef CONFIG_OF |
c3be1efd | 1463 | static int |
abfafc2d | 1464 | sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, |
07bf2b54 | 1465 | struct sdhci_host *host, |
91fa4252 | 1466 | struct pltfm_imx_data *imx_data) |
abfafc2d SG |
1467 | { |
1468 | struct device_node *np = pdev->dev.of_node; | |
91fa4252 | 1469 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; |
4800e87a | 1470 | int ret; |
abfafc2d | 1471 | |
abfafc2d SG |
1472 | if (of_get_property(np, "fsl,wp-controller", NULL)) |
1473 | boarddata->wp_type = ESDHC_WP_CONTROLLER; | |
1474 | ||
74ff81e1 LW |
1475 | /* |
1476 | * If we have this property, then activate WP check. | |
1477 | * Retrieveing and requesting the actual WP GPIO will happen | |
1478 | * in the call to mmc_of_parse(). | |
1479 | */ | |
1480 | if (of_property_read_bool(np, "wp-gpios")) | |
abfafc2d SG |
1481 | boarddata->wp_type = ESDHC_WP_GPIO; |
1482 | ||
d407e30b | 1483 | of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step); |
d87fc966 DA |
1484 | of_property_read_u32(np, "fsl,tuning-start-tap", |
1485 | &boarddata->tuning_start_tap); | |
d407e30b | 1486 | |
5bd2acdc HC |
1487 | of_property_read_u32(np, "fsl,strobe-dll-delay-target", |
1488 | &boarddata->strobe_dll_delay_target); | |
ad93220d | 1489 | if (of_find_property(np, "no-1-8-v", NULL)) |
86f495c5 | 1490 | host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; |
ad93220d | 1491 | |
602519b2 DA |
1492 | if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) |
1493 | boarddata->delay_line = 0; | |
1494 | ||
07bf2b54 SH |
1495 | mmc_of_parse_voltage(np, &host->ocr_mask); |
1496 | ||
2480b720 | 1497 | if (esdhc_is_usdhc(imx_data)) { |
91fa4252 DA |
1498 | imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, |
1499 | ESDHC_PINCTRL_STATE_100MHZ); | |
1500 | imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, | |
1501 | ESDHC_PINCTRL_STATE_200MHZ); | |
91fa4252 DA |
1502 | } |
1503 | ||
15064119 | 1504 | /* call to generic mmc_of_parse to support additional capabilities */ |
4800e87a DA |
1505 | ret = mmc_of_parse(host->mmc); |
1506 | if (ret) | |
1507 | return ret; | |
1508 | ||
287980e4 | 1509 | if (mmc_gpio_get_cd(host->mmc) >= 0) |
4800e87a DA |
1510 | host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; |
1511 | ||
1512 | return 0; | |
abfafc2d SG |
1513 | } |
1514 | #else | |
1515 | static inline int | |
1516 | sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, | |
07bf2b54 | 1517 | struct sdhci_host *host, |
91fa4252 | 1518 | struct pltfm_imx_data *imx_data) |
abfafc2d SG |
1519 | { |
1520 | return -ENODEV; | |
1521 | } | |
1522 | #endif | |
1523 | ||
91fa4252 DA |
1524 | static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, |
1525 | struct sdhci_host *host, | |
1526 | struct pltfm_imx_data *imx_data) | |
1527 | { | |
1528 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; | |
1529 | int err; | |
1530 | ||
1531 | if (!host->mmc->parent->platform_data) { | |
1532 | dev_err(mmc_dev(host->mmc), "no board data!\n"); | |
1533 | return -EINVAL; | |
1534 | } | |
1535 | ||
1536 | imx_data->boarddata = *((struct esdhc_platform_data *) | |
1537 | host->mmc->parent->platform_data); | |
1538 | /* write_protect */ | |
1539 | if (boarddata->wp_type == ESDHC_WP_GPIO) { | |
9073d10b MM |
1540 | host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; |
1541 | ||
d0052ad9 | 1542 | err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0); |
91fa4252 DA |
1543 | if (err) { |
1544 | dev_err(mmc_dev(host->mmc), | |
1545 | "failed to request write-protect gpio!\n"); | |
1546 | return err; | |
1547 | } | |
91fa4252 DA |
1548 | } |
1549 | ||
1550 | /* card_detect */ | |
1551 | switch (boarddata->cd_type) { | |
1552 | case ESDHC_CD_GPIO: | |
d0052ad9 | 1553 | err = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0); |
91fa4252 DA |
1554 | if (err) { |
1555 | dev_err(mmc_dev(host->mmc), | |
1556 | "failed to request card-detect gpio!\n"); | |
1557 | return err; | |
1558 | } | |
df561f66 | 1559 | fallthrough; |
91fa4252 DA |
1560 | |
1561 | case ESDHC_CD_CONTROLLER: | |
1562 | /* we have a working card_detect back */ | |
1563 | host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; | |
1564 | break; | |
1565 | ||
1566 | case ESDHC_CD_PERMANENT: | |
1567 | host->mmc->caps |= MMC_CAP_NONREMOVABLE; | |
1568 | break; | |
1569 | ||
1570 | case ESDHC_CD_NONE: | |
1571 | break; | |
1572 | } | |
1573 | ||
1574 | switch (boarddata->max_bus_width) { | |
1575 | case 8: | |
1576 | host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; | |
1577 | break; | |
1578 | case 4: | |
1579 | host->mmc->caps |= MMC_CAP_4_BIT_DATA; | |
1580 | break; | |
1581 | case 1: | |
1582 | default: | |
1583 | host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; | |
1584 | break; | |
1585 | } | |
1586 | ||
1587 | return 0; | |
1588 | } | |
1589 | ||
c3be1efd | 1590 | static int sdhci_esdhc_imx_probe(struct platform_device *pdev) |
95f25efe | 1591 | { |
abfafc2d SG |
1592 | const struct of_device_id *of_id = |
1593 | of_match_device(imx_esdhc_dt_ids, &pdev->dev); | |
85d6509d SG |
1594 | struct sdhci_pltfm_host *pltfm_host; |
1595 | struct sdhci_host *host; | |
bb6e3581 | 1596 | struct cqhci_host *cq_host; |
0c6d49ce | 1597 | int err; |
e149860d | 1598 | struct pltfm_imx_data *imx_data; |
95f25efe | 1599 | |
070e6d3f JZ |
1600 | host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, |
1601 | sizeof(*imx_data)); | |
85d6509d SG |
1602 | if (IS_ERR(host)) |
1603 | return PTR_ERR(host); | |
1604 | ||
1605 | pltfm_host = sdhci_priv(host); | |
1606 | ||
070e6d3f | 1607 | imx_data = sdhci_pltfm_priv(pltfm_host); |
57ed3314 | 1608 | |
f47c4bbf SG |
1609 | imx_data->socdata = of_id ? of_id->data : (struct esdhc_soc_data *) |
1610 | pdev->id_entry->driver_data; | |
85d6509d | 1611 | |
1c4989b0 | 1612 | if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
d1b98305 | 1613 | cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0); |
1c4989b0 | 1614 | |
52dac615 SH |
1615 | imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
1616 | if (IS_ERR(imx_data->clk_ipg)) { | |
1617 | err = PTR_ERR(imx_data->clk_ipg); | |
e3af31c6 | 1618 | goto free_sdhci; |
95f25efe | 1619 | } |
52dac615 SH |
1620 | |
1621 | imx_data->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); | |
1622 | if (IS_ERR(imx_data->clk_ahb)) { | |
1623 | err = PTR_ERR(imx_data->clk_ahb); | |
e3af31c6 | 1624 | goto free_sdhci; |
52dac615 SH |
1625 | } |
1626 | ||
1627 | imx_data->clk_per = devm_clk_get(&pdev->dev, "per"); | |
1628 | if (IS_ERR(imx_data->clk_per)) { | |
1629 | err = PTR_ERR(imx_data->clk_per); | |
e3af31c6 | 1630 | goto free_sdhci; |
52dac615 SH |
1631 | } |
1632 | ||
1633 | pltfm_host->clk = imx_data->clk_per; | |
a974862f | 1634 | pltfm_host->clock = clk_get_rate(pltfm_host->clk); |
17b1eb7f FE |
1635 | err = clk_prepare_enable(imx_data->clk_per); |
1636 | if (err) | |
1637 | goto free_sdhci; | |
1638 | err = clk_prepare_enable(imx_data->clk_ipg); | |
1639 | if (err) | |
1640 | goto disable_per_clk; | |
1641 | err = clk_prepare_enable(imx_data->clk_ahb); | |
1642 | if (err) | |
1643 | goto disable_ipg_clk; | |
95f25efe | 1644 | |
ad93220d | 1645 | imx_data->pinctrl = devm_pinctrl_get(&pdev->dev); |
e62d8b8f DA |
1646 | if (IS_ERR(imx_data->pinctrl)) { |
1647 | err = PTR_ERR(imx_data->pinctrl); | |
b62eee9f | 1648 | dev_warn(mmc_dev(host->mmc), "could not get pinctrl\n"); |
e62d8b8f DA |
1649 | } |
1650 | ||
69ed60e0 | 1651 | if (esdhc_is_usdhc(imx_data)) { |
69ed60e0 | 1652 | host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; |
09c8192b | 1653 | host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR; |
f6140462 HC |
1654 | |
1655 | /* GPIO CD can be set as a wakeup source */ | |
1656 | host->mmc->caps |= MMC_CAP_CD_WAKE; | |
1657 | ||
4245afff DA |
1658 | if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200)) |
1659 | host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200; | |
a75dcbf4 DA |
1660 | |
1661 | /* clear tuning bits in case ROM has set it already */ | |
1662 | writel(0x0, host->ioaddr + ESDHC_MIX_CTRL); | |
869f8a69 | 1663 | writel(0x0, host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
a75dcbf4 | 1664 | writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); |
de3e1dd0 BC |
1665 | |
1666 | /* | |
1667 | * Link usdhc specific mmc_host_ops execute_tuning function, | |
1668 | * to replace the standard one in sdhci_ops. | |
1669 | */ | |
1670 | host->mmc_host_ops.execute_tuning = usdhc_execute_tuning; | |
69ed60e0 | 1671 | } |
f750ba9b | 1672 | |
6e9fd28e DA |
1673 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) |
1674 | sdhci_esdhc_ops.platform_execute_tuning = | |
1675 | esdhc_executing_tuning; | |
8b2bb0ad | 1676 | |
18094430 DA |
1677 | if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) |
1678 | host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; | |
1679 | ||
28b07674 HC |
1680 | if (imx_data->socdata->flags & ESDHC_FLAG_HS400) |
1681 | host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400; | |
1682 | ||
74898cbc HC |
1683 | if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) |
1684 | host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN; | |
1685 | ||
029e2476 BC |
1686 | if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { |
1687 | host->mmc->caps2 |= MMC_CAP2_HS400_ES; | |
1688 | host->mmc_host_ops.hs400_enhanced_strobe = | |
1689 | esdhc_hs400_enhanced_strobe; | |
1690 | } | |
1691 | ||
bb6e3581 | 1692 | if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) { |
bcdb5301 | 1693 | host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; |
bb6e3581 | 1694 | cq_host = devm_kzalloc(&pdev->dev, sizeof(*cq_host), GFP_KERNEL); |
9a633f3b WY |
1695 | if (!cq_host) { |
1696 | err = -ENOMEM; | |
bb6e3581 BC |
1697 | goto disable_ahb_clk; |
1698 | } | |
1699 | ||
1700 | cq_host->mmio = host->ioaddr + ESDHC_CQHCI_ADDR_OFFSET; | |
1701 | cq_host->ops = &esdhc_cqhci_ops; | |
1702 | ||
1703 | err = cqhci_init(cq_host, host->mmc, false); | |
1704 | if (err) | |
1705 | goto disable_ahb_clk; | |
1706 | } | |
1707 | ||
91fa4252 DA |
1708 | if (of_id) |
1709 | err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); | |
1710 | else | |
1711 | err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data); | |
1712 | if (err) | |
17b1eb7f | 1713 | goto disable_ahb_clk; |
ad93220d | 1714 | |
f3f5cf3d DA |
1715 | sdhci_esdhc_imx_hwinit(host); |
1716 | ||
85d6509d SG |
1717 | err = sdhci_add_host(host); |
1718 | if (err) | |
17b1eb7f | 1719 | goto disable_ahb_clk; |
85d6509d | 1720 | |
89d7e5c1 | 1721 | pm_runtime_set_active(&pdev->dev); |
89d7e5c1 DA |
1722 | pm_runtime_set_autosuspend_delay(&pdev->dev, 50); |
1723 | pm_runtime_use_autosuspend(&pdev->dev); | |
1724 | pm_suspend_ignore_children(&pdev->dev, 1); | |
77903c01 | 1725 | pm_runtime_enable(&pdev->dev); |
89d7e5c1 | 1726 | |
95f25efe | 1727 | return 0; |
7e29c306 | 1728 | |
17b1eb7f | 1729 | disable_ahb_clk: |
52dac615 | 1730 | clk_disable_unprepare(imx_data->clk_ahb); |
17b1eb7f FE |
1731 | disable_ipg_clk: |
1732 | clk_disable_unprepare(imx_data->clk_ipg); | |
1733 | disable_per_clk: | |
1734 | clk_disable_unprepare(imx_data->clk_per); | |
e3af31c6 | 1735 | free_sdhci: |
1c4989b0 | 1736 | if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
d1b98305 | 1737 | cpu_latency_qos_remove_request(&imx_data->pm_qos_req); |
85d6509d SG |
1738 | sdhci_pltfm_free(pdev); |
1739 | return err; | |
95f25efe WS |
1740 | } |
1741 | ||
6e0ee714 | 1742 | static int sdhci_esdhc_imx_remove(struct platform_device *pdev) |
95f25efe | 1743 | { |
85d6509d | 1744 | struct sdhci_host *host = platform_get_drvdata(pdev); |
95f25efe | 1745 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
070e6d3f | 1746 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
85d6509d SG |
1747 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); |
1748 | ||
0b414368 | 1749 | pm_runtime_get_sync(&pdev->dev); |
89d7e5c1 | 1750 | pm_runtime_disable(&pdev->dev); |
0b414368 | 1751 | pm_runtime_put_noidle(&pdev->dev); |
89d7e5c1 | 1752 | |
0b414368 UH |
1753 | sdhci_remove_host(host, dead); |
1754 | ||
1755 | clk_disable_unprepare(imx_data->clk_per); | |
1756 | clk_disable_unprepare(imx_data->clk_ipg); | |
1757 | clk_disable_unprepare(imx_data->clk_ahb); | |
52dac615 | 1758 | |
1c4989b0 | 1759 | if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
d1b98305 | 1760 | cpu_latency_qos_remove_request(&imx_data->pm_qos_req); |
1c4989b0 | 1761 | |
85d6509d SG |
1762 | sdhci_pltfm_free(pdev); |
1763 | ||
1764 | return 0; | |
95f25efe WS |
1765 | } |
1766 | ||
2788ed42 | 1767 | #ifdef CONFIG_PM_SLEEP |
04143fba DA |
1768 | static int sdhci_esdhc_suspend(struct device *dev) |
1769 | { | |
3e3274ab | 1770 | struct sdhci_host *host = dev_get_drvdata(dev); |
a26a4f1b HC |
1771 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
1772 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); | |
bb6e3581 BC |
1773 | int ret; |
1774 | ||
1775 | if (host->mmc->caps2 & MMC_CAP2_CQE) { | |
1776 | ret = cqhci_suspend(host->mmc); | |
1777 | if (ret) | |
1778 | return ret; | |
1779 | } | |
3e3274ab | 1780 | |
a26a4f1b HC |
1781 | if ((imx_data->socdata->flags & ESDHC_FLAG_STATE_LOST_IN_LPMODE) && |
1782 | (host->tuning_mode != SDHCI_TUNING_MODE_1)) { | |
1783 | mmc_retune_timer_stop(host->mmc); | |
1784 | mmc_retune_needed(host->mmc); | |
1785 | } | |
1786 | ||
d38dcad4 AH |
1787 | if (host->tuning_mode != SDHCI_TUNING_MODE_3) |
1788 | mmc_retune_needed(host->mmc); | |
1789 | ||
af8fade4 | 1790 | ret = sdhci_suspend_host(host); |
f6140462 HC |
1791 | if (ret) |
1792 | return ret; | |
1793 | ||
1794 | ret = pinctrl_pm_select_sleep_state(dev); | |
1795 | if (ret) | |
1796 | return ret; | |
1797 | ||
1798 | ret = mmc_gpio_set_cd_wake(host->mmc, true); | |
af8fade4 HC |
1799 | |
1800 | return ret; | |
04143fba DA |
1801 | } |
1802 | ||
1803 | static int sdhci_esdhc_resume(struct device *dev) | |
1804 | { | |
cc17e129 | 1805 | struct sdhci_host *host = dev_get_drvdata(dev); |
bb6e3581 | 1806 | int ret; |
cc17e129 | 1807 | |
af8fade4 HC |
1808 | ret = pinctrl_pm_select_default_state(dev); |
1809 | if (ret) | |
1810 | return ret; | |
1811 | ||
19dbfdd3 DA |
1812 | /* re-initialize hw state in case it's lost in low power mode */ |
1813 | sdhci_esdhc_imx_hwinit(host); | |
cc17e129 | 1814 | |
bb6e3581 BC |
1815 | ret = sdhci_resume_host(host); |
1816 | if (ret) | |
1817 | return ret; | |
1818 | ||
1819 | if (host->mmc->caps2 & MMC_CAP2_CQE) | |
1820 | ret = cqhci_resume(host->mmc); | |
1821 | ||
f6140462 HC |
1822 | if (!ret) |
1823 | ret = mmc_gpio_set_cd_wake(host->mmc, false); | |
1824 | ||
bb6e3581 | 1825 | return ret; |
04143fba | 1826 | } |
2788ed42 | 1827 | #endif |
04143fba | 1828 | |
2788ed42 | 1829 | #ifdef CONFIG_PM |
89d7e5c1 DA |
1830 | static int sdhci_esdhc_runtime_suspend(struct device *dev) |
1831 | { | |
1832 | struct sdhci_host *host = dev_get_drvdata(dev); | |
1833 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
070e6d3f | 1834 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
89d7e5c1 DA |
1835 | int ret; |
1836 | ||
bb6e3581 BC |
1837 | if (host->mmc->caps2 & MMC_CAP2_CQE) { |
1838 | ret = cqhci_suspend(host->mmc); | |
1839 | if (ret) | |
1840 | return ret; | |
1841 | } | |
1842 | ||
89d7e5c1 | 1843 | ret = sdhci_runtime_suspend_host(host); |
371d39fa MT |
1844 | if (ret) |
1845 | return ret; | |
89d7e5c1 | 1846 | |
d38dcad4 AH |
1847 | if (host->tuning_mode != SDHCI_TUNING_MODE_3) |
1848 | mmc_retune_needed(host->mmc); | |
1849 | ||
af5d2b7b UH |
1850 | imx_data->actual_clock = host->mmc->actual_clock; |
1851 | esdhc_pltfm_set_clock(host, 0); | |
1852 | clk_disable_unprepare(imx_data->clk_per); | |
1853 | clk_disable_unprepare(imx_data->clk_ipg); | |
89d7e5c1 DA |
1854 | clk_disable_unprepare(imx_data->clk_ahb); |
1855 | ||
1c4989b0 | 1856 | if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
d1b98305 | 1857 | cpu_latency_qos_remove_request(&imx_data->pm_qos_req); |
1c4989b0 | 1858 | |
89d7e5c1 DA |
1859 | return ret; |
1860 | } | |
1861 | ||
1862 | static int sdhci_esdhc_runtime_resume(struct device *dev) | |
1863 | { | |
1864 | struct sdhci_host *host = dev_get_drvdata(dev); | |
1865 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
070e6d3f | 1866 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
17b1eb7f | 1867 | int err; |
89d7e5c1 | 1868 | |
1c4989b0 | 1869 | if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
d1b98305 | 1870 | cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0); |
1c4989b0 | 1871 | |
5c11f1ff HC |
1872 | if (imx_data->socdata->flags & ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME) |
1873 | clk_set_rate(imx_data->clk_per, pltfm_host->clock); | |
1874 | ||
a0ad3087 MT |
1875 | err = clk_prepare_enable(imx_data->clk_ahb); |
1876 | if (err) | |
1c4989b0 | 1877 | goto remove_pm_qos_request; |
a0ad3087 | 1878 | |
af5d2b7b UH |
1879 | err = clk_prepare_enable(imx_data->clk_per); |
1880 | if (err) | |
1881 | goto disable_ahb_clk; | |
1882 | ||
1883 | err = clk_prepare_enable(imx_data->clk_ipg); | |
1884 | if (err) | |
1885 | goto disable_per_clk; | |
1886 | ||
1887 | esdhc_pltfm_set_clock(host, imx_data->actual_clock); | |
a0ad3087 | 1888 | |
c6303c5d | 1889 | err = sdhci_runtime_resume_host(host, 0); |
17b1eb7f | 1890 | if (err) |
a0ad3087 | 1891 | goto disable_ipg_clk; |
17b1eb7f | 1892 | |
bb6e3581 BC |
1893 | if (host->mmc->caps2 & MMC_CAP2_CQE) |
1894 | err = cqhci_resume(host->mmc); | |
1895 | ||
1896 | return err; | |
89d7e5c1 | 1897 | |
17b1eb7f | 1898 | disable_ipg_clk: |
af5d2b7b | 1899 | clk_disable_unprepare(imx_data->clk_ipg); |
17b1eb7f | 1900 | disable_per_clk: |
af5d2b7b | 1901 | clk_disable_unprepare(imx_data->clk_per); |
a0ad3087 MT |
1902 | disable_ahb_clk: |
1903 | clk_disable_unprepare(imx_data->clk_ahb); | |
1c4989b0 BC |
1904 | remove_pm_qos_request: |
1905 | if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) | |
d1b98305 | 1906 | cpu_latency_qos_remove_request(&imx_data->pm_qos_req); |
17b1eb7f | 1907 | return err; |
89d7e5c1 DA |
1908 | } |
1909 | #endif | |
1910 | ||
1911 | static const struct dev_pm_ops sdhci_esdhc_pmops = { | |
04143fba | 1912 | SET_SYSTEM_SLEEP_PM_OPS(sdhci_esdhc_suspend, sdhci_esdhc_resume) |
89d7e5c1 DA |
1913 | SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend, |
1914 | sdhci_esdhc_runtime_resume, NULL) | |
1915 | }; | |
1916 | ||
85d6509d SG |
1917 | static struct platform_driver sdhci_esdhc_imx_driver = { |
1918 | .driver = { | |
1919 | .name = "sdhci-esdhc-imx", | |
abfafc2d | 1920 | .of_match_table = imx_esdhc_dt_ids, |
89d7e5c1 | 1921 | .pm = &sdhci_esdhc_pmops, |
85d6509d | 1922 | }, |
57ed3314 | 1923 | .id_table = imx_esdhc_devtype, |
85d6509d | 1924 | .probe = sdhci_esdhc_imx_probe, |
0433c143 | 1925 | .remove = sdhci_esdhc_imx_remove, |
95f25efe | 1926 | }; |
85d6509d | 1927 | |
d1f81a64 | 1928 | module_platform_driver(sdhci_esdhc_imx_driver); |
85d6509d SG |
1929 | |
1930 | MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC"); | |
035ff831 | 1931 | MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>"); |
85d6509d | 1932 | MODULE_LICENSE("GPL v2"); |