.. | .. |
---|
8 | 8 | * Author: Wolfram Sang <kernel@pengutronix.de> |
---|
9 | 9 | */ |
---|
10 | 10 | |
---|
| 11 | +#include <linux/bitfield.h> |
---|
11 | 12 | #include <linux/io.h> |
---|
| 13 | +#include <linux/iopoll.h> |
---|
12 | 14 | #include <linux/delay.h> |
---|
13 | 15 | #include <linux/err.h> |
---|
14 | 16 | #include <linux/clk.h> |
---|
15 | | -#include <linux/gpio.h> |
---|
16 | 17 | #include <linux/module.h> |
---|
17 | 18 | #include <linux/slab.h> |
---|
| 19 | +#include <linux/pm_qos.h> |
---|
18 | 20 | #include <linux/mmc/host.h> |
---|
19 | 21 | #include <linux/mmc/mmc.h> |
---|
20 | 22 | #include <linux/mmc/sdio.h> |
---|
21 | 23 | #include <linux/mmc/slot-gpio.h> |
---|
22 | 24 | #include <linux/of.h> |
---|
23 | 25 | #include <linux/of_device.h> |
---|
24 | | -#include <linux/of_gpio.h> |
---|
25 | 26 | #include <linux/pinctrl/consumer.h> |
---|
26 | 27 | #include <linux/platform_data/mmc-esdhc-imx.h> |
---|
27 | 28 | #include <linux/pm_runtime.h> |
---|
28 | | -#include <linux/iopoll.h> |
---|
| 29 | +#include "sdhci-cqhci.h" |
---|
29 | 30 | #include "sdhci-pltfm.h" |
---|
30 | 31 | #include "sdhci-esdhc.h" |
---|
| 32 | +#include "cqhci.h" |
---|
31 | 33 | |
---|
32 | 34 | #define ESDHC_SYS_CTRL_DTOCV_MASK 0x0f |
---|
33 | 35 | #define ESDHC_CTRL_D3CD 0x08 |
---|
.. | .. |
---|
37 | 39 | #define ESDHC_VENDOR_SPEC_SDIO_QUIRK (1 << 1) |
---|
38 | 40 | #define ESDHC_VENDOR_SPEC_VSELECT (1 << 1) |
---|
39 | 41 | #define ESDHC_VENDOR_SPEC_FRC_SDCLK_ON (1 << 8) |
---|
| 42 | +#define ESDHC_DEBUG_SEL_AND_STATUS_REG 0xc2 |
---|
| 43 | +#define ESDHC_DEBUG_SEL_REG 0xc3 |
---|
| 44 | +#define ESDHC_DEBUG_SEL_MASK 0xf |
---|
| 45 | +#define ESDHC_DEBUG_SEL_CMD_STATE 1 |
---|
| 46 | +#define ESDHC_DEBUG_SEL_DATA_STATE 2 |
---|
| 47 | +#define ESDHC_DEBUG_SEL_TRANS_STATE 3 |
---|
| 48 | +#define ESDHC_DEBUG_SEL_DMA_STATE 4 |
---|
| 49 | +#define ESDHC_DEBUG_SEL_ADMA_STATE 5 |
---|
| 50 | +#define ESDHC_DEBUG_SEL_FIFO_STATE 6 |
---|
| 51 | +#define ESDHC_DEBUG_SEL_ASYNC_FIFO_STATE 7 |
---|
40 | 52 | #define ESDHC_WTMK_LVL 0x44 |
---|
41 | 53 | #define ESDHC_WTMK_DEFAULT_VAL 0x10401040 |
---|
42 | 54 | #define ESDHC_WTMK_LVL_RD_WML_MASK 0x000000FF |
---|
.. | .. |
---|
53 | 65 | #define ESDHC_MIX_CTRL_AUTO_TUNE_EN (1 << 24) |
---|
54 | 66 | #define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25) |
---|
55 | 67 | #define ESDHC_MIX_CTRL_HS400_EN (1 << 26) |
---|
| 68 | +#define ESDHC_MIX_CTRL_HS400_ES_EN (1 << 27) |
---|
56 | 69 | /* Bits 3 and 6 are not SDHCI standard definitions */ |
---|
57 | 70 | #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 |
---|
58 | 71 | /* Tuning bits */ |
---|
.. | .. |
---|
73 | 86 | #define ESDHC_STROBE_DLL_CTRL 0x70 |
---|
74 | 87 | #define ESDHC_STROBE_DLL_CTRL_ENABLE (1 << 0) |
---|
75 | 88 | #define ESDHC_STROBE_DLL_CTRL_RESET (1 << 1) |
---|
| 89 | +#define ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT 0x7 |
---|
76 | 90 | #define ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT 3 |
---|
| 91 | +#define ESDHC_STROBE_DLL_CTRL_SLV_UPDATE_INT_DEFAULT (4 << 20) |
---|
77 | 92 | |
---|
78 | 93 | #define ESDHC_STROBE_DLL_STATUS 0x74 |
---|
79 | 94 | #define ESDHC_STROBE_DLL_STS_REF_LOCK (1 << 1) |
---|
80 | 95 | #define ESDHC_STROBE_DLL_STS_SLV_LOCK 0x1 |
---|
| 96 | + |
---|
| 97 | +#define ESDHC_VEND_SPEC2 0xc8 |
---|
| 98 | +#define ESDHC_VEND_SPEC2_EN_BUSY_IRQ (1 << 8) |
---|
81 | 99 | |
---|
82 | 100 | #define ESDHC_TUNING_CTRL 0xcc |
---|
83 | 101 | #define ESDHC_STD_TUNING_EN (1 << 24) |
---|
84 | 102 | /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */ |
---|
85 | 103 | #define ESDHC_TUNING_START_TAP_DEFAULT 0x1 |
---|
86 | 104 | #define ESDHC_TUNING_START_TAP_MASK 0x7f |
---|
| 105 | +#define ESDHC_TUNING_CMD_CRC_CHECK_DISABLE (1 << 7) |
---|
| 106 | +#define ESDHC_TUNING_STEP_DEFAULT 0x1 |
---|
87 | 107 | #define ESDHC_TUNING_STEP_MASK 0x00070000 |
---|
88 | 108 | #define ESDHC_TUNING_STEP_SHIFT 16 |
---|
89 | 109 | |
---|
.. | .. |
---|
105 | 125 | * Define this macro DMA error INT for fsl eSDHC |
---|
106 | 126 | */ |
---|
107 | 127 | #define ESDHC_INT_VENDOR_SPEC_DMA_ERR (1 << 28) |
---|
| 128 | + |
---|
| 129 | +/* the address offset of CQHCI */ |
---|
| 130 | +#define ESDHC_CQHCI_ADDR_OFFSET 0x100 |
---|
108 | 131 | |
---|
109 | 132 | /* |
---|
110 | 133 | * The CMDTYPE of the CMD register (offset 0xE) should be set to |
---|
.. | .. |
---|
141 | 164 | #define ESDHC_FLAG_HS200 BIT(8) |
---|
142 | 165 | /* The IP supports HS400 mode */ |
---|
143 | 166 | #define ESDHC_FLAG_HS400 BIT(9) |
---|
144 | | - |
---|
145 | | -/* A clock frequency higher than this rate requires strobe dll control */ |
---|
146 | | -#define ESDHC_STROBE_DLL_CLK_FREQ 100000000 |
---|
| 167 | +/* |
---|
| 168 | + * The IP has errata ERR010450 |
---|
| 169 | + * uSDHC: At 1.8V due to the I/O timing limit, for SDR mode, SD card |
---|
| 170 | + * clock can't exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz. |
---|
| 171 | + */ |
---|
| 172 | +#define ESDHC_FLAG_ERR010450 BIT(10) |
---|
| 173 | +/* The IP supports HS400ES mode */ |
---|
| 174 | +#define ESDHC_FLAG_HS400_ES BIT(11) |
---|
| 175 | +/* The IP has Host Controller Interface for Command Queuing */ |
---|
| 176 | +#define ESDHC_FLAG_CQHCI BIT(12) |
---|
| 177 | +/* need request pmqos during low power */ |
---|
| 178 | +#define ESDHC_FLAG_PMQOS BIT(13) |
---|
| 179 | +/* The IP state got lost in low power mode */ |
---|
| 180 | +#define ESDHC_FLAG_STATE_LOST_IN_LPMODE BIT(14) |
---|
| 181 | +/* The IP lost clock rate in PM_RUNTIME */ |
---|
| 182 | +#define ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME BIT(15) |
---|
| 183 | +/* |
---|
| 184 | + * The IP do not support the ACMD23 feature completely when use ADMA mode. |
---|
| 185 | + * In ADMA mode, it only use the 16 bit block count of the register 0x4 |
---|
| 186 | + * (BLOCK_ATT) as the CMD23's argument for ACMD23 mode, which means it will |
---|
| 187 | + * ignore the upper 16 bit of the CMD23's argument. This will block the reliable |
---|
| 188 | + * write operation in RPMB, because RPMB reliable write need to set the bit31 |
---|
| 189 | + * of the CMD23's argument. |
---|
| 190 | + * imx6qpdl/imx6sx/imx6sl/imx7d has this limitation only for ADMA mode, SDMA |
---|
| 191 | + * do not has this limitation. so when these SoC use ADMA mode, it need to |
---|
| 192 | + * disable the ACMD23 feature. |
---|
| 193 | + */ |
---|
| 194 | +#define ESDHC_FLAG_BROKEN_AUTO_CMD23 BIT(16) |
---|
147 | 195 | |
---|
148 | 196 | struct esdhc_soc_data { |
---|
149 | 197 | u32 flags; |
---|
150 | 198 | }; |
---|
151 | 199 | |
---|
152 | | -static struct esdhc_soc_data esdhc_imx25_data = { |
---|
| 200 | +static const struct esdhc_soc_data esdhc_imx25_data = { |
---|
153 | 201 | .flags = ESDHC_FLAG_ERR004536, |
---|
154 | 202 | }; |
---|
155 | 203 | |
---|
156 | | -static struct esdhc_soc_data esdhc_imx35_data = { |
---|
| 204 | +static const struct esdhc_soc_data esdhc_imx35_data = { |
---|
157 | 205 | .flags = ESDHC_FLAG_ERR004536, |
---|
158 | 206 | }; |
---|
159 | 207 | |
---|
160 | | -static struct esdhc_soc_data esdhc_imx51_data = { |
---|
| 208 | +static const struct esdhc_soc_data esdhc_imx51_data = { |
---|
161 | 209 | .flags = 0, |
---|
162 | 210 | }; |
---|
163 | 211 | |
---|
164 | | -static struct esdhc_soc_data esdhc_imx53_data = { |
---|
| 212 | +static const struct esdhc_soc_data esdhc_imx53_data = { |
---|
165 | 213 | .flags = ESDHC_FLAG_MULTIBLK_NO_INT, |
---|
166 | 214 | }; |
---|
167 | 215 | |
---|
168 | | -static struct esdhc_soc_data usdhc_imx6q_data = { |
---|
169 | | - .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING, |
---|
| 216 | +static const struct esdhc_soc_data usdhc_imx6q_data = { |
---|
| 217 | + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING |
---|
| 218 | + | ESDHC_FLAG_BROKEN_AUTO_CMD23, |
---|
170 | 219 | }; |
---|
171 | 220 | |
---|
172 | | -static struct esdhc_soc_data usdhc_imx6sl_data = { |
---|
| 221 | +static const struct esdhc_soc_data usdhc_imx6sl_data = { |
---|
173 | 222 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
---|
174 | 223 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_ERR004536 |
---|
175 | | - | ESDHC_FLAG_HS200, |
---|
| 224 | + | ESDHC_FLAG_HS200 |
---|
| 225 | + | ESDHC_FLAG_BROKEN_AUTO_CMD23, |
---|
176 | 226 | }; |
---|
177 | 227 | |
---|
178 | | -static struct esdhc_soc_data usdhc_imx6sx_data = { |
---|
179 | | - .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
---|
180 | | - | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200, |
---|
181 | | -}; |
---|
182 | | - |
---|
183 | | -static struct esdhc_soc_data usdhc_imx7d_data = { |
---|
| 228 | +static const struct esdhc_soc_data usdhc_imx6sll_data = { |
---|
184 | 229 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
---|
185 | 230 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
---|
186 | | - | ESDHC_FLAG_HS400, |
---|
| 231 | + | ESDHC_FLAG_HS400 |
---|
| 232 | + | ESDHC_FLAG_STATE_LOST_IN_LPMODE, |
---|
| 233 | +}; |
---|
| 234 | + |
---|
| 235 | +static const struct esdhc_soc_data usdhc_imx6sx_data = { |
---|
| 236 | + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
---|
| 237 | + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
---|
| 238 | + | ESDHC_FLAG_STATE_LOST_IN_LPMODE |
---|
| 239 | + | ESDHC_FLAG_BROKEN_AUTO_CMD23, |
---|
| 240 | +}; |
---|
| 241 | + |
---|
| 242 | +static const struct esdhc_soc_data usdhc_imx6ull_data = { |
---|
| 243 | + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
---|
| 244 | + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
---|
| 245 | + | ESDHC_FLAG_ERR010450 |
---|
| 246 | + | ESDHC_FLAG_STATE_LOST_IN_LPMODE, |
---|
| 247 | +}; |
---|
| 248 | + |
---|
| 249 | +static const struct esdhc_soc_data usdhc_imx7d_data = { |
---|
| 250 | + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
---|
| 251 | + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
---|
| 252 | + | ESDHC_FLAG_HS400 |
---|
| 253 | + | ESDHC_FLAG_STATE_LOST_IN_LPMODE |
---|
| 254 | + | ESDHC_FLAG_BROKEN_AUTO_CMD23, |
---|
| 255 | +}; |
---|
| 256 | + |
---|
| 257 | +static struct esdhc_soc_data usdhc_imx7ulp_data = { |
---|
| 258 | + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
---|
| 259 | + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
---|
| 260 | + | ESDHC_FLAG_PMQOS | ESDHC_FLAG_HS400 |
---|
| 261 | + | ESDHC_FLAG_STATE_LOST_IN_LPMODE, |
---|
| 262 | +}; |
---|
| 263 | + |
---|
| 264 | +static struct esdhc_soc_data usdhc_imx8qxp_data = { |
---|
| 265 | + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
---|
| 266 | + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
---|
| 267 | + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES |
---|
| 268 | + | ESDHC_FLAG_STATE_LOST_IN_LPMODE |
---|
| 269 | + | ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME, |
---|
| 270 | +}; |
---|
| 271 | + |
---|
| 272 | +static struct esdhc_soc_data usdhc_imx8mm_data = { |
---|
| 273 | + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
---|
| 274 | + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
---|
| 275 | + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES |
---|
| 276 | + | ESDHC_FLAG_STATE_LOST_IN_LPMODE, |
---|
187 | 277 | }; |
---|
188 | 278 | |
---|
189 | 279 | struct pltfm_imx_data { |
---|
190 | 280 | u32 scratchpad; |
---|
191 | 281 | struct pinctrl *pinctrl; |
---|
192 | | - struct pinctrl_state *pins_default; |
---|
193 | 282 | struct pinctrl_state *pins_100mhz; |
---|
194 | 283 | struct pinctrl_state *pins_200mhz; |
---|
195 | 284 | const struct esdhc_soc_data *socdata; |
---|
.. | .. |
---|
204 | 293 | WAIT_FOR_INT, /* sent CMD12, waiting for response INT */ |
---|
205 | 294 | } multiblock_status; |
---|
206 | 295 | u32 is_ddr; |
---|
| 296 | + struct pm_qos_request pm_qos_req; |
---|
207 | 297 | }; |
---|
208 | | - |
---|
209 | | -static const struct platform_device_id imx_esdhc_devtype[] = { |
---|
210 | | - { |
---|
211 | | - .name = "sdhci-esdhc-imx25", |
---|
212 | | - .driver_data = (kernel_ulong_t) &esdhc_imx25_data, |
---|
213 | | - }, { |
---|
214 | | - .name = "sdhci-esdhc-imx35", |
---|
215 | | - .driver_data = (kernel_ulong_t) &esdhc_imx35_data, |
---|
216 | | - }, { |
---|
217 | | - .name = "sdhci-esdhc-imx51", |
---|
218 | | - .driver_data = (kernel_ulong_t) &esdhc_imx51_data, |
---|
219 | | - }, { |
---|
220 | | - /* sentinel */ |
---|
221 | | - } |
---|
222 | | -}; |
---|
223 | | -MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype); |
---|
224 | 298 | |
---|
225 | 299 | static const struct of_device_id imx_esdhc_dt_ids[] = { |
---|
226 | 300 | { .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_data, }, |
---|
.. | .. |
---|
229 | 303 | { .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, }, |
---|
230 | 304 | { .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, }, |
---|
231 | 305 | { .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, }, |
---|
| 306 | + { .compatible = "fsl,imx6sll-usdhc", .data = &usdhc_imx6sll_data, }, |
---|
232 | 307 | { .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, }, |
---|
| 308 | + { .compatible = "fsl,imx6ull-usdhc", .data = &usdhc_imx6ull_data, }, |
---|
233 | 309 | { .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, }, |
---|
| 310 | + { .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, }, |
---|
| 311 | + { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, }, |
---|
| 312 | + { .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, }, |
---|
234 | 313 | { /* sentinel */ } |
---|
235 | 314 | }; |
---|
236 | 315 | MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); |
---|
.. | .. |
---|
261 | 340 | u32 shift = (reg & 0x3) * 8; |
---|
262 | 341 | |
---|
263 | 342 | writel(((readl(base) & ~(mask << shift)) | (val << shift)), base); |
---|
| 343 | +} |
---|
| 344 | + |
---|
| 345 | +#define DRIVER_NAME "sdhci-esdhc-imx" |
---|
| 346 | +#define ESDHC_IMX_DUMP(f, x...) \ |
---|
| 347 | + pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) |
---|
| 348 | +static void esdhc_dump_debug_regs(struct sdhci_host *host) |
---|
| 349 | +{ |
---|
| 350 | + int i; |
---|
| 351 | + char *debug_status[7] = { |
---|
| 352 | + "cmd debug status", |
---|
| 353 | + "data debug status", |
---|
| 354 | + "trans debug status", |
---|
| 355 | + "dma debug status", |
---|
| 356 | + "adma debug status", |
---|
| 357 | + "fifo debug status", |
---|
| 358 | + "async fifo debug status" |
---|
| 359 | + }; |
---|
| 360 | + |
---|
| 361 | + ESDHC_IMX_DUMP("========= ESDHC IMX DEBUG STATUS DUMP =========\n"); |
---|
| 362 | + for (i = 0; i < 7; i++) { |
---|
| 363 | + esdhc_clrset_le(host, ESDHC_DEBUG_SEL_MASK, |
---|
| 364 | + ESDHC_DEBUG_SEL_CMD_STATE + i, ESDHC_DEBUG_SEL_REG); |
---|
| 365 | + ESDHC_IMX_DUMP("%s: 0x%04x\n", debug_status[i], |
---|
| 366 | + readw(host->ioaddr + ESDHC_DEBUG_SEL_AND_STATUS_REG)); |
---|
| 367 | + } |
---|
| 368 | + |
---|
| 369 | + esdhc_clrset_le(host, ESDHC_DEBUG_SEL_MASK, 0, ESDHC_DEBUG_SEL_REG); |
---|
| 370 | + |
---|
| 371 | +} |
---|
| 372 | + |
---|
| 373 | +static inline void esdhc_wait_for_card_clock_gate_off(struct sdhci_host *host) |
---|
| 374 | +{ |
---|
| 375 | + u32 present_state; |
---|
| 376 | + int ret; |
---|
| 377 | + |
---|
| 378 | + ret = readl_poll_timeout(host->ioaddr + ESDHC_PRSSTAT, present_state, |
---|
| 379 | + (present_state & ESDHC_CLOCK_GATE_OFF), 2, 100); |
---|
| 380 | + if (ret == -ETIMEDOUT) |
---|
| 381 | + dev_warn(mmc_dev(host->mmc), "%s: card clock still not gate off in 100us!.\n", __func__); |
---|
264 | 382 | } |
---|
265 | 383 | |
---|
266 | 384 | static u32 esdhc_readl_le(struct sdhci_host *host, int reg) |
---|
.. | .. |
---|
306 | 424 | val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104 |
---|
307 | 425 | | SDHCI_SUPPORT_SDR50 |
---|
308 | 426 | | SDHCI_USE_SDR50_TUNING |
---|
309 | | - | (SDHCI_TUNING_MODE_3 << SDHCI_RETUNING_MODE_SHIFT); |
---|
| 427 | + | FIELD_PREP(SDHCI_RETUNING_MODE_MASK, |
---|
| 428 | + SDHCI_TUNING_MODE_3); |
---|
310 | 429 | |
---|
311 | 430 | if (imx_data->socdata->flags & ESDHC_FLAG_HS400) |
---|
312 | 431 | val |= SDHCI_SUPPORT_HS400; |
---|
.. | .. |
---|
324 | 443 | |
---|
325 | 444 | if (unlikely(reg == SDHCI_MAX_CURRENT) && esdhc_is_usdhc(imx_data)) { |
---|
326 | 445 | val = 0; |
---|
327 | | - val |= 0xFF << SDHCI_MAX_CURRENT_330_SHIFT; |
---|
328 | | - val |= 0xFF << SDHCI_MAX_CURRENT_300_SHIFT; |
---|
329 | | - val |= 0xFF << SDHCI_MAX_CURRENT_180_SHIFT; |
---|
| 446 | + val |= FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, 0xFF); |
---|
| 447 | + val |= FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, 0xFF); |
---|
| 448 | + val |= FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, 0xFF); |
---|
330 | 449 | } |
---|
331 | 450 | |
---|
332 | 451 | if (unlikely(reg == SDHCI_INT_STATUS)) { |
---|
.. | .. |
---|
476 | 595 | else |
---|
477 | 596 | new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; |
---|
478 | 597 | writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); |
---|
| 598 | + if (!(new_val & ESDHC_VENDOR_SPEC_FRC_SDCLK_ON)) |
---|
| 599 | + esdhc_wait_for_card_clock_gate_off(host); |
---|
479 | 600 | return; |
---|
480 | 601 | case SDHCI_HOST_CONTROL2: |
---|
481 | 602 | new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); |
---|
.. | .. |
---|
544 | 665 | * For DMA access restore the levels to default value. |
---|
545 | 666 | */ |
---|
546 | 667 | m = readl(host->ioaddr + ESDHC_WTMK_LVL); |
---|
547 | | - if (val & SDHCI_TRNS_DMA) |
---|
| 668 | + if (val & SDHCI_TRNS_DMA) { |
---|
548 | 669 | wml = ESDHC_WTMK_LVL_WML_VAL_DEF; |
---|
549 | | - else |
---|
| 670 | + } else { |
---|
| 671 | + u8 ctrl; |
---|
550 | 672 | wml = ESDHC_WTMK_LVL_WML_VAL_MAX; |
---|
| 673 | + |
---|
| 674 | + /* |
---|
| 675 | + * Since already disable DMA mode, so also need |
---|
| 676 | + * to clear the DMASEL. Otherwise, for standard |
---|
| 677 | + * tuning, when send tuning command, usdhc will |
---|
| 678 | + * still prefetch the ADMA script from wrong |
---|
| 679 | + * DMA address, then we will see IOMMU report |
---|
| 680 | + * some error which show lack of TLB mapping. |
---|
| 681 | + */ |
---|
| 682 | + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
---|
| 683 | + ctrl &= ~SDHCI_CTRL_DMA_MASK; |
---|
| 684 | + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); |
---|
| 685 | + } |
---|
551 | 686 | m &= ~(ESDHC_WTMK_LVL_RD_WML_MASK | |
---|
552 | 687 | ESDHC_WTMK_LVL_WR_WML_MASK); |
---|
553 | 688 | m |= (wml << ESDHC_WTMK_LVL_RD_WML_SHIFT) | |
---|
.. | .. |
---|
704 | 839 | int ddr_pre_div = imx_data->is_ddr ? 2 : 1; |
---|
705 | 840 | int pre_div = 1; |
---|
706 | 841 | int div = 1; |
---|
| 842 | + int ret; |
---|
707 | 843 | u32 temp, val; |
---|
708 | 844 | |
---|
709 | 845 | if (esdhc_is_usdhc(imx_data)) { |
---|
710 | 846 | val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); |
---|
711 | 847 | writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, |
---|
712 | 848 | host->ioaddr + ESDHC_VENDOR_SPEC); |
---|
| 849 | + esdhc_wait_for_card_clock_gate_off(host); |
---|
713 | 850 | } |
---|
714 | 851 | |
---|
715 | 852 | if (clock == 0) { |
---|
.. | .. |
---|
736 | 873 | | ESDHC_CLOCK_MASK); |
---|
737 | 874 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); |
---|
738 | 875 | |
---|
| 876 | + if ((imx_data->socdata->flags & ESDHC_FLAG_ERR010450) && |
---|
| 877 | + (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V))) { |
---|
| 878 | + unsigned int max_clock; |
---|
| 879 | + |
---|
| 880 | + max_clock = imx_data->is_ddr ? 45000000 : 150000000; |
---|
| 881 | + |
---|
| 882 | + clock = min(clock, max_clock); |
---|
| 883 | + } |
---|
| 884 | + |
---|
739 | 885 | while (host_clock / (16 * pre_div * ddr_pre_div) > clock && |
---|
740 | 886 | pre_div < 256) |
---|
741 | 887 | pre_div *= 2; |
---|
.. | .. |
---|
756 | 902 | | (pre_div << ESDHC_PREDIV_SHIFT)); |
---|
757 | 903 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); |
---|
758 | 904 | |
---|
| 905 | + /* need to wait the bit 3 of the PRSSTAT to be set, make sure card clock is stable */ |
---|
| 906 | + ret = readl_poll_timeout(host->ioaddr + ESDHC_PRSSTAT, temp, |
---|
| 907 | + (temp & ESDHC_CLOCK_STABLE), 2, 100); |
---|
| 908 | + if (ret == -ETIMEDOUT) |
---|
| 909 | + dev_warn(mmc_dev(host->mmc), "card clock still not stable in 100us!.\n"); |
---|
| 910 | + |
---|
759 | 911 | if (esdhc_is_usdhc(imx_data)) { |
---|
760 | 912 | val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); |
---|
761 | 913 | writel(val | ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, |
---|
762 | 914 | host->ioaddr + ESDHC_VENDOR_SPEC); |
---|
763 | 915 | } |
---|
764 | 916 | |
---|
765 | | - mdelay(1); |
---|
766 | 917 | } |
---|
767 | 918 | |
---|
768 | 919 | static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) |
---|
.. | .. |
---|
804 | 955 | SDHCI_HOST_CONTROL); |
---|
805 | 956 | } |
---|
806 | 957 | |
---|
| 958 | +static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) |
---|
| 959 | +{ |
---|
| 960 | + struct sdhci_host *host = mmc_priv(mmc); |
---|
| 961 | + |
---|
| 962 | + /* |
---|
| 963 | + * i.MX uSDHC internally already uses a fixed optimized timing for |
---|
| 964 | + * DDR50, normally does not require tuning for DDR50 mode. |
---|
| 965 | + */ |
---|
| 966 | + if (host->timing == MMC_TIMING_UHS_DDR50) |
---|
| 967 | + return 0; |
---|
| 968 | + |
---|
| 969 | + return sdhci_execute_tuning(mmc, opcode); |
---|
| 970 | +} |
---|
| 971 | + |
---|
807 | 972 | static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) |
---|
808 | 973 | { |
---|
809 | 974 | u32 reg; |
---|
| 975 | + u8 sw_rst; |
---|
| 976 | + int ret; |
---|
810 | 977 | |
---|
811 | 978 | /* FIXME: delay a bit for card to be ready for next tuning due to errors */ |
---|
812 | 979 | mdelay(1); |
---|
| 980 | + |
---|
| 981 | + /* IC suggest to reset USDHC before every tuning command */ |
---|
| 982 | + esdhc_clrset_le(host, 0xff, SDHCI_RESET_ALL, SDHCI_SOFTWARE_RESET); |
---|
| 983 | + ret = readb_poll_timeout(host->ioaddr + SDHCI_SOFTWARE_RESET, sw_rst, |
---|
| 984 | + !(sw_rst & SDHCI_RESET_ALL), 10, 100); |
---|
| 985 | + if (ret == -ETIMEDOUT) |
---|
| 986 | + dev_warn(mmc_dev(host->mmc), |
---|
| 987 | + "warning! RESET_ALL never complete before sending tuning command\n"); |
---|
813 | 988 | |
---|
814 | 989 | reg = readl(host->ioaddr + ESDHC_MIX_CTRL); |
---|
815 | 990 | reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | |
---|
.. | .. |
---|
867 | 1042 | return ret; |
---|
868 | 1043 | } |
---|
869 | 1044 | |
---|
| 1045 | +static void esdhc_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios) |
---|
| 1046 | +{ |
---|
| 1047 | + struct sdhci_host *host = mmc_priv(mmc); |
---|
| 1048 | + u32 m; |
---|
| 1049 | + |
---|
| 1050 | + m = readl(host->ioaddr + ESDHC_MIX_CTRL); |
---|
| 1051 | + if (ios->enhanced_strobe) |
---|
| 1052 | + m |= ESDHC_MIX_CTRL_HS400_ES_EN; |
---|
| 1053 | + else |
---|
| 1054 | + m &= ~ESDHC_MIX_CTRL_HS400_ES_EN; |
---|
| 1055 | + writel(m, host->ioaddr + ESDHC_MIX_CTRL); |
---|
| 1056 | +} |
---|
| 1057 | + |
---|
870 | 1058 | static int esdhc_change_pinstate(struct sdhci_host *host, |
---|
871 | 1059 | unsigned int uhs) |
---|
872 | 1060 | { |
---|
.. | .. |
---|
877 | 1065 | dev_dbg(mmc_dev(host->mmc), "change pinctrl state for uhs %d\n", uhs); |
---|
878 | 1066 | |
---|
879 | 1067 | if (IS_ERR(imx_data->pinctrl) || |
---|
880 | | - IS_ERR(imx_data->pins_default) || |
---|
881 | 1068 | IS_ERR(imx_data->pins_100mhz) || |
---|
882 | 1069 | IS_ERR(imx_data->pins_200mhz)) |
---|
883 | 1070 | return -EINVAL; |
---|
.. | .. |
---|
894 | 1081 | break; |
---|
895 | 1082 | default: |
---|
896 | 1083 | /* back to default state for other legacy timing */ |
---|
897 | | - pinctrl = imx_data->pins_default; |
---|
| 1084 | + return pinctrl_select_default_state(mmc_dev(host->mmc)); |
---|
898 | 1085 | } |
---|
899 | 1086 | |
---|
900 | 1087 | return pinctrl_select_state(imx_data->pinctrl, pinctrl); |
---|
.. | .. |
---|
908 | 1095 | * edge of data_strobe line. Due to the time delay between CLK line and |
---|
909 | 1096 | * data_strobe line, if the delay time is larger than one clock cycle, |
---|
910 | 1097 | * then CLK and data_strobe line will be misaligned, read error shows up. |
---|
911 | | - * So when the CLK is higher than 100MHz, each clock cycle is short enough, |
---|
912 | | - * host should configure the delay target. |
---|
913 | 1098 | */ |
---|
914 | 1099 | static void esdhc_set_strobe_dll(struct sdhci_host *host) |
---|
915 | 1100 | { |
---|
| 1101 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 1102 | + struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
---|
| 1103 | + u32 strobe_delay; |
---|
916 | 1104 | u32 v; |
---|
| 1105 | + int ret; |
---|
917 | 1106 | |
---|
918 | | - if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) { |
---|
919 | | - /* disable clock before enabling strobe dll */ |
---|
920 | | - writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) & |
---|
921 | | - ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, |
---|
922 | | - host->ioaddr + ESDHC_VENDOR_SPEC); |
---|
| 1107 | + /* disable clock before enabling strobe dll */ |
---|
| 1108 | + writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) & |
---|
| 1109 | + ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, |
---|
| 1110 | + host->ioaddr + ESDHC_VENDOR_SPEC); |
---|
| 1111 | + esdhc_wait_for_card_clock_gate_off(host); |
---|
923 | 1112 | |
---|
924 | | - /* force a reset on strobe dll */ |
---|
925 | | - writel(ESDHC_STROBE_DLL_CTRL_RESET, |
---|
926 | | - host->ioaddr + ESDHC_STROBE_DLL_CTRL); |
---|
927 | | - /* |
---|
928 | | - * enable strobe dll ctrl and adjust the delay target |
---|
929 | | - * for the uSDHC loopback read clock |
---|
930 | | - */ |
---|
931 | | - v = ESDHC_STROBE_DLL_CTRL_ENABLE | |
---|
932 | | - (7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); |
---|
933 | | - writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL); |
---|
934 | | - /* wait 1us to make sure strobe dll status register stable */ |
---|
935 | | - udelay(1); |
---|
936 | | - v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS); |
---|
937 | | - if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK)) |
---|
938 | | - dev_warn(mmc_dev(host->mmc), |
---|
939 | | - "warning! HS400 strobe DLL status REF not lock!\n"); |
---|
940 | | - if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK)) |
---|
941 | | - dev_warn(mmc_dev(host->mmc), |
---|
942 | | - "warning! HS400 strobe DLL status SLV not lock!\n"); |
---|
943 | | - } |
---|
| 1113 | + /* force a reset on strobe dll */ |
---|
| 1114 | + writel(ESDHC_STROBE_DLL_CTRL_RESET, |
---|
| 1115 | + host->ioaddr + ESDHC_STROBE_DLL_CTRL); |
---|
| 1116 | + /* clear the reset bit on strobe dll before any setting */ |
---|
| 1117 | + writel(0, host->ioaddr + ESDHC_STROBE_DLL_CTRL); |
---|
| 1118 | + |
---|
| 1119 | + /* |
---|
| 1120 | + * enable strobe dll ctrl and adjust the delay target |
---|
| 1121 | + * for the uSDHC loopback read clock |
---|
| 1122 | + */ |
---|
| 1123 | + if (imx_data->boarddata.strobe_dll_delay_target) |
---|
| 1124 | + strobe_delay = imx_data->boarddata.strobe_dll_delay_target; |
---|
| 1125 | + else |
---|
| 1126 | + strobe_delay = ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT; |
---|
| 1127 | + v = ESDHC_STROBE_DLL_CTRL_ENABLE | |
---|
| 1128 | + ESDHC_STROBE_DLL_CTRL_SLV_UPDATE_INT_DEFAULT | |
---|
| 1129 | + (strobe_delay << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); |
---|
| 1130 | + writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL); |
---|
| 1131 | + |
---|
| 1132 | + /* wait max 50us to get the REF/SLV lock */ |
---|
| 1133 | + ret = readl_poll_timeout(host->ioaddr + ESDHC_STROBE_DLL_STATUS, v, |
---|
| 1134 | + ((v & ESDHC_STROBE_DLL_STS_REF_LOCK) && (v & ESDHC_STROBE_DLL_STS_SLV_LOCK)), 1, 50); |
---|
| 1135 | + if (ret == -ETIMEDOUT) |
---|
| 1136 | + dev_warn(mmc_dev(host->mmc), |
---|
| 1137 | + "warning! HS400 strobe DLL status REF/SLV not lock in 50us, STROBE DLL status is %x!\n", v); |
---|
944 | 1138 | } |
---|
945 | 1139 | |
---|
946 | 1140 | static void esdhc_reset_tuning(struct sdhci_host *host) |
---|
.. | .. |
---|
1036 | 1230 | |
---|
1037 | 1231 | static void esdhc_reset(struct sdhci_host *host, u8 mask) |
---|
1038 | 1232 | { |
---|
1039 | | - sdhci_reset(host, mask); |
---|
| 1233 | + sdhci_and_cqhci_reset(host, mask); |
---|
1040 | 1234 | |
---|
1041 | 1235 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); |
---|
1042 | 1236 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); |
---|
.. | .. |
---|
1062 | 1256 | SDHCI_TIMEOUT_CONTROL); |
---|
1063 | 1257 | } |
---|
1064 | 1258 | |
---|
| 1259 | +static u32 esdhc_cqhci_irq(struct sdhci_host *host, u32 intmask) |
---|
| 1260 | +{ |
---|
| 1261 | + int cmd_error = 0; |
---|
| 1262 | + int data_error = 0; |
---|
| 1263 | + |
---|
| 1264 | + if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) |
---|
| 1265 | + return intmask; |
---|
| 1266 | + |
---|
| 1267 | + cqhci_irq(host->mmc, intmask, cmd_error, data_error); |
---|
| 1268 | + |
---|
| 1269 | + return 0; |
---|
| 1270 | +} |
---|
| 1271 | + |
---|
1065 | 1272 | static struct sdhci_ops sdhci_esdhc_ops = { |
---|
1066 | 1273 | .read_l = esdhc_readl_le, |
---|
1067 | 1274 | .read_w = esdhc_readw_le, |
---|
.. | .. |
---|
1078 | 1285 | .set_bus_width = esdhc_pltfm_set_bus_width, |
---|
1079 | 1286 | .set_uhs_signaling = esdhc_set_uhs_signaling, |
---|
1080 | 1287 | .reset = esdhc_reset, |
---|
| 1288 | + .irq = esdhc_cqhci_irq, |
---|
| 1289 | + .dump_vendor_regs = esdhc_dump_debug_regs, |
---|
1081 | 1290 | }; |
---|
1082 | 1291 | |
---|
1083 | 1292 | static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { |
---|
.. | .. |
---|
1092 | 1301 | { |
---|
1093 | 1302 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
1094 | 1303 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
---|
1095 | | - int tmp; |
---|
| 1304 | + struct cqhci_host *cq_host = host->mmc->cqe_private; |
---|
| 1305 | + u32 tmp; |
---|
1096 | 1306 | |
---|
1097 | 1307 | if (esdhc_is_usdhc(imx_data)) { |
---|
1098 | 1308 | /* |
---|
.. | .. |
---|
1126 | 1336 | /* disable DLL_CTRL delay line settings */ |
---|
1127 | 1337 | writel(0x0, host->ioaddr + ESDHC_DLL_CTRL); |
---|
1128 | 1338 | |
---|
| 1339 | + /* |
---|
| 1340 | + * For the case of command with busy, if set the bit |
---|
| 1341 | + * ESDHC_VEND_SPEC2_EN_BUSY_IRQ, USDHC will generate a |
---|
| 1342 | + * transfer complete interrupt when busy is deasserted. |
---|
| 1343 | + * When CQHCI use DCMD to send a CMD need R1b respons, |
---|
| 1344 | + * CQHCI require to set ESDHC_VEND_SPEC2_EN_BUSY_IRQ, |
---|
| 1345 | + * otherwise DCMD will always meet timeout waiting for |
---|
| 1346 | + * hardware interrupt issue. |
---|
| 1347 | + */ |
---|
| 1348 | + if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) { |
---|
| 1349 | + tmp = readl(host->ioaddr + ESDHC_VEND_SPEC2); |
---|
| 1350 | + tmp |= ESDHC_VEND_SPEC2_EN_BUSY_IRQ; |
---|
| 1351 | + writel(tmp, host->ioaddr + ESDHC_VEND_SPEC2); |
---|
| 1352 | + |
---|
| 1353 | + host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; |
---|
| 1354 | + } |
---|
| 1355 | + |
---|
1129 | 1356 | if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { |
---|
1130 | 1357 | tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL); |
---|
1131 | | - tmp |= ESDHC_STD_TUNING_EN | |
---|
1132 | | - ESDHC_TUNING_START_TAP_DEFAULT; |
---|
1133 | | - if (imx_data->boarddata.tuning_start_tap) { |
---|
1134 | | - tmp &= ~ESDHC_TUNING_START_TAP_MASK; |
---|
| 1358 | + tmp |= ESDHC_STD_TUNING_EN; |
---|
| 1359 | + |
---|
| 1360 | + /* |
---|
| 1361 | + * ROM code or bootloader may config the start tap |
---|
| 1362 | + * and step, unmask them first. |
---|
| 1363 | + */ |
---|
| 1364 | + tmp &= ~(ESDHC_TUNING_START_TAP_MASK | ESDHC_TUNING_STEP_MASK); |
---|
| 1365 | + if (imx_data->boarddata.tuning_start_tap) |
---|
1135 | 1366 | tmp |= imx_data->boarddata.tuning_start_tap; |
---|
1136 | | - } |
---|
| 1367 | + else |
---|
| 1368 | + tmp |= ESDHC_TUNING_START_TAP_DEFAULT; |
---|
1137 | 1369 | |
---|
1138 | 1370 | if (imx_data->boarddata.tuning_step) { |
---|
1139 | | - tmp &= ~ESDHC_TUNING_STEP_MASK; |
---|
1140 | 1371 | tmp |= imx_data->boarddata.tuning_step |
---|
1141 | 1372 | << ESDHC_TUNING_STEP_SHIFT; |
---|
| 1373 | + } else { |
---|
| 1374 | + tmp |= ESDHC_TUNING_STEP_DEFAULT |
---|
| 1375 | + << ESDHC_TUNING_STEP_SHIFT; |
---|
1142 | 1376 | } |
---|
| 1377 | + |
---|
| 1378 | + /* Disable the CMD CRC check for tuning, if not, need to |
---|
| 1379 | + * add some delay after every tuning command, because |
---|
| 1380 | + * hardware standard tuning logic will directly go to next |
---|
| 1381 | + * step once it detect the CMD CRC error, will not wait for |
---|
| 1382 | + * the card side to finally send out the tuning data, trigger |
---|
| 1383 | + * the buffer read ready interrupt immediately. If usdhc send |
---|
| 1384 | + * the next tuning command some eMMC card will stuck, can't |
---|
| 1385 | + * response, block the tuning procedure or the first command |
---|
| 1386 | + * after the whole tuning procedure always can't get any response. |
---|
| 1387 | + */ |
---|
| 1388 | + tmp |= ESDHC_TUNING_CMD_CRC_CHECK_DISABLE; |
---|
1143 | 1389 | writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL); |
---|
| 1390 | + } else if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { |
---|
| 1391 | + /* |
---|
| 1392 | + * ESDHC_STD_TUNING_EN may be configed in bootloader |
---|
| 1393 | + * or ROM code, so clear this bit here to make sure |
---|
| 1394 | + * the manual tuning can work. |
---|
| 1395 | + */ |
---|
| 1396 | + tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL); |
---|
| 1397 | + tmp &= ~ESDHC_STD_TUNING_EN; |
---|
| 1398 | + writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL); |
---|
| 1399 | + } |
---|
| 1400 | + |
---|
| 1401 | + /* |
---|
| 1402 | + * On i.MX8MM, we are running Dual Linux OS, with 1st Linux using SD Card |
---|
| 1403 | + * as rootfs storage, 2nd Linux using eMMC as rootfs storage. We let the |
---|
| 1404 | + * the 1st linux configure power/clock for the 2nd Linux. |
---|
| 1405 | + * |
---|
| 1406 | + * When the 2nd Linux is booting into rootfs stage, we let the 1st Linux |
---|
| 1407 | + * to destroy the 2nd linux, then restart the 2nd linux, we met SDHCI dump. |
---|
| 1408 | + * After we clear the pending interrupt and halt CQCTL, issue gone. |
---|
| 1409 | + */ |
---|
| 1410 | + if (cq_host) { |
---|
| 1411 | + tmp = cqhci_readl(cq_host, CQHCI_IS); |
---|
| 1412 | + cqhci_writel(cq_host, tmp, CQHCI_IS); |
---|
| 1413 | + cqhci_writel(cq_host, CQHCI_HALT, CQHCI_CTL); |
---|
1144 | 1414 | } |
---|
1145 | 1415 | } |
---|
1146 | 1416 | } |
---|
| 1417 | + |
---|
| 1418 | +static void esdhc_cqe_enable(struct mmc_host *mmc) |
---|
| 1419 | +{ |
---|
| 1420 | + struct sdhci_host *host = mmc_priv(mmc); |
---|
| 1421 | + struct cqhci_host *cq_host = mmc->cqe_private; |
---|
| 1422 | + u32 reg; |
---|
| 1423 | + u16 mode; |
---|
| 1424 | + int count = 10; |
---|
| 1425 | + |
---|
| 1426 | + /* |
---|
| 1427 | + * CQE gets stuck if it sees Buffer Read Enable bit set, which can be |
---|
| 1428 | + * the case after tuning, so ensure the buffer is drained. |
---|
| 1429 | + */ |
---|
| 1430 | + reg = sdhci_readl(host, SDHCI_PRESENT_STATE); |
---|
| 1431 | + while (reg & SDHCI_DATA_AVAILABLE) { |
---|
| 1432 | + sdhci_readl(host, SDHCI_BUFFER); |
---|
| 1433 | + reg = sdhci_readl(host, SDHCI_PRESENT_STATE); |
---|
| 1434 | + if (count-- == 0) { |
---|
| 1435 | + dev_warn(mmc_dev(host->mmc), |
---|
| 1436 | + "CQE may get stuck because the Buffer Read Enable bit is set\n"); |
---|
| 1437 | + break; |
---|
| 1438 | + } |
---|
| 1439 | + mdelay(1); |
---|
| 1440 | + } |
---|
| 1441 | + |
---|
| 1442 | + /* |
---|
| 1443 | + * Runtime resume will reset the entire host controller, which |
---|
| 1444 | + * will also clear the DMAEN/BCEN of register ESDHC_MIX_CTRL. |
---|
| 1445 | + * Here set DMAEN and BCEN when enable CMDQ. |
---|
| 1446 | + */ |
---|
| 1447 | + mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); |
---|
| 1448 | + if (host->flags & SDHCI_REQ_USE_DMA) |
---|
| 1449 | + mode |= SDHCI_TRNS_DMA; |
---|
| 1450 | + if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) |
---|
| 1451 | + mode |= SDHCI_TRNS_BLK_CNT_EN; |
---|
| 1452 | + sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); |
---|
| 1453 | + |
---|
| 1454 | + /* |
---|
| 1455 | + * Though Runtime resume reset the entire host controller, |
---|
| 1456 | + * but do not impact the CQHCI side, need to clear the |
---|
| 1457 | + * HALT bit, avoid CQHCI stuck in the first request when |
---|
| 1458 | + * system resume back. |
---|
| 1459 | + */ |
---|
| 1460 | + cqhci_writel(cq_host, 0, CQHCI_CTL); |
---|
| 1461 | + if (cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT) |
---|
| 1462 | + dev_err(mmc_dev(host->mmc), |
---|
| 1463 | + "failed to exit halt state when enable CQE\n"); |
---|
| 1464 | + |
---|
| 1465 | + |
---|
| 1466 | + sdhci_cqe_enable(mmc); |
---|
| 1467 | +} |
---|
| 1468 | + |
---|
| 1469 | +static void esdhc_sdhci_dumpregs(struct mmc_host *mmc) |
---|
| 1470 | +{ |
---|
| 1471 | + sdhci_dumpregs(mmc_priv(mmc)); |
---|
| 1472 | +} |
---|
| 1473 | + |
---|
| 1474 | +static const struct cqhci_host_ops esdhc_cqhci_ops = { |
---|
| 1475 | + .enable = esdhc_cqe_enable, |
---|
| 1476 | + .disable = sdhci_cqe_disable, |
---|
| 1477 | + .dumpregs = esdhc_sdhci_dumpregs, |
---|
| 1478 | +}; |
---|
1147 | 1479 | |
---|
1148 | 1480 | #ifdef CONFIG_OF |
---|
1149 | 1481 | static int |
---|
.. | .. |
---|
1158 | 1490 | if (of_get_property(np, "fsl,wp-controller", NULL)) |
---|
1159 | 1491 | boarddata->wp_type = ESDHC_WP_CONTROLLER; |
---|
1160 | 1492 | |
---|
1161 | | - boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); |
---|
1162 | | - if (gpio_is_valid(boarddata->wp_gpio)) |
---|
| 1493 | + /* |
---|
| 1494 | + * If we have this property, then activate WP check. |
---|
| 1495 | + * Retrieveing and requesting the actual WP GPIO will happen |
---|
| 1496 | + * in the call to mmc_of_parse(). |
---|
| 1497 | + */ |
---|
| 1498 | + if (of_property_read_bool(np, "wp-gpios")) |
---|
1163 | 1499 | boarddata->wp_type = ESDHC_WP_GPIO; |
---|
1164 | 1500 | |
---|
1165 | 1501 | of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step); |
---|
1166 | 1502 | of_property_read_u32(np, "fsl,tuning-start-tap", |
---|
1167 | 1503 | &boarddata->tuning_start_tap); |
---|
1168 | 1504 | |
---|
| 1505 | + of_property_read_u32(np, "fsl,strobe-dll-delay-target", |
---|
| 1506 | + &boarddata->strobe_dll_delay_target); |
---|
1169 | 1507 | if (of_find_property(np, "no-1-8-v", NULL)) |
---|
1170 | 1508 | host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; |
---|
1171 | 1509 | |
---|
.. | .. |
---|
1174 | 1512 | |
---|
1175 | 1513 | mmc_of_parse_voltage(np, &host->ocr_mask); |
---|
1176 | 1514 | |
---|
1177 | | - if (esdhc_is_usdhc(imx_data) && !IS_ERR(imx_data->pins_default)) { |
---|
| 1515 | + if (esdhc_is_usdhc(imx_data) && !IS_ERR(imx_data->pinctrl)) { |
---|
1178 | 1516 | imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, |
---|
1179 | 1517 | ESDHC_PINCTRL_STATE_100MHZ); |
---|
1180 | 1518 | imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, |
---|
.. | .. |
---|
1201 | 1539 | } |
---|
1202 | 1540 | #endif |
---|
1203 | 1541 | |
---|
1204 | | -static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, |
---|
1205 | | - struct sdhci_host *host, |
---|
1206 | | - struct pltfm_imx_data *imx_data) |
---|
1207 | | -{ |
---|
1208 | | - struct esdhc_platform_data *boarddata = &imx_data->boarddata; |
---|
1209 | | - int err; |
---|
1210 | | - |
---|
1211 | | - if (!host->mmc->parent->platform_data) { |
---|
1212 | | - dev_err(mmc_dev(host->mmc), "no board data!\n"); |
---|
1213 | | - return -EINVAL; |
---|
1214 | | - } |
---|
1215 | | - |
---|
1216 | | - imx_data->boarddata = *((struct esdhc_platform_data *) |
---|
1217 | | - host->mmc->parent->platform_data); |
---|
1218 | | - /* write_protect */ |
---|
1219 | | - if (boarddata->wp_type == ESDHC_WP_GPIO) { |
---|
1220 | | - err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); |
---|
1221 | | - if (err) { |
---|
1222 | | - dev_err(mmc_dev(host->mmc), |
---|
1223 | | - "failed to request write-protect gpio!\n"); |
---|
1224 | | - return err; |
---|
1225 | | - } |
---|
1226 | | - host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; |
---|
1227 | | - } |
---|
1228 | | - |
---|
1229 | | - /* card_detect */ |
---|
1230 | | - switch (boarddata->cd_type) { |
---|
1231 | | - case ESDHC_CD_GPIO: |
---|
1232 | | - err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); |
---|
1233 | | - if (err) { |
---|
1234 | | - dev_err(mmc_dev(host->mmc), |
---|
1235 | | - "failed to request card-detect gpio!\n"); |
---|
1236 | | - return err; |
---|
1237 | | - } |
---|
1238 | | - /* fall through */ |
---|
1239 | | - |
---|
1240 | | - case ESDHC_CD_CONTROLLER: |
---|
1241 | | - /* we have a working card_detect back */ |
---|
1242 | | - host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; |
---|
1243 | | - break; |
---|
1244 | | - |
---|
1245 | | - case ESDHC_CD_PERMANENT: |
---|
1246 | | - host->mmc->caps |= MMC_CAP_NONREMOVABLE; |
---|
1247 | | - break; |
---|
1248 | | - |
---|
1249 | | - case ESDHC_CD_NONE: |
---|
1250 | | - break; |
---|
1251 | | - } |
---|
1252 | | - |
---|
1253 | | - switch (boarddata->max_bus_width) { |
---|
1254 | | - case 8: |
---|
1255 | | - host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; |
---|
1256 | | - break; |
---|
1257 | | - case 4: |
---|
1258 | | - host->mmc->caps |= MMC_CAP_4_BIT_DATA; |
---|
1259 | | - break; |
---|
1260 | | - case 1: |
---|
1261 | | - default: |
---|
1262 | | - host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; |
---|
1263 | | - break; |
---|
1264 | | - } |
---|
1265 | | - |
---|
1266 | | - return 0; |
---|
1267 | | -} |
---|
1268 | | - |
---|
1269 | 1542 | static int sdhci_esdhc_imx_probe(struct platform_device *pdev) |
---|
1270 | 1543 | { |
---|
1271 | 1544 | const struct of_device_id *of_id = |
---|
1272 | 1545 | of_match_device(imx_esdhc_dt_ids, &pdev->dev); |
---|
1273 | 1546 | struct sdhci_pltfm_host *pltfm_host; |
---|
1274 | 1547 | struct sdhci_host *host; |
---|
| 1548 | + struct cqhci_host *cq_host; |
---|
1275 | 1549 | int err; |
---|
1276 | 1550 | struct pltfm_imx_data *imx_data; |
---|
1277 | 1551 | |
---|
.. | .. |
---|
1284 | 1558 | |
---|
1285 | 1559 | imx_data = sdhci_pltfm_priv(pltfm_host); |
---|
1286 | 1560 | |
---|
1287 | | - imx_data->socdata = of_id ? of_id->data : (struct esdhc_soc_data *) |
---|
1288 | | - pdev->id_entry->driver_data; |
---|
| 1561 | + imx_data->socdata = of_id->data; |
---|
| 1562 | + |
---|
| 1563 | + if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
---|
| 1564 | + cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0); |
---|
1289 | 1565 | |
---|
1290 | 1566 | imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
---|
1291 | 1567 | if (IS_ERR(imx_data->clk_ipg)) { |
---|
.. | .. |
---|
1318 | 1594 | goto disable_ipg_clk; |
---|
1319 | 1595 | |
---|
1320 | 1596 | imx_data->pinctrl = devm_pinctrl_get(&pdev->dev); |
---|
1321 | | - if (IS_ERR(imx_data->pinctrl)) { |
---|
1322 | | - err = PTR_ERR(imx_data->pinctrl); |
---|
1323 | | - goto disable_ahb_clk; |
---|
1324 | | - } |
---|
1325 | | - |
---|
1326 | | - imx_data->pins_default = pinctrl_lookup_state(imx_data->pinctrl, |
---|
1327 | | - PINCTRL_STATE_DEFAULT); |
---|
1328 | | - if (IS_ERR(imx_data->pins_default)) |
---|
1329 | | - dev_warn(mmc_dev(host->mmc), "could not get default state\n"); |
---|
| 1597 | + if (IS_ERR(imx_data->pinctrl)) |
---|
| 1598 | + dev_warn(mmc_dev(host->mmc), "could not get pinctrl\n"); |
---|
1330 | 1599 | |
---|
1331 | 1600 | if (esdhc_is_usdhc(imx_data)) { |
---|
1332 | 1601 | host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; |
---|
1333 | 1602 | host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR; |
---|
| 1603 | + |
---|
| 1604 | + /* GPIO CD can be set as a wakeup source */ |
---|
| 1605 | + host->mmc->caps |= MMC_CAP_CD_WAKE; |
---|
| 1606 | + |
---|
1334 | 1607 | if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200)) |
---|
1335 | 1608 | host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200; |
---|
1336 | 1609 | |
---|
.. | .. |
---|
1338 | 1611 | writel(0x0, host->ioaddr + ESDHC_MIX_CTRL); |
---|
1339 | 1612 | writel(0x0, host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
---|
1340 | 1613 | writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); |
---|
| 1614 | + |
---|
| 1615 | + /* |
---|
| 1616 | + * Link usdhc specific mmc_host_ops execute_tuning function, |
---|
| 1617 | + * to replace the standard one in sdhci_ops. |
---|
| 1618 | + */ |
---|
| 1619 | + host->mmc_host_ops.execute_tuning = usdhc_execute_tuning; |
---|
1341 | 1620 | } |
---|
| 1621 | + |
---|
| 1622 | + err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); |
---|
| 1623 | + if (err) |
---|
| 1624 | + goto disable_ahb_clk; |
---|
1342 | 1625 | |
---|
1343 | 1626 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) |
---|
1344 | 1627 | sdhci_esdhc_ops.platform_execute_tuning = |
---|
.. | .. |
---|
1347 | 1630 | if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) |
---|
1348 | 1631 | host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; |
---|
1349 | 1632 | |
---|
1350 | | - if (imx_data->socdata->flags & ESDHC_FLAG_HS400) |
---|
| 1633 | + if (host->mmc->caps & MMC_CAP_8_BIT_DATA && |
---|
| 1634 | + imx_data->socdata->flags & ESDHC_FLAG_HS400) |
---|
1351 | 1635 | host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400; |
---|
1352 | 1636 | |
---|
1353 | | - if (of_id) |
---|
1354 | | - err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); |
---|
1355 | | - else |
---|
1356 | | - err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data); |
---|
1357 | | - if (err) |
---|
1358 | | - goto disable_ahb_clk; |
---|
| 1637 | + if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) |
---|
| 1638 | + host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN; |
---|
| 1639 | + |
---|
| 1640 | + if (host->mmc->caps & MMC_CAP_8_BIT_DATA && |
---|
| 1641 | + imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { |
---|
| 1642 | + host->mmc->caps2 |= MMC_CAP2_HS400_ES; |
---|
| 1643 | + host->mmc_host_ops.hs400_enhanced_strobe = |
---|
| 1644 | + esdhc_hs400_enhanced_strobe; |
---|
| 1645 | + } |
---|
| 1646 | + |
---|
| 1647 | + if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) { |
---|
| 1648 | + host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; |
---|
| 1649 | + cq_host = devm_kzalloc(&pdev->dev, sizeof(*cq_host), GFP_KERNEL); |
---|
| 1650 | + if (!cq_host) { |
---|
| 1651 | + err = -ENOMEM; |
---|
| 1652 | + goto disable_ahb_clk; |
---|
| 1653 | + } |
---|
| 1654 | + |
---|
| 1655 | + cq_host->mmio = host->ioaddr + ESDHC_CQHCI_ADDR_OFFSET; |
---|
| 1656 | + cq_host->ops = &esdhc_cqhci_ops; |
---|
| 1657 | + |
---|
| 1658 | + err = cqhci_init(cq_host, host->mmc, false); |
---|
| 1659 | + if (err) |
---|
| 1660 | + goto disable_ahb_clk; |
---|
| 1661 | + } |
---|
1359 | 1662 | |
---|
1360 | 1663 | sdhci_esdhc_imx_hwinit(host); |
---|
1361 | 1664 | |
---|
.. | .. |
---|
1378 | 1681 | disable_per_clk: |
---|
1379 | 1682 | clk_disable_unprepare(imx_data->clk_per); |
---|
1380 | 1683 | free_sdhci: |
---|
| 1684 | + if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
---|
| 1685 | + cpu_latency_qos_remove_request(&imx_data->pm_qos_req); |
---|
1381 | 1686 | sdhci_pltfm_free(pdev); |
---|
1382 | 1687 | return err; |
---|
1383 | 1688 | } |
---|
.. | .. |
---|
1400 | 1705 | clk_disable_unprepare(imx_data->clk_ipg); |
---|
1401 | 1706 | clk_disable_unprepare(imx_data->clk_ahb); |
---|
1402 | 1707 | |
---|
| 1708 | + if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
---|
| 1709 | + cpu_latency_qos_remove_request(&imx_data->pm_qos_req); |
---|
| 1710 | + |
---|
1403 | 1711 | sdhci_pltfm_free(pdev); |
---|
1404 | 1712 | |
---|
1405 | 1713 | return 0; |
---|
.. | .. |
---|
1409 | 1717 | static int sdhci_esdhc_suspend(struct device *dev) |
---|
1410 | 1718 | { |
---|
1411 | 1719 | struct sdhci_host *host = dev_get_drvdata(dev); |
---|
| 1720 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 1721 | + struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
---|
| 1722 | + int ret; |
---|
| 1723 | + |
---|
| 1724 | + if (host->mmc->caps2 & MMC_CAP2_CQE) { |
---|
| 1725 | + ret = cqhci_suspend(host->mmc); |
---|
| 1726 | + if (ret) |
---|
| 1727 | + return ret; |
---|
| 1728 | + } |
---|
| 1729 | + |
---|
| 1730 | + if ((imx_data->socdata->flags & ESDHC_FLAG_STATE_LOST_IN_LPMODE) && |
---|
| 1731 | + (host->tuning_mode != SDHCI_TUNING_MODE_1)) { |
---|
| 1732 | + mmc_retune_timer_stop(host->mmc); |
---|
| 1733 | + mmc_retune_needed(host->mmc); |
---|
| 1734 | + } |
---|
1412 | 1735 | |
---|
1413 | 1736 | if (host->tuning_mode != SDHCI_TUNING_MODE_3) |
---|
1414 | 1737 | mmc_retune_needed(host->mmc); |
---|
1415 | 1738 | |
---|
1416 | | - return sdhci_suspend_host(host); |
---|
| 1739 | + ret = sdhci_suspend_host(host); |
---|
| 1740 | + if (ret) |
---|
| 1741 | + return ret; |
---|
| 1742 | + |
---|
| 1743 | + ret = pinctrl_pm_select_sleep_state(dev); |
---|
| 1744 | + if (ret) |
---|
| 1745 | + return ret; |
---|
| 1746 | + |
---|
| 1747 | + ret = mmc_gpio_set_cd_wake(host->mmc, true); |
---|
| 1748 | + |
---|
| 1749 | + return ret; |
---|
1417 | 1750 | } |
---|
1418 | 1751 | |
---|
1419 | 1752 | static int sdhci_esdhc_resume(struct device *dev) |
---|
1420 | 1753 | { |
---|
1421 | 1754 | struct sdhci_host *host = dev_get_drvdata(dev); |
---|
| 1755 | + int ret; |
---|
| 1756 | + |
---|
| 1757 | + ret = pinctrl_pm_select_default_state(dev); |
---|
| 1758 | + if (ret) |
---|
| 1759 | + return ret; |
---|
1422 | 1760 | |
---|
1423 | 1761 | /* re-initialize hw state in case it's lost in low power mode */ |
---|
1424 | 1762 | sdhci_esdhc_imx_hwinit(host); |
---|
1425 | 1763 | |
---|
1426 | | - return sdhci_resume_host(host); |
---|
| 1764 | + ret = sdhci_resume_host(host); |
---|
| 1765 | + if (ret) |
---|
| 1766 | + return ret; |
---|
| 1767 | + |
---|
| 1768 | + if (host->mmc->caps2 & MMC_CAP2_CQE) |
---|
| 1769 | + ret = cqhci_resume(host->mmc); |
---|
| 1770 | + |
---|
| 1771 | + if (!ret) |
---|
| 1772 | + ret = mmc_gpio_set_cd_wake(host->mmc, false); |
---|
| 1773 | + |
---|
| 1774 | + return ret; |
---|
1427 | 1775 | } |
---|
1428 | 1776 | #endif |
---|
1429 | 1777 | |
---|
.. | .. |
---|
1435 | 1783 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
---|
1436 | 1784 | int ret; |
---|
1437 | 1785 | |
---|
| 1786 | + if (host->mmc->caps2 & MMC_CAP2_CQE) { |
---|
| 1787 | + ret = cqhci_suspend(host->mmc); |
---|
| 1788 | + if (ret) |
---|
| 1789 | + return ret; |
---|
| 1790 | + } |
---|
| 1791 | + |
---|
1438 | 1792 | ret = sdhci_runtime_suspend_host(host); |
---|
1439 | 1793 | if (ret) |
---|
1440 | 1794 | return ret; |
---|
.. | .. |
---|
1442 | 1796 | if (host->tuning_mode != SDHCI_TUNING_MODE_3) |
---|
1443 | 1797 | mmc_retune_needed(host->mmc); |
---|
1444 | 1798 | |
---|
1445 | | - if (!sdhci_sdio_irq_enabled(host)) { |
---|
1446 | | - imx_data->actual_clock = host->mmc->actual_clock; |
---|
1447 | | - esdhc_pltfm_set_clock(host, 0); |
---|
1448 | | - clk_disable_unprepare(imx_data->clk_per); |
---|
1449 | | - clk_disable_unprepare(imx_data->clk_ipg); |
---|
1450 | | - } |
---|
| 1799 | + imx_data->actual_clock = host->mmc->actual_clock; |
---|
| 1800 | + esdhc_pltfm_set_clock(host, 0); |
---|
| 1801 | + clk_disable_unprepare(imx_data->clk_per); |
---|
| 1802 | + clk_disable_unprepare(imx_data->clk_ipg); |
---|
1451 | 1803 | clk_disable_unprepare(imx_data->clk_ahb); |
---|
| 1804 | + |
---|
| 1805 | + if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
---|
| 1806 | + cpu_latency_qos_remove_request(&imx_data->pm_qos_req); |
---|
1452 | 1807 | |
---|
1453 | 1808 | return ret; |
---|
1454 | 1809 | } |
---|
.. | .. |
---|
1460 | 1815 | struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); |
---|
1461 | 1816 | int err; |
---|
1462 | 1817 | |
---|
| 1818 | + if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
---|
| 1819 | + cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0); |
---|
| 1820 | + |
---|
| 1821 | + if (imx_data->socdata->flags & ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME) |
---|
| 1822 | + clk_set_rate(imx_data->clk_per, pltfm_host->clock); |
---|
| 1823 | + |
---|
1463 | 1824 | err = clk_prepare_enable(imx_data->clk_ahb); |
---|
1464 | 1825 | if (err) |
---|
1465 | | - return err; |
---|
| 1826 | + goto remove_pm_qos_request; |
---|
1466 | 1827 | |
---|
1467 | | - if (!sdhci_sdio_irq_enabled(host)) { |
---|
1468 | | - err = clk_prepare_enable(imx_data->clk_per); |
---|
1469 | | - if (err) |
---|
1470 | | - goto disable_ahb_clk; |
---|
1471 | | - err = clk_prepare_enable(imx_data->clk_ipg); |
---|
1472 | | - if (err) |
---|
1473 | | - goto disable_per_clk; |
---|
1474 | | - esdhc_pltfm_set_clock(host, imx_data->actual_clock); |
---|
1475 | | - } |
---|
| 1828 | + err = clk_prepare_enable(imx_data->clk_per); |
---|
| 1829 | + if (err) |
---|
| 1830 | + goto disable_ahb_clk; |
---|
1476 | 1831 | |
---|
1477 | | - err = sdhci_runtime_resume_host(host); |
---|
| 1832 | + err = clk_prepare_enable(imx_data->clk_ipg); |
---|
| 1833 | + if (err) |
---|
| 1834 | + goto disable_per_clk; |
---|
| 1835 | + |
---|
| 1836 | + esdhc_pltfm_set_clock(host, imx_data->actual_clock); |
---|
| 1837 | + |
---|
| 1838 | + err = sdhci_runtime_resume_host(host, 0); |
---|
1478 | 1839 | if (err) |
---|
1479 | 1840 | goto disable_ipg_clk; |
---|
1480 | 1841 | |
---|
1481 | | - return 0; |
---|
| 1842 | + if (host->mmc->caps2 & MMC_CAP2_CQE) |
---|
| 1843 | + err = cqhci_resume(host->mmc); |
---|
| 1844 | + |
---|
| 1845 | + return err; |
---|
1482 | 1846 | |
---|
1483 | 1847 | disable_ipg_clk: |
---|
1484 | | - if (!sdhci_sdio_irq_enabled(host)) |
---|
1485 | | - clk_disable_unprepare(imx_data->clk_ipg); |
---|
| 1848 | + clk_disable_unprepare(imx_data->clk_ipg); |
---|
1486 | 1849 | disable_per_clk: |
---|
1487 | | - if (!sdhci_sdio_irq_enabled(host)) |
---|
1488 | | - clk_disable_unprepare(imx_data->clk_per); |
---|
| 1850 | + clk_disable_unprepare(imx_data->clk_per); |
---|
1489 | 1851 | disable_ahb_clk: |
---|
1490 | 1852 | clk_disable_unprepare(imx_data->clk_ahb); |
---|
| 1853 | +remove_pm_qos_request: |
---|
| 1854 | + if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) |
---|
| 1855 | + cpu_latency_qos_remove_request(&imx_data->pm_qos_req); |
---|
1491 | 1856 | return err; |
---|
1492 | 1857 | } |
---|
1493 | 1858 | #endif |
---|
.. | .. |
---|
1501 | 1866 | static struct platform_driver sdhci_esdhc_imx_driver = { |
---|
1502 | 1867 | .driver = { |
---|
1503 | 1868 | .name = "sdhci-esdhc-imx", |
---|
| 1869 | + .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
---|
1504 | 1870 | .of_match_table = imx_esdhc_dt_ids, |
---|
1505 | 1871 | .pm = &sdhci_esdhc_pmops, |
---|
1506 | 1872 | }, |
---|
1507 | | - .id_table = imx_esdhc_devtype, |
---|
1508 | 1873 | .probe = sdhci_esdhc_imx_probe, |
---|
1509 | 1874 | .remove = sdhci_esdhc_imx_remove, |
---|
1510 | 1875 | }; |
---|