.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * drivers/mmc/host/sdhci-msm.c - Qualcomm SDHCI Platform driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 and |
---|
8 | | - * only version 2 as published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | | - * GNU General Public License for more details. |
---|
14 | | - * |
---|
15 | 6 | */ |
---|
16 | 7 | |
---|
17 | 8 | #include <linux/module.h> |
---|
.. | .. |
---|
19 | 10 | #include <linux/delay.h> |
---|
20 | 11 | #include <linux/mmc/mmc.h> |
---|
21 | 12 | #include <linux/pm_runtime.h> |
---|
| 13 | +#include <linux/pm_opp.h> |
---|
22 | 14 | #include <linux/slab.h> |
---|
23 | 15 | #include <linux/iopoll.h> |
---|
| 16 | +#include <linux/qcom_scm.h> |
---|
24 | 17 | #include <linux/regulator/consumer.h> |
---|
| 18 | +#include <linux/interconnect.h> |
---|
| 19 | +#include <linux/pinctrl/consumer.h> |
---|
| 20 | +#include <linux/reset.h> |
---|
25 | 21 | |
---|
26 | 22 | #include "sdhci-pltfm.h" |
---|
| 23 | +#include "cqhci.h" |
---|
27 | 24 | |
---|
28 | 25 | #define CORE_MCI_VERSION 0x50 |
---|
29 | 26 | #define CORE_VERSION_MAJOR_SHIFT 28 |
---|
.. | .. |
---|
43 | 40 | #define CORE_PWRCTL_IO_LOW BIT(2) |
---|
44 | 41 | #define CORE_PWRCTL_IO_HIGH BIT(3) |
---|
45 | 42 | #define CORE_PWRCTL_BUS_SUCCESS BIT(0) |
---|
| 43 | +#define CORE_PWRCTL_BUS_FAIL BIT(1) |
---|
46 | 44 | #define CORE_PWRCTL_IO_SUCCESS BIT(2) |
---|
| 45 | +#define CORE_PWRCTL_IO_FAIL BIT(3) |
---|
47 | 46 | #define REQ_BUS_OFF BIT(0) |
---|
48 | 47 | #define REQ_BUS_ON BIT(1) |
---|
49 | 48 | #define REQ_IO_LOW BIT(2) |
---|
.. | .. |
---|
64 | 63 | #define CORE_FLL_CYCLE_CNT BIT(18) |
---|
65 | 64 | #define CORE_DLL_CLOCK_DISABLE BIT(21) |
---|
66 | 65 | |
---|
67 | | -#define CORE_VENDOR_SPEC_POR_VAL 0xa1c |
---|
| 66 | +#define DLL_USR_CTL_POR_VAL 0x10800 |
---|
| 67 | +#define ENABLE_DLL_LOCK_STATUS BIT(26) |
---|
| 68 | +#define FINE_TUNE_MODE_EN BIT(27) |
---|
| 69 | +#define BIAS_OK_SIGNAL BIT(29) |
---|
| 70 | + |
---|
| 71 | +#define DLL_CONFIG_3_LOW_FREQ_VAL 0x08 |
---|
| 72 | +#define DLL_CONFIG_3_HIGH_FREQ_VAL 0x10 |
---|
| 73 | + |
---|
| 74 | +#define CORE_VENDOR_SPEC_POR_VAL 0xa9c |
---|
68 | 75 | #define CORE_CLK_PWRSAVE BIT(1) |
---|
69 | 76 | #define CORE_HC_MCLK_SEL_DFLT (2 << 8) |
---|
70 | 77 | #define CORE_HC_MCLK_SEL_HS400 (3 << 8) |
---|
71 | 78 | #define CORE_HC_MCLK_SEL_MASK (3 << 8) |
---|
72 | | -#define CORE_IO_PAD_PWR_SWITCH_EN (1 << 15) |
---|
73 | | -#define CORE_IO_PAD_PWR_SWITCH (1 << 16) |
---|
| 79 | +#define CORE_IO_PAD_PWR_SWITCH_EN BIT(15) |
---|
| 80 | +#define CORE_IO_PAD_PWR_SWITCH BIT(16) |
---|
74 | 81 | #define CORE_HC_SELECT_IN_EN BIT(18) |
---|
75 | 82 | #define CORE_HC_SELECT_IN_HS400 (6 << 19) |
---|
76 | 83 | #define CORE_HC_SELECT_IN_MASK (7 << 19) |
---|
77 | 84 | |
---|
78 | | -#define CORE_3_0V_SUPPORT (1 << 25) |
---|
79 | | -#define CORE_1_8V_SUPPORT (1 << 26) |
---|
| 85 | +#define CORE_3_0V_SUPPORT BIT(25) |
---|
| 86 | +#define CORE_1_8V_SUPPORT BIT(26) |
---|
80 | 87 | #define CORE_VOLT_SUPPORT (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT) |
---|
81 | 88 | |
---|
82 | 89 | #define CORE_CSR_CDC_CTLR_CFG0 0x130 |
---|
.. | .. |
---|
125 | 132 | /* Timeout value to avoid infinite waiting for pwr_irq */ |
---|
126 | 133 | #define MSM_PWR_IRQ_TIMEOUT_MS 5000 |
---|
127 | 134 | |
---|
| 135 | +/* Max load for eMMC Vdd-io supply */ |
---|
| 136 | +#define MMC_VQMMC_MAX_LOAD_UA 325000 |
---|
| 137 | + |
---|
128 | 138 | #define msm_host_readl(msm_host, host, offset) \ |
---|
129 | 139 | msm_host->var_ops->msm_readl_relaxed(host, offset) |
---|
130 | 140 | |
---|
131 | 141 | #define msm_host_writel(msm_host, val, host, offset) \ |
---|
132 | 142 | msm_host->var_ops->msm_writel_relaxed(val, host, offset) |
---|
| 143 | + |
---|
| 144 | +/* CQHCI vendor specific registers */ |
---|
| 145 | +#define CQHCI_VENDOR_CFG1 0xA00 |
---|
| 146 | +#define CQHCI_VENDOR_DIS_RST_ON_CQ_EN (0x3 << 13) |
---|
133 | 147 | |
---|
134 | 148 | struct sdhci_msm_offset { |
---|
135 | 149 | u32 core_hc_mode; |
---|
.. | .. |
---|
160 | 174 | u32 core_dll_config_3; |
---|
161 | 175 | u32 core_ddr_config_old; /* Applicable to sdcc minor ver < 0x49 */ |
---|
162 | 176 | u32 core_ddr_config; |
---|
| 177 | + u32 core_dll_usr_ctl; /* Present on SDCC5.1 onwards */ |
---|
163 | 178 | }; |
---|
164 | 179 | |
---|
165 | 180 | static const struct sdhci_msm_offset sdhci_msm_v5_offset = { |
---|
.. | .. |
---|
189 | 204 | .core_dll_config_2 = 0x254, |
---|
190 | 205 | .core_dll_config_3 = 0x258, |
---|
191 | 206 | .core_ddr_config = 0x25c, |
---|
| 207 | + .core_dll_usr_ctl = 0x388, |
---|
192 | 208 | }; |
---|
193 | 209 | |
---|
194 | 210 | static const struct sdhci_msm_offset sdhci_msm_mci_offset = { |
---|
.. | .. |
---|
233 | 249 | */ |
---|
234 | 250 | struct sdhci_msm_variant_info { |
---|
235 | 251 | bool mci_removed; |
---|
| 252 | + bool restore_dll_config; |
---|
| 253 | + bool uses_tassadar_dll; |
---|
236 | 254 | const struct sdhci_msm_variant_ops *var_ops; |
---|
237 | 255 | const struct sdhci_msm_offset *offset; |
---|
238 | 256 | }; |
---|
.. | .. |
---|
240 | 258 | struct sdhci_msm_host { |
---|
241 | 259 | struct platform_device *pdev; |
---|
242 | 260 | void __iomem *core_mem; /* MSM SDCC mapped address */ |
---|
| 261 | + void __iomem *ice_mem; /* MSM ICE mapped address (if available) */ |
---|
243 | 262 | int pwr_irq; /* power irq */ |
---|
244 | 263 | struct clk *bus_clk; /* SDHC bus voter clock */ |
---|
245 | 264 | struct clk *xo_clk; /* TCXO clk needed for FLL feature of cm_dll*/ |
---|
246 | | - struct clk_bulk_data bulk_clks[4]; /* core, iface, cal, sleep clocks */ |
---|
| 265 | + /* core, iface, cal, sleep, and ice clocks */ |
---|
| 266 | + struct clk_bulk_data bulk_clks[5]; |
---|
247 | 267 | unsigned long clk_rate; |
---|
248 | 268 | struct mmc_host *mmc; |
---|
| 269 | + struct opp_table *opp_table; |
---|
249 | 270 | bool use_14lpp_dll_reset; |
---|
250 | 271 | bool tuning_done; |
---|
251 | 272 | bool calibration_done; |
---|
.. | .. |
---|
257 | 278 | bool pwr_irq_flag; |
---|
258 | 279 | u32 caps_0; |
---|
259 | 280 | bool mci_removed; |
---|
| 281 | + bool restore_dll_config; |
---|
260 | 282 | const struct sdhci_msm_variant_ops *var_ops; |
---|
261 | 283 | const struct sdhci_msm_offset *offset; |
---|
262 | 284 | bool use_cdr; |
---|
263 | 285 | u32 transfer_mode; |
---|
264 | 286 | bool updated_ddr_cfg; |
---|
| 287 | + bool uses_tassadar_dll; |
---|
| 288 | + u32 dll_config; |
---|
| 289 | + u32 ddr_config; |
---|
| 290 | + bool vqmmc_enabled; |
---|
265 | 291 | }; |
---|
266 | 292 | |
---|
267 | 293 | static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host) |
---|
.. | .. |
---|
334 | 360 | int rc; |
---|
335 | 361 | |
---|
336 | 362 | clock = msm_get_clock_rate_for_bus_mode(host, clock); |
---|
337 | | - rc = clk_set_rate(core_clk, clock); |
---|
| 363 | + rc = dev_pm_opp_set_rate(mmc_dev(host->mmc), clock); |
---|
338 | 364 | if (rc) { |
---|
339 | 365 | pr_err("%s: Failed to set clock at rate %u at timing %d\n", |
---|
340 | 366 | mmc_hostname(host->mmc), clock, |
---|
.. | .. |
---|
603 | 629 | config &= ~CORE_CLK_PWRSAVE; |
---|
604 | 630 | writel_relaxed(config, host->ioaddr + msm_offset->core_vendor_spec); |
---|
605 | 631 | |
---|
| 632 | + if (msm_host->dll_config) |
---|
| 633 | + writel_relaxed(msm_host->dll_config, |
---|
| 634 | + host->ioaddr + msm_offset->core_dll_config); |
---|
| 635 | + |
---|
606 | 636 | if (msm_host->use_14lpp_dll_reset) { |
---|
607 | 637 | config = readl_relaxed(host->ioaddr + |
---|
608 | 638 | msm_offset->core_dll_config); |
---|
.. | .. |
---|
628 | 658 | config |= CORE_DLL_PDN; |
---|
629 | 659 | writel_relaxed(config, host->ioaddr + |
---|
630 | 660 | msm_offset->core_dll_config); |
---|
631 | | - msm_cm_dll_set_freq(host); |
---|
| 661 | + |
---|
| 662 | + if (!msm_host->dll_config) |
---|
| 663 | + msm_cm_dll_set_freq(host); |
---|
632 | 664 | |
---|
633 | 665 | if (msm_host->use_14lpp_dll_reset && |
---|
634 | 666 | !IS_ERR_OR_NULL(msm_host->xo_clk)) { |
---|
.. | .. |
---|
668 | 700 | msm_offset->core_dll_config); |
---|
669 | 701 | |
---|
670 | 702 | if (msm_host->use_14lpp_dll_reset) { |
---|
671 | | - msm_cm_dll_set_freq(host); |
---|
| 703 | + if (!msm_host->dll_config) |
---|
| 704 | + msm_cm_dll_set_freq(host); |
---|
672 | 705 | config = readl_relaxed(host->ioaddr + |
---|
673 | 706 | msm_offset->core_dll_config_2); |
---|
674 | 707 | config &= ~CORE_DLL_CLOCK_DISABLE; |
---|
675 | 708 | writel_relaxed(config, host->ioaddr + |
---|
676 | 709 | msm_offset->core_dll_config_2); |
---|
| 710 | + } |
---|
| 711 | + |
---|
| 712 | + /* |
---|
| 713 | + * Configure DLL user control register to enable DLL status. |
---|
| 714 | + * This setting is applicable to SDCC v5.1 onwards only. |
---|
| 715 | + */ |
---|
| 716 | + if (msm_host->uses_tassadar_dll) { |
---|
| 717 | + config = DLL_USR_CTL_POR_VAL | FINE_TUNE_MODE_EN | |
---|
| 718 | + ENABLE_DLL_LOCK_STATUS | BIAS_OK_SIGNAL; |
---|
| 719 | + writel_relaxed(config, host->ioaddr + |
---|
| 720 | + msm_offset->core_dll_usr_ctl); |
---|
| 721 | + |
---|
| 722 | + config = readl_relaxed(host->ioaddr + |
---|
| 723 | + msm_offset->core_dll_config_3); |
---|
| 724 | + config &= ~0xFF; |
---|
| 725 | + if (msm_host->clk_rate < 150000000) |
---|
| 726 | + config |= DLL_CONFIG_3_LOW_FREQ_VAL; |
---|
| 727 | + else |
---|
| 728 | + config |= DLL_CONFIG_3_HIGH_FREQ_VAL; |
---|
| 729 | + writel_relaxed(config, host->ioaddr + |
---|
| 730 | + msm_offset->core_dll_config_3); |
---|
677 | 731 | } |
---|
678 | 732 | |
---|
679 | 733 | config = readl_relaxed(host->ioaddr + |
---|
.. | .. |
---|
953 | 1007 | ddr_cfg_offset = msm_offset->core_ddr_config; |
---|
954 | 1008 | else |
---|
955 | 1009 | ddr_cfg_offset = msm_offset->core_ddr_config_old; |
---|
956 | | - writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + ddr_cfg_offset); |
---|
| 1010 | + writel_relaxed(msm_host->ddr_config, host->ioaddr + ddr_cfg_offset); |
---|
957 | 1011 | |
---|
958 | 1012 | if (mmc->ios.enhanced_strobe) { |
---|
959 | 1013 | config = readl_relaxed(host->ioaddr + |
---|
.. | .. |
---|
979 | 1033 | goto out; |
---|
980 | 1034 | } |
---|
981 | 1035 | |
---|
982 | | - config = readl_relaxed(host->ioaddr + msm_offset->core_vendor_spec3); |
---|
983 | | - config |= CORE_PWRSAVE_DLL; |
---|
984 | | - writel_relaxed(config, host->ioaddr + msm_offset->core_vendor_spec3); |
---|
| 1036 | + /* |
---|
| 1037 | + * Set CORE_PWRSAVE_DLL bit in CORE_VENDOR_SPEC3. |
---|
| 1038 | + * When MCLK is gated OFF, it is not gated for less than 0.5us |
---|
| 1039 | + * and MCLK must be switched on for at-least 1us before DATA |
---|
| 1040 | + * starts coming. Controllers with 14lpp and later tech DLL cannot |
---|
| 1041 | + * guarantee above requirement. So PWRSAVE_DLL should not be |
---|
| 1042 | + * turned on for host controllers using this DLL. |
---|
| 1043 | + */ |
---|
| 1044 | + if (!msm_host->use_14lpp_dll_reset) { |
---|
| 1045 | + config = readl_relaxed(host->ioaddr + |
---|
| 1046 | + msm_offset->core_vendor_spec3); |
---|
| 1047 | + config |= CORE_PWRSAVE_DLL; |
---|
| 1048 | + writel_relaxed(config, host->ioaddr + |
---|
| 1049 | + msm_offset->core_vendor_spec3); |
---|
| 1050 | + } |
---|
985 | 1051 | |
---|
986 | 1052 | /* |
---|
987 | 1053 | * Drain writebuffer to ensure above DLL calibration |
---|
.. | .. |
---|
1037 | 1103 | return ret; |
---|
1038 | 1104 | } |
---|
1039 | 1105 | |
---|
| 1106 | +static bool sdhci_msm_is_tuning_needed(struct sdhci_host *host) |
---|
| 1107 | +{ |
---|
| 1108 | + struct mmc_ios *ios = &host->mmc->ios; |
---|
| 1109 | + |
---|
| 1110 | + /* |
---|
| 1111 | + * Tuning is required for SDR104, HS200 and HS400 cards and |
---|
| 1112 | + * if clock frequency is greater than 100MHz in these modes. |
---|
| 1113 | + */ |
---|
| 1114 | + if (host->clock <= CORE_FREQ_100MHZ || |
---|
| 1115 | + !(ios->timing == MMC_TIMING_MMC_HS400 || |
---|
| 1116 | + ios->timing == MMC_TIMING_MMC_HS200 || |
---|
| 1117 | + ios->timing == MMC_TIMING_UHS_SDR104) || |
---|
| 1118 | + ios->enhanced_strobe) |
---|
| 1119 | + return false; |
---|
| 1120 | + |
---|
| 1121 | + return true; |
---|
| 1122 | +} |
---|
| 1123 | + |
---|
| 1124 | +static int sdhci_msm_restore_sdr_dll_config(struct sdhci_host *host) |
---|
| 1125 | +{ |
---|
| 1126 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 1127 | + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
---|
| 1128 | + int ret; |
---|
| 1129 | + |
---|
| 1130 | + /* |
---|
| 1131 | + * SDR DLL comes into picture only for timing modes which needs |
---|
| 1132 | + * tuning. |
---|
| 1133 | + */ |
---|
| 1134 | + if (!sdhci_msm_is_tuning_needed(host)) |
---|
| 1135 | + return 0; |
---|
| 1136 | + |
---|
| 1137 | + /* Reset the tuning block */ |
---|
| 1138 | + ret = msm_init_cm_dll(host); |
---|
| 1139 | + if (ret) |
---|
| 1140 | + return ret; |
---|
| 1141 | + |
---|
| 1142 | + /* Restore the tuning block */ |
---|
| 1143 | + ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase); |
---|
| 1144 | + |
---|
| 1145 | + return ret; |
---|
| 1146 | +} |
---|
| 1147 | + |
---|
1040 | 1148 | static void sdhci_msm_set_cdr(struct sdhci_host *host, bool enable) |
---|
1041 | 1149 | { |
---|
1042 | 1150 | const struct sdhci_msm_offset *msm_offset = sdhci_priv_msm_offset(host); |
---|
.. | .. |
---|
1052 | 1160 | config |= CORE_CDR_EXT_EN; |
---|
1053 | 1161 | } |
---|
1054 | 1162 | |
---|
1055 | | - if (config != oldconfig) |
---|
| 1163 | + if (config != oldconfig) { |
---|
1056 | 1164 | writel_relaxed(config, host->ioaddr + |
---|
1057 | 1165 | msm_offset->core_dll_config); |
---|
| 1166 | + } |
---|
1058 | 1167 | } |
---|
1059 | 1168 | |
---|
1060 | 1169 | static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode) |
---|
.. | .. |
---|
1067 | 1176 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
1068 | 1177 | struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
---|
1069 | 1178 | |
---|
1070 | | - /* |
---|
1071 | | - * Tuning is required for SDR104, HS200 and HS400 cards and |
---|
1072 | | - * if clock frequency is greater than 100MHz in these modes. |
---|
1073 | | - */ |
---|
1074 | | - if (host->clock <= CORE_FREQ_100MHZ || |
---|
1075 | | - !(ios.timing == MMC_TIMING_MMC_HS400 || |
---|
1076 | | - ios.timing == MMC_TIMING_MMC_HS200 || |
---|
1077 | | - ios.timing == MMC_TIMING_UHS_SDR104)) { |
---|
| 1179 | + if (!sdhci_msm_is_tuning_needed(host)) { |
---|
1078 | 1180 | msm_host->use_cdr = false; |
---|
1079 | 1181 | sdhci_msm_set_cdr(host, false); |
---|
1080 | 1182 | return 0; |
---|
.. | .. |
---|
1113 | 1215 | if (rc) |
---|
1114 | 1216 | return rc; |
---|
1115 | 1217 | |
---|
1116 | | - msm_host->saved_tuning_phase = phase; |
---|
1117 | 1218 | rc = mmc_send_tuning(mmc, opcode, NULL); |
---|
1118 | 1219 | if (!rc) { |
---|
1119 | 1220 | /* Tuning is successful at this tuning point */ |
---|
.. | .. |
---|
1154 | 1255 | rc = msm_config_cm_dll_phase(host, phase); |
---|
1155 | 1256 | if (rc) |
---|
1156 | 1257 | return rc; |
---|
| 1258 | + msm_host->saved_tuning_phase = phase; |
---|
1157 | 1259 | dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", |
---|
1158 | 1260 | mmc_hostname(mmc), phase); |
---|
1159 | 1261 | } else { |
---|
.. | .. |
---|
1271 | 1373 | sdhci_msm_hs400(host, &mmc->ios); |
---|
1272 | 1374 | } |
---|
1273 | 1375 | |
---|
| 1376 | +static int sdhci_msm_set_pincfg(struct sdhci_msm_host *msm_host, bool level) |
---|
| 1377 | +{ |
---|
| 1378 | + struct platform_device *pdev = msm_host->pdev; |
---|
| 1379 | + int ret; |
---|
| 1380 | + |
---|
| 1381 | + if (level) |
---|
| 1382 | + ret = pinctrl_pm_select_default_state(&pdev->dev); |
---|
| 1383 | + else |
---|
| 1384 | + ret = pinctrl_pm_select_sleep_state(&pdev->dev); |
---|
| 1385 | + |
---|
| 1386 | + return ret; |
---|
| 1387 | +} |
---|
| 1388 | + |
---|
| 1389 | +static int sdhci_msm_set_vmmc(struct mmc_host *mmc) |
---|
| 1390 | +{ |
---|
| 1391 | + if (IS_ERR(mmc->supply.vmmc)) |
---|
| 1392 | + return 0; |
---|
| 1393 | + |
---|
| 1394 | + return mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, mmc->ios.vdd); |
---|
| 1395 | +} |
---|
| 1396 | + |
---|
| 1397 | +static int msm_toggle_vqmmc(struct sdhci_msm_host *msm_host, |
---|
| 1398 | + struct mmc_host *mmc, bool level) |
---|
| 1399 | +{ |
---|
| 1400 | + int ret; |
---|
| 1401 | + struct mmc_ios ios; |
---|
| 1402 | + |
---|
| 1403 | + if (msm_host->vqmmc_enabled == level) |
---|
| 1404 | + return 0; |
---|
| 1405 | + |
---|
| 1406 | + if (level) { |
---|
| 1407 | + /* Set the IO voltage regulator to default voltage level */ |
---|
| 1408 | + if (msm_host->caps_0 & CORE_3_0V_SUPPORT) |
---|
| 1409 | + ios.signal_voltage = MMC_SIGNAL_VOLTAGE_330; |
---|
| 1410 | + else if (msm_host->caps_0 & CORE_1_8V_SUPPORT) |
---|
| 1411 | + ios.signal_voltage = MMC_SIGNAL_VOLTAGE_180; |
---|
| 1412 | + |
---|
| 1413 | + if (msm_host->caps_0 & CORE_VOLT_SUPPORT) { |
---|
| 1414 | + ret = mmc_regulator_set_vqmmc(mmc, &ios); |
---|
| 1415 | + if (ret < 0) { |
---|
| 1416 | + dev_err(mmc_dev(mmc), "%s: vqmmc set volgate failed: %d\n", |
---|
| 1417 | + mmc_hostname(mmc), ret); |
---|
| 1418 | + goto out; |
---|
| 1419 | + } |
---|
| 1420 | + } |
---|
| 1421 | + ret = regulator_enable(mmc->supply.vqmmc); |
---|
| 1422 | + } else { |
---|
| 1423 | + ret = regulator_disable(mmc->supply.vqmmc); |
---|
| 1424 | + } |
---|
| 1425 | + |
---|
| 1426 | + if (ret) |
---|
| 1427 | + dev_err(mmc_dev(mmc), "%s: vqmm %sable failed: %d\n", |
---|
| 1428 | + mmc_hostname(mmc), level ? "en":"dis", ret); |
---|
| 1429 | + else |
---|
| 1430 | + msm_host->vqmmc_enabled = level; |
---|
| 1431 | +out: |
---|
| 1432 | + return ret; |
---|
| 1433 | +} |
---|
| 1434 | + |
---|
| 1435 | +static int msm_config_vqmmc_mode(struct sdhci_msm_host *msm_host, |
---|
| 1436 | + struct mmc_host *mmc, bool hpm) |
---|
| 1437 | +{ |
---|
| 1438 | + int load, ret; |
---|
| 1439 | + |
---|
| 1440 | + load = hpm ? MMC_VQMMC_MAX_LOAD_UA : 0; |
---|
| 1441 | + ret = regulator_set_load(mmc->supply.vqmmc, load); |
---|
| 1442 | + if (ret) |
---|
| 1443 | + dev_err(mmc_dev(mmc), "%s: vqmmc set load failed: %d\n", |
---|
| 1444 | + mmc_hostname(mmc), ret); |
---|
| 1445 | + return ret; |
---|
| 1446 | +} |
---|
| 1447 | + |
---|
| 1448 | +static int sdhci_msm_set_vqmmc(struct sdhci_msm_host *msm_host, |
---|
| 1449 | + struct mmc_host *mmc, bool level) |
---|
| 1450 | +{ |
---|
| 1451 | + int ret; |
---|
| 1452 | + bool always_on; |
---|
| 1453 | + |
---|
| 1454 | + if (IS_ERR(mmc->supply.vqmmc) || |
---|
| 1455 | + (mmc->ios.power_mode == MMC_POWER_UNDEFINED)) |
---|
| 1456 | + return 0; |
---|
| 1457 | + /* |
---|
| 1458 | + * For eMMC don't turn off Vqmmc, Instead just configure it in LPM |
---|
| 1459 | + * and HPM modes by setting the corresponding load. |
---|
| 1460 | + * |
---|
| 1461 | + * Till eMMC is initialized (i.e. always_on == 0), just turn on/off |
---|
| 1462 | + * Vqmmc. Vqmmc gets turned off only if init fails and mmc_power_off |
---|
| 1463 | + * gets invoked. Once eMMC is initialized (i.e. always_on == 1), |
---|
| 1464 | + * Vqmmc should remain ON, So just set the load instead of turning it |
---|
| 1465 | + * off/on. |
---|
| 1466 | + */ |
---|
| 1467 | + always_on = !mmc_card_is_removable(mmc) && |
---|
| 1468 | + mmc->card && mmc_card_mmc(mmc->card); |
---|
| 1469 | + |
---|
| 1470 | + if (always_on) |
---|
| 1471 | + ret = msm_config_vqmmc_mode(msm_host, mmc, level); |
---|
| 1472 | + else |
---|
| 1473 | + ret = msm_toggle_vqmmc(msm_host, mmc, level); |
---|
| 1474 | + |
---|
| 1475 | + return ret; |
---|
| 1476 | +} |
---|
| 1477 | + |
---|
1274 | 1478 | static inline void sdhci_msm_init_pwr_irq_wait(struct sdhci_msm_host *msm_host) |
---|
1275 | 1479 | { |
---|
1276 | 1480 | init_waitqueue_head(&msm_host->pwr_irq_wait); |
---|
.. | .. |
---|
1288 | 1492 | * To what state the register writes will change the IO lines should be passed |
---|
1289 | 1493 | * as the argument req_type. This API will check whether the IO line's state |
---|
1290 | 1494 | * is already the expected state and will wait for power irq only if |
---|
1291 | | - * power irq is expected to be trigerred based on the current IO line state |
---|
| 1495 | + * power irq is expected to be triggered based on the current IO line state |
---|
1292 | 1496 | * and expected IO line state. |
---|
1293 | 1497 | */ |
---|
1294 | 1498 | static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type) |
---|
.. | .. |
---|
1374 | 1578 | { |
---|
1375 | 1579 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
1376 | 1580 | struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
---|
| 1581 | + struct mmc_host *mmc = host->mmc; |
---|
1377 | 1582 | u32 irq_status, irq_ack = 0; |
---|
1378 | | - int retry = 10; |
---|
| 1583 | + int retry = 10, ret; |
---|
1379 | 1584 | u32 pwr_state = 0, io_level = 0; |
---|
1380 | 1585 | u32 config; |
---|
1381 | 1586 | const struct sdhci_msm_offset *msm_offset = msm_host->offset; |
---|
.. | .. |
---|
1413 | 1618 | if (irq_status & CORE_PWRCTL_BUS_ON) { |
---|
1414 | 1619 | pwr_state = REQ_BUS_ON; |
---|
1415 | 1620 | io_level = REQ_IO_HIGH; |
---|
1416 | | - irq_ack |= CORE_PWRCTL_BUS_SUCCESS; |
---|
1417 | 1621 | } |
---|
1418 | 1622 | if (irq_status & CORE_PWRCTL_BUS_OFF) { |
---|
1419 | 1623 | pwr_state = REQ_BUS_OFF; |
---|
1420 | 1624 | io_level = REQ_IO_LOW; |
---|
1421 | | - irq_ack |= CORE_PWRCTL_BUS_SUCCESS; |
---|
1422 | 1625 | } |
---|
| 1626 | + |
---|
| 1627 | + if (pwr_state) { |
---|
| 1628 | + ret = sdhci_msm_set_vmmc(mmc); |
---|
| 1629 | + if (!ret) |
---|
| 1630 | + ret = sdhci_msm_set_vqmmc(msm_host, mmc, |
---|
| 1631 | + pwr_state & REQ_BUS_ON); |
---|
| 1632 | + if (!ret) |
---|
| 1633 | + ret = sdhci_msm_set_pincfg(msm_host, |
---|
| 1634 | + pwr_state & REQ_BUS_ON); |
---|
| 1635 | + if (!ret) |
---|
| 1636 | + irq_ack |= CORE_PWRCTL_BUS_SUCCESS; |
---|
| 1637 | + else |
---|
| 1638 | + irq_ack |= CORE_PWRCTL_BUS_FAIL; |
---|
| 1639 | + } |
---|
| 1640 | + |
---|
1423 | 1641 | /* Handle IO LOW/HIGH */ |
---|
1424 | | - if (irq_status & CORE_PWRCTL_IO_LOW) { |
---|
| 1642 | + if (irq_status & CORE_PWRCTL_IO_LOW) |
---|
1425 | 1643 | io_level = REQ_IO_LOW; |
---|
1426 | | - irq_ack |= CORE_PWRCTL_IO_SUCCESS; |
---|
1427 | | - } |
---|
1428 | | - if (irq_status & CORE_PWRCTL_IO_HIGH) { |
---|
| 1644 | + |
---|
| 1645 | + if (irq_status & CORE_PWRCTL_IO_HIGH) |
---|
1429 | 1646 | io_level = REQ_IO_HIGH; |
---|
| 1647 | + |
---|
| 1648 | + if (io_level) |
---|
1430 | 1649 | irq_ack |= CORE_PWRCTL_IO_SUCCESS; |
---|
| 1650 | + |
---|
| 1651 | + if (io_level && !IS_ERR(mmc->supply.vqmmc) && !pwr_state) { |
---|
| 1652 | + ret = mmc_regulator_set_vqmmc(mmc, &mmc->ios); |
---|
| 1653 | + if (ret < 0) { |
---|
| 1654 | + dev_err(mmc_dev(mmc), "%s: IO_level setting failed(%d). signal_voltage: %d, vdd: %d irq_status: 0x%08x\n", |
---|
| 1655 | + mmc_hostname(mmc), ret, |
---|
| 1656 | + mmc->ios.signal_voltage, mmc->ios.vdd, |
---|
| 1657 | + irq_status); |
---|
| 1658 | + irq_ack |= CORE_PWRCTL_IO_FAIL; |
---|
| 1659 | + } |
---|
1431 | 1660 | } |
---|
1432 | 1661 | |
---|
1433 | 1662 | /* |
---|
.. | .. |
---|
1476 | 1705 | if (io_level) |
---|
1477 | 1706 | msm_host->curr_io_level = io_level; |
---|
1478 | 1707 | |
---|
1479 | | - pr_debug("%s: %s: Handled IRQ(%d), irq_status=0x%x, ack=0x%x\n", |
---|
| 1708 | + dev_dbg(mmc_dev(mmc), "%s: %s: Handled IRQ(%d), irq_status=0x%x, ack=0x%x\n", |
---|
1480 | 1709 | mmc_hostname(msm_host->mmc), __func__, irq, irq_status, |
---|
1481 | 1710 | irq_ack); |
---|
1482 | 1711 | } |
---|
.. | .. |
---|
1509 | 1738 | return SDHCI_MSM_MIN_CLOCK; |
---|
1510 | 1739 | } |
---|
1511 | 1740 | |
---|
1512 | | -/** |
---|
| 1741 | +/* |
---|
1513 | 1742 | * __sdhci_msm_set_clock - sdhci_msm clock control. |
---|
1514 | 1743 | * |
---|
1515 | 1744 | * Description: |
---|
.. | .. |
---|
1558 | 1787 | msm_set_clock_rate_for_bus_mode(host, clock); |
---|
1559 | 1788 | out: |
---|
1560 | 1789 | __sdhci_msm_set_clock(host, clock); |
---|
| 1790 | +} |
---|
| 1791 | + |
---|
| 1792 | +/*****************************************************************************\ |
---|
| 1793 | + * * |
---|
| 1794 | + * Inline Crypto Engine (ICE) support * |
---|
| 1795 | + * * |
---|
| 1796 | +\*****************************************************************************/ |
---|
| 1797 | + |
---|
| 1798 | +#ifdef CONFIG_MMC_CRYPTO |
---|
| 1799 | + |
---|
| 1800 | +#define AES_256_XTS_KEY_SIZE 64 |
---|
| 1801 | + |
---|
| 1802 | +/* QCOM ICE registers */ |
---|
| 1803 | + |
---|
| 1804 | +#define QCOM_ICE_REG_VERSION 0x0008 |
---|
| 1805 | + |
---|
| 1806 | +#define QCOM_ICE_REG_FUSE_SETTING 0x0010 |
---|
| 1807 | +#define QCOM_ICE_FUSE_SETTING_MASK 0x1 |
---|
| 1808 | +#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2 |
---|
| 1809 | +#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4 |
---|
| 1810 | + |
---|
| 1811 | +#define QCOM_ICE_REG_BIST_STATUS 0x0070 |
---|
| 1812 | +#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000 |
---|
| 1813 | + |
---|
| 1814 | +#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000 |
---|
| 1815 | + |
---|
| 1816 | +#define sdhci_msm_ice_writel(host, val, reg) \ |
---|
| 1817 | + writel((val), (host)->ice_mem + (reg)) |
---|
| 1818 | +#define sdhci_msm_ice_readl(host, reg) \ |
---|
| 1819 | + readl((host)->ice_mem + (reg)) |
---|
| 1820 | + |
---|
| 1821 | +static bool sdhci_msm_ice_supported(struct sdhci_msm_host *msm_host) |
---|
| 1822 | +{ |
---|
| 1823 | + struct device *dev = mmc_dev(msm_host->mmc); |
---|
| 1824 | + u32 regval = sdhci_msm_ice_readl(msm_host, QCOM_ICE_REG_VERSION); |
---|
| 1825 | + int major = regval >> 24; |
---|
| 1826 | + int minor = (regval >> 16) & 0xFF; |
---|
| 1827 | + int step = regval & 0xFFFF; |
---|
| 1828 | + |
---|
| 1829 | + /* For now this driver only supports ICE version 3. */ |
---|
| 1830 | + if (major != 3) { |
---|
| 1831 | + dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n", |
---|
| 1832 | + major, minor, step); |
---|
| 1833 | + return false; |
---|
| 1834 | + } |
---|
| 1835 | + |
---|
| 1836 | + dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", |
---|
| 1837 | + major, minor, step); |
---|
| 1838 | + |
---|
| 1839 | + /* If fuses are blown, ICE might not work in the standard way. */ |
---|
| 1840 | + regval = sdhci_msm_ice_readl(msm_host, QCOM_ICE_REG_FUSE_SETTING); |
---|
| 1841 | + if (regval & (QCOM_ICE_FUSE_SETTING_MASK | |
---|
| 1842 | + QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK | |
---|
| 1843 | + QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) { |
---|
| 1844 | + dev_warn(dev, "Fuses are blown; ICE is unusable!\n"); |
---|
| 1845 | + return false; |
---|
| 1846 | + } |
---|
| 1847 | + return true; |
---|
| 1848 | +} |
---|
| 1849 | + |
---|
| 1850 | +static inline struct clk *sdhci_msm_ice_get_clk(struct device *dev) |
---|
| 1851 | +{ |
---|
| 1852 | + return devm_clk_get(dev, "ice"); |
---|
| 1853 | +} |
---|
| 1854 | + |
---|
| 1855 | +static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, |
---|
| 1856 | + struct cqhci_host *cq_host) |
---|
| 1857 | +{ |
---|
| 1858 | + struct mmc_host *mmc = msm_host->mmc; |
---|
| 1859 | + struct device *dev = mmc_dev(mmc); |
---|
| 1860 | + struct resource *res; |
---|
| 1861 | + int err; |
---|
| 1862 | + |
---|
| 1863 | + if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS)) |
---|
| 1864 | + return 0; |
---|
| 1865 | + |
---|
| 1866 | + res = platform_get_resource_byname(msm_host->pdev, IORESOURCE_MEM, |
---|
| 1867 | + "ice"); |
---|
| 1868 | + if (!res) { |
---|
| 1869 | + dev_warn(dev, "ICE registers not found\n"); |
---|
| 1870 | + goto disable; |
---|
| 1871 | + } |
---|
| 1872 | + |
---|
| 1873 | + if (!qcom_scm_ice_available()) { |
---|
| 1874 | + dev_warn(dev, "ICE SCM interface not found\n"); |
---|
| 1875 | + goto disable; |
---|
| 1876 | + } |
---|
| 1877 | + |
---|
| 1878 | + msm_host->ice_mem = devm_ioremap_resource(dev, res); |
---|
| 1879 | + if (IS_ERR(msm_host->ice_mem)) { |
---|
| 1880 | + err = PTR_ERR(msm_host->ice_mem); |
---|
| 1881 | + dev_err(dev, "Failed to map ICE registers; err=%d\n", err); |
---|
| 1882 | + return err; |
---|
| 1883 | + } |
---|
| 1884 | + |
---|
| 1885 | + if (!sdhci_msm_ice_supported(msm_host)) |
---|
| 1886 | + goto disable; |
---|
| 1887 | + |
---|
| 1888 | + mmc->caps2 |= MMC_CAP2_CRYPTO; |
---|
| 1889 | + return 0; |
---|
| 1890 | + |
---|
| 1891 | +disable: |
---|
| 1892 | + dev_warn(dev, "Disabling inline encryption support\n"); |
---|
| 1893 | + return 0; |
---|
| 1894 | +} |
---|
| 1895 | + |
---|
| 1896 | +static void sdhci_msm_ice_low_power_mode_enable(struct sdhci_msm_host *msm_host) |
---|
| 1897 | +{ |
---|
| 1898 | + u32 regval; |
---|
| 1899 | + |
---|
| 1900 | + regval = sdhci_msm_ice_readl(msm_host, QCOM_ICE_REG_ADVANCED_CONTROL); |
---|
| 1901 | + /* |
---|
| 1902 | + * Enable low power mode sequence |
---|
| 1903 | + * [0]-0, [1]-0, [2]-0, [3]-E, [4]-0, [5]-0, [6]-0, [7]-0 |
---|
| 1904 | + */ |
---|
| 1905 | + regval |= 0x7000; |
---|
| 1906 | + sdhci_msm_ice_writel(msm_host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); |
---|
| 1907 | +} |
---|
| 1908 | + |
---|
| 1909 | +static void sdhci_msm_ice_optimization_enable(struct sdhci_msm_host *msm_host) |
---|
| 1910 | +{ |
---|
| 1911 | + u32 regval; |
---|
| 1912 | + |
---|
| 1913 | + /* ICE Optimizations Enable Sequence */ |
---|
| 1914 | + regval = sdhci_msm_ice_readl(msm_host, QCOM_ICE_REG_ADVANCED_CONTROL); |
---|
| 1915 | + regval |= 0xD807100; |
---|
| 1916 | + /* ICE HPG requires delay before writing */ |
---|
| 1917 | + udelay(5); |
---|
| 1918 | + sdhci_msm_ice_writel(msm_host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); |
---|
| 1919 | + udelay(5); |
---|
| 1920 | +} |
---|
| 1921 | + |
---|
| 1922 | +/* |
---|
| 1923 | + * Wait until the ICE BIST (built-in self-test) has completed. |
---|
| 1924 | + * |
---|
| 1925 | + * This may be necessary before ICE can be used. |
---|
| 1926 | + * |
---|
| 1927 | + * Note that we don't really care whether the BIST passed or failed; we really |
---|
| 1928 | + * just want to make sure that it isn't still running. This is because (a) the |
---|
| 1929 | + * BIST is a FIPS compliance thing that never fails in practice, (b) ICE is |
---|
| 1930 | + * documented to reject crypto requests if the BIST fails, so we needn't do it |
---|
| 1931 | + * in software too, and (c) properly testing storage encryption requires testing |
---|
| 1932 | + * the full storage stack anyway, and not relying on hardware-level self-tests. |
---|
| 1933 | + */ |
---|
| 1934 | +static int sdhci_msm_ice_wait_bist_status(struct sdhci_msm_host *msm_host) |
---|
| 1935 | +{ |
---|
| 1936 | + u32 regval; |
---|
| 1937 | + int err; |
---|
| 1938 | + |
---|
| 1939 | + err = readl_poll_timeout(msm_host->ice_mem + QCOM_ICE_REG_BIST_STATUS, |
---|
| 1940 | + regval, !(regval & QCOM_ICE_BIST_STATUS_MASK), |
---|
| 1941 | + 50, 5000); |
---|
| 1942 | + if (err) |
---|
| 1943 | + dev_err(mmc_dev(msm_host->mmc), |
---|
| 1944 | + "Timed out waiting for ICE self-test to complete\n"); |
---|
| 1945 | + return err; |
---|
| 1946 | +} |
---|
| 1947 | + |
---|
| 1948 | +static void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host) |
---|
| 1949 | +{ |
---|
| 1950 | + if (!(msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)) |
---|
| 1951 | + return; |
---|
| 1952 | + sdhci_msm_ice_low_power_mode_enable(msm_host); |
---|
| 1953 | + sdhci_msm_ice_optimization_enable(msm_host); |
---|
| 1954 | + sdhci_msm_ice_wait_bist_status(msm_host); |
---|
| 1955 | +} |
---|
| 1956 | + |
---|
| 1957 | +static int __maybe_unused sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host) |
---|
| 1958 | +{ |
---|
| 1959 | + if (!(msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)) |
---|
| 1960 | + return 0; |
---|
| 1961 | + return sdhci_msm_ice_wait_bist_status(msm_host); |
---|
| 1962 | +} |
---|
| 1963 | + |
---|
| 1964 | +/* |
---|
| 1965 | + * Program a key into a QC ICE keyslot, or evict a keyslot. QC ICE requires |
---|
| 1966 | + * vendor-specific SCM calls for this; it doesn't support the standard way. |
---|
| 1967 | + */ |
---|
| 1968 | +static int sdhci_msm_program_key(struct cqhci_host *cq_host, |
---|
| 1969 | + const union cqhci_crypto_cfg_entry *cfg, |
---|
| 1970 | + int slot) |
---|
| 1971 | +{ |
---|
| 1972 | + struct device *dev = mmc_dev(cq_host->mmc); |
---|
| 1973 | + union cqhci_crypto_cap_entry cap; |
---|
| 1974 | + union { |
---|
| 1975 | + u8 bytes[AES_256_XTS_KEY_SIZE]; |
---|
| 1976 | + u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)]; |
---|
| 1977 | + } key; |
---|
| 1978 | + int i; |
---|
| 1979 | + int err; |
---|
| 1980 | + |
---|
| 1981 | + if (!(cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE)) |
---|
| 1982 | + return qcom_scm_ice_invalidate_key(slot); |
---|
| 1983 | + |
---|
| 1984 | + /* Only AES-256-XTS has been tested so far. */ |
---|
| 1985 | + cap = cq_host->crypto_cap_array[cfg->crypto_cap_idx]; |
---|
| 1986 | + if (cap.algorithm_id != CQHCI_CRYPTO_ALG_AES_XTS || |
---|
| 1987 | + cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256) { |
---|
| 1988 | + dev_err_ratelimited(dev, |
---|
| 1989 | + "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n", |
---|
| 1990 | + cap.algorithm_id, cap.key_size); |
---|
| 1991 | + return -EINVAL; |
---|
| 1992 | + } |
---|
| 1993 | + |
---|
| 1994 | + memcpy(key.bytes, cfg->crypto_key, AES_256_XTS_KEY_SIZE); |
---|
| 1995 | + |
---|
| 1996 | + /* |
---|
| 1997 | + * The SCM call byte-swaps the 32-bit words of the key. So we have to |
---|
| 1998 | + * do the same, in order for the final key be correct. |
---|
| 1999 | + */ |
---|
| 2000 | + for (i = 0; i < ARRAY_SIZE(key.words); i++) |
---|
| 2001 | + __cpu_to_be32s(&key.words[i]); |
---|
| 2002 | + |
---|
| 2003 | + err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE, |
---|
| 2004 | + QCOM_SCM_ICE_CIPHER_AES_256_XTS, |
---|
| 2005 | + cfg->data_unit_size); |
---|
| 2006 | + memzero_explicit(&key, sizeof(key)); |
---|
| 2007 | + return err; |
---|
| 2008 | +} |
---|
| 2009 | +#else /* CONFIG_MMC_CRYPTO */ |
---|
| 2010 | +static inline struct clk *sdhci_msm_ice_get_clk(struct device *dev) |
---|
| 2011 | +{ |
---|
| 2012 | + return NULL; |
---|
| 2013 | +} |
---|
| 2014 | + |
---|
| 2015 | +static inline int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, |
---|
| 2016 | + struct cqhci_host *cq_host) |
---|
| 2017 | +{ |
---|
| 2018 | + return 0; |
---|
| 2019 | +} |
---|
| 2020 | + |
---|
| 2021 | +static inline void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host) |
---|
| 2022 | +{ |
---|
| 2023 | +} |
---|
| 2024 | + |
---|
| 2025 | +static inline int __maybe_unused |
---|
| 2026 | +sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host) |
---|
| 2027 | +{ |
---|
| 2028 | + return 0; |
---|
| 2029 | +} |
---|
| 2030 | +#endif /* !CONFIG_MMC_CRYPTO */ |
---|
| 2031 | + |
---|
| 2032 | +/*****************************************************************************\ |
---|
| 2033 | + * * |
---|
| 2034 | + * MSM Command Queue Engine (CQE) * |
---|
| 2035 | + * * |
---|
| 2036 | +\*****************************************************************************/ |
---|
| 2037 | + |
---|
| 2038 | +static u32 sdhci_msm_cqe_irq(struct sdhci_host *host, u32 intmask) |
---|
| 2039 | +{ |
---|
| 2040 | + int cmd_error = 0; |
---|
| 2041 | + int data_error = 0; |
---|
| 2042 | + |
---|
| 2043 | + if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) |
---|
| 2044 | + return intmask; |
---|
| 2045 | + |
---|
| 2046 | + cqhci_irq(host->mmc, intmask, cmd_error, data_error); |
---|
| 2047 | + return 0; |
---|
| 2048 | +} |
---|
| 2049 | + |
---|
| 2050 | +static void sdhci_msm_cqe_enable(struct mmc_host *mmc) |
---|
| 2051 | +{ |
---|
| 2052 | + struct sdhci_host *host = mmc_priv(mmc); |
---|
| 2053 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 2054 | + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
---|
| 2055 | + |
---|
| 2056 | + sdhci_cqe_enable(mmc); |
---|
| 2057 | + sdhci_msm_ice_enable(msm_host); |
---|
| 2058 | +} |
---|
| 2059 | + |
---|
| 2060 | +static void sdhci_msm_cqe_disable(struct mmc_host *mmc, bool recovery) |
---|
| 2061 | +{ |
---|
| 2062 | + struct sdhci_host *host = mmc_priv(mmc); |
---|
| 2063 | + unsigned long flags; |
---|
| 2064 | + u32 ctrl; |
---|
| 2065 | + |
---|
| 2066 | + /* |
---|
| 2067 | + * When CQE is halted, the legacy SDHCI path operates only |
---|
| 2068 | + * on 16-byte descriptors in 64bit mode. |
---|
| 2069 | + */ |
---|
| 2070 | + if (host->flags & SDHCI_USE_64_BIT_DMA) |
---|
| 2071 | + host->desc_sz = 16; |
---|
| 2072 | + |
---|
| 2073 | + spin_lock_irqsave(&host->lock, flags); |
---|
| 2074 | + |
---|
| 2075 | + /* |
---|
| 2076 | + * During CQE command transfers, command complete bit gets latched. |
---|
| 2077 | + * So s/w should clear command complete interrupt status when CQE is |
---|
| 2078 | + * either halted or disabled. Otherwise unexpected SDCHI legacy |
---|
| 2079 | + * interrupt gets triggered when CQE is halted/disabled. |
---|
| 2080 | + */ |
---|
| 2081 | + ctrl = sdhci_readl(host, SDHCI_INT_ENABLE); |
---|
| 2082 | + ctrl |= SDHCI_INT_RESPONSE; |
---|
| 2083 | + sdhci_writel(host, ctrl, SDHCI_INT_ENABLE); |
---|
| 2084 | + sdhci_writel(host, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS); |
---|
| 2085 | + |
---|
| 2086 | + spin_unlock_irqrestore(&host->lock, flags); |
---|
| 2087 | + |
---|
| 2088 | + sdhci_cqe_disable(mmc, recovery); |
---|
| 2089 | +} |
---|
| 2090 | + |
---|
| 2091 | +static void sdhci_msm_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) |
---|
| 2092 | +{ |
---|
| 2093 | + u32 count, start = 15; |
---|
| 2094 | + |
---|
| 2095 | + __sdhci_set_timeout(host, cmd); |
---|
| 2096 | + count = sdhci_readb(host, SDHCI_TIMEOUT_CONTROL); |
---|
| 2097 | + /* |
---|
| 2098 | + * Update software timeout value if its value is less than hardware data |
---|
| 2099 | + * timeout value. Qcom SoC hardware data timeout value was calculated |
---|
| 2100 | + * using 4 * MCLK * 2^(count + 13). where MCLK = 1 / host->clock. |
---|
| 2101 | + */ |
---|
| 2102 | + if (cmd && cmd->data && host->clock > 400000 && |
---|
| 2103 | + host->clock <= 50000000 && |
---|
| 2104 | + ((1 << (count + start)) > (10 * host->clock))) |
---|
| 2105 | + host->data_timeout = 22LL * NSEC_PER_SEC; |
---|
| 2106 | +} |
---|
| 2107 | + |
---|
| 2108 | +static const struct cqhci_host_ops sdhci_msm_cqhci_ops = { |
---|
| 2109 | + .enable = sdhci_msm_cqe_enable, |
---|
| 2110 | + .disable = sdhci_msm_cqe_disable, |
---|
| 2111 | +#ifdef CONFIG_MMC_CRYPTO |
---|
| 2112 | + .program_key = sdhci_msm_program_key, |
---|
| 2113 | +#endif |
---|
| 2114 | +}; |
---|
| 2115 | + |
---|
| 2116 | +static int sdhci_msm_cqe_add_host(struct sdhci_host *host, |
---|
| 2117 | + struct platform_device *pdev) |
---|
| 2118 | +{ |
---|
| 2119 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 2120 | + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
---|
| 2121 | + struct cqhci_host *cq_host; |
---|
| 2122 | + bool dma64; |
---|
| 2123 | + u32 cqcfg; |
---|
| 2124 | + int ret; |
---|
| 2125 | + |
---|
| 2126 | + /* |
---|
| 2127 | + * When CQE is halted, SDHC operates only on 16byte ADMA descriptors. |
---|
| 2128 | + * So ensure ADMA table is allocated for 16byte descriptors. |
---|
| 2129 | + */ |
---|
| 2130 | + if (host->caps & SDHCI_CAN_64BIT) |
---|
| 2131 | + host->alloc_desc_sz = 16; |
---|
| 2132 | + |
---|
| 2133 | + ret = sdhci_setup_host(host); |
---|
| 2134 | + if (ret) |
---|
| 2135 | + return ret; |
---|
| 2136 | + |
---|
| 2137 | + cq_host = cqhci_pltfm_init(pdev); |
---|
| 2138 | + if (IS_ERR(cq_host)) { |
---|
| 2139 | + ret = PTR_ERR(cq_host); |
---|
| 2140 | + dev_err(&pdev->dev, "cqhci-pltfm init: failed: %d\n", ret); |
---|
| 2141 | + goto cleanup; |
---|
| 2142 | + } |
---|
| 2143 | + |
---|
| 2144 | + msm_host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; |
---|
| 2145 | + cq_host->ops = &sdhci_msm_cqhci_ops; |
---|
| 2146 | + |
---|
| 2147 | + dma64 = host->flags & SDHCI_USE_64_BIT_DMA; |
---|
| 2148 | + |
---|
| 2149 | + ret = sdhci_msm_ice_init(msm_host, cq_host); |
---|
| 2150 | + if (ret) |
---|
| 2151 | + goto cleanup; |
---|
| 2152 | + |
---|
| 2153 | + ret = cqhci_init(cq_host, host->mmc, dma64); |
---|
| 2154 | + if (ret) { |
---|
| 2155 | + dev_err(&pdev->dev, "%s: CQE init: failed (%d)\n", |
---|
| 2156 | + mmc_hostname(host->mmc), ret); |
---|
| 2157 | + goto cleanup; |
---|
| 2158 | + } |
---|
| 2159 | + |
---|
| 2160 | + /* Disable cqe reset due to cqe enable signal */ |
---|
| 2161 | + cqcfg = cqhci_readl(cq_host, CQHCI_VENDOR_CFG1); |
---|
| 2162 | + cqcfg |= CQHCI_VENDOR_DIS_RST_ON_CQ_EN; |
---|
| 2163 | + cqhci_writel(cq_host, cqcfg, CQHCI_VENDOR_CFG1); |
---|
| 2164 | + |
---|
| 2165 | + /* |
---|
| 2166 | + * SDHC expects 12byte ADMA descriptors till CQE is enabled. |
---|
| 2167 | + * So limit desc_sz to 12 so that the data commands that are sent |
---|
| 2168 | + * during card initialization (before CQE gets enabled) would |
---|
| 2169 | + * get executed without any issues. |
---|
| 2170 | + */ |
---|
| 2171 | + if (host->flags & SDHCI_USE_64_BIT_DMA) |
---|
| 2172 | + host->desc_sz = 12; |
---|
| 2173 | + |
---|
| 2174 | + ret = __sdhci_add_host(host); |
---|
| 2175 | + if (ret) |
---|
| 2176 | + goto cleanup; |
---|
| 2177 | + |
---|
| 2178 | + dev_info(&pdev->dev, "%s: CQE init: success\n", |
---|
| 2179 | + mmc_hostname(host->mmc)); |
---|
| 2180 | + return ret; |
---|
| 2181 | + |
---|
| 2182 | +cleanup: |
---|
| 2183 | + sdhci_cleanup_host(host); |
---|
| 2184 | + return ret; |
---|
1561 | 2185 | } |
---|
1562 | 2186 | |
---|
1563 | 2187 | /* |
---|
.. | .. |
---|
1678 | 2302 | pr_debug("%s: supported caps: 0x%08x\n", mmc_hostname(mmc), caps); |
---|
1679 | 2303 | } |
---|
1680 | 2304 | |
---|
| 2305 | +static void sdhci_msm_reset(struct sdhci_host *host, u8 mask) |
---|
| 2306 | +{ |
---|
| 2307 | + if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL)) |
---|
| 2308 | + cqhci_deactivate(host->mmc); |
---|
| 2309 | + sdhci_reset(host, mask); |
---|
| 2310 | +} |
---|
| 2311 | + |
---|
| 2312 | +static int sdhci_msm_register_vreg(struct sdhci_msm_host *msm_host) |
---|
| 2313 | +{ |
---|
| 2314 | + int ret; |
---|
| 2315 | + |
---|
| 2316 | + ret = mmc_regulator_get_supply(msm_host->mmc); |
---|
| 2317 | + if (ret) |
---|
| 2318 | + return ret; |
---|
| 2319 | + |
---|
| 2320 | + sdhci_msm_set_regulator_caps(msm_host); |
---|
| 2321 | + |
---|
| 2322 | + return 0; |
---|
| 2323 | +} |
---|
| 2324 | + |
---|
| 2325 | +static int sdhci_msm_start_signal_voltage_switch(struct mmc_host *mmc, |
---|
| 2326 | + struct mmc_ios *ios) |
---|
| 2327 | +{ |
---|
| 2328 | + struct sdhci_host *host = mmc_priv(mmc); |
---|
| 2329 | + u16 ctrl, status; |
---|
| 2330 | + |
---|
| 2331 | + /* |
---|
| 2332 | + * Signal Voltage Switching is only applicable for Host Controllers |
---|
| 2333 | + * v3.00 and above. |
---|
| 2334 | + */ |
---|
| 2335 | + if (host->version < SDHCI_SPEC_300) |
---|
| 2336 | + return 0; |
---|
| 2337 | + |
---|
| 2338 | + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
---|
| 2339 | + |
---|
| 2340 | + switch (ios->signal_voltage) { |
---|
| 2341 | + case MMC_SIGNAL_VOLTAGE_330: |
---|
| 2342 | + if (!(host->flags & SDHCI_SIGNALING_330)) |
---|
| 2343 | + return -EINVAL; |
---|
| 2344 | + |
---|
| 2345 | + /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ |
---|
| 2346 | + ctrl &= ~SDHCI_CTRL_VDD_180; |
---|
| 2347 | + break; |
---|
| 2348 | + case MMC_SIGNAL_VOLTAGE_180: |
---|
| 2349 | + if (!(host->flags & SDHCI_SIGNALING_180)) |
---|
| 2350 | + return -EINVAL; |
---|
| 2351 | + |
---|
| 2352 | + /* Enable 1.8V Signal Enable in the Host Control2 register */ |
---|
| 2353 | + ctrl |= SDHCI_CTRL_VDD_180; |
---|
| 2354 | + break; |
---|
| 2355 | + |
---|
| 2356 | + default: |
---|
| 2357 | + return -EINVAL; |
---|
| 2358 | + } |
---|
| 2359 | + |
---|
| 2360 | + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
---|
| 2361 | + |
---|
| 2362 | + /* Wait for 5ms */ |
---|
| 2363 | + usleep_range(5000, 5500); |
---|
| 2364 | + |
---|
| 2365 | + /* regulator output should be stable within 5 ms */ |
---|
| 2366 | + status = ctrl & SDHCI_CTRL_VDD_180; |
---|
| 2367 | + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
---|
| 2368 | + if ((ctrl & SDHCI_CTRL_VDD_180) == status) |
---|
| 2369 | + return 0; |
---|
| 2370 | + |
---|
| 2371 | + dev_warn(mmc_dev(mmc), "%s: Regulator output did not became stable\n", |
---|
| 2372 | + mmc_hostname(mmc)); |
---|
| 2373 | + |
---|
| 2374 | + return -EAGAIN; |
---|
| 2375 | +} |
---|
| 2376 | + |
---|
| 2377 | +#define DRIVER_NAME "sdhci_msm" |
---|
| 2378 | +#define SDHCI_MSM_DUMP(f, x...) \ |
---|
| 2379 | + pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) |
---|
| 2380 | + |
---|
| 2381 | +static void sdhci_msm_dump_vendor_regs(struct sdhci_host *host) |
---|
| 2382 | +{ |
---|
| 2383 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 2384 | + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
---|
| 2385 | + const struct sdhci_msm_offset *msm_offset = msm_host->offset; |
---|
| 2386 | + |
---|
| 2387 | + SDHCI_MSM_DUMP("----------- VENDOR REGISTER DUMP -----------\n"); |
---|
| 2388 | + |
---|
| 2389 | + SDHCI_MSM_DUMP( |
---|
| 2390 | + "DLL sts: 0x%08x | DLL cfg: 0x%08x | DLL cfg2: 0x%08x\n", |
---|
| 2391 | + readl_relaxed(host->ioaddr + msm_offset->core_dll_status), |
---|
| 2392 | + readl_relaxed(host->ioaddr + msm_offset->core_dll_config), |
---|
| 2393 | + readl_relaxed(host->ioaddr + msm_offset->core_dll_config_2)); |
---|
| 2394 | + SDHCI_MSM_DUMP( |
---|
| 2395 | + "DLL cfg3: 0x%08x | DLL usr ctl: 0x%08x | DDR cfg: 0x%08x\n", |
---|
| 2396 | + readl_relaxed(host->ioaddr + msm_offset->core_dll_config_3), |
---|
| 2397 | + readl_relaxed(host->ioaddr + msm_offset->core_dll_usr_ctl), |
---|
| 2398 | + readl_relaxed(host->ioaddr + msm_offset->core_ddr_config)); |
---|
| 2399 | + SDHCI_MSM_DUMP( |
---|
| 2400 | + "Vndr func: 0x%08x | Vndr func2 : 0x%08x Vndr func3: 0x%08x\n", |
---|
| 2401 | + readl_relaxed(host->ioaddr + msm_offset->core_vendor_spec), |
---|
| 2402 | + readl_relaxed(host->ioaddr + |
---|
| 2403 | + msm_offset->core_vendor_spec_func2), |
---|
| 2404 | + readl_relaxed(host->ioaddr + msm_offset->core_vendor_spec3)); |
---|
| 2405 | +} |
---|
| 2406 | + |
---|
1681 | 2407 | static const struct sdhci_msm_variant_ops mci_var_ops = { |
---|
1682 | 2408 | .msm_readl_relaxed = sdhci_msm_mci_variant_readl_relaxed, |
---|
1683 | 2409 | .msm_writel_relaxed = sdhci_msm_mci_variant_writel_relaxed, |
---|
.. | .. |
---|
1689 | 2415 | }; |
---|
1690 | 2416 | |
---|
1691 | 2417 | static const struct sdhci_msm_variant_info sdhci_msm_mci_var = { |
---|
1692 | | - .mci_removed = false, |
---|
1693 | 2418 | .var_ops = &mci_var_ops, |
---|
1694 | 2419 | .offset = &sdhci_msm_mci_offset, |
---|
1695 | 2420 | }; |
---|
.. | .. |
---|
1700 | 2425 | .offset = &sdhci_msm_v5_offset, |
---|
1701 | 2426 | }; |
---|
1702 | 2427 | |
---|
| 2428 | +static const struct sdhci_msm_variant_info sdm845_sdhci_var = { |
---|
| 2429 | + .mci_removed = true, |
---|
| 2430 | + .restore_dll_config = true, |
---|
| 2431 | + .var_ops = &v5_var_ops, |
---|
| 2432 | + .offset = &sdhci_msm_v5_offset, |
---|
| 2433 | +}; |
---|
| 2434 | + |
---|
| 2435 | +static const struct sdhci_msm_variant_info sm8250_sdhci_var = { |
---|
| 2436 | + .mci_removed = true, |
---|
| 2437 | + .uses_tassadar_dll = true, |
---|
| 2438 | + .var_ops = &v5_var_ops, |
---|
| 2439 | + .offset = &sdhci_msm_v5_offset, |
---|
| 2440 | +}; |
---|
| 2441 | + |
---|
1703 | 2442 | static const struct of_device_id sdhci_msm_dt_match[] = { |
---|
1704 | 2443 | {.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var}, |
---|
1705 | 2444 | {.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var}, |
---|
| 2445 | + {.compatible = "qcom,sdm670-sdhci", .data = &sdm845_sdhci_var}, |
---|
| 2446 | + {.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var}, |
---|
| 2447 | + {.compatible = "qcom,sm8250-sdhci", .data = &sm8250_sdhci_var}, |
---|
| 2448 | + {.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var}, |
---|
1706 | 2449 | {}, |
---|
1707 | 2450 | }; |
---|
1708 | 2451 | |
---|
1709 | 2452 | MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match); |
---|
1710 | 2453 | |
---|
1711 | 2454 | static const struct sdhci_ops sdhci_msm_ops = { |
---|
1712 | | - .reset = sdhci_reset, |
---|
| 2455 | + .reset = sdhci_msm_reset, |
---|
1713 | 2456 | .set_clock = sdhci_msm_set_clock, |
---|
1714 | 2457 | .get_min_clock = sdhci_msm_get_min_clock, |
---|
1715 | 2458 | .get_max_clock = sdhci_msm_get_max_clock, |
---|
.. | .. |
---|
1717 | 2460 | .set_uhs_signaling = sdhci_msm_set_uhs_signaling, |
---|
1718 | 2461 | .write_w = sdhci_msm_writew, |
---|
1719 | 2462 | .write_b = sdhci_msm_writeb, |
---|
| 2463 | + .irq = sdhci_msm_cqe_irq, |
---|
| 2464 | + .dump_vendor_regs = sdhci_msm_dump_vendor_regs, |
---|
| 2465 | + .set_power = sdhci_set_power_noreg, |
---|
| 2466 | + .set_timeout = sdhci_msm_set_timeout, |
---|
1720 | 2467 | }; |
---|
1721 | 2468 | |
---|
1722 | 2469 | static const struct sdhci_pltfm_data sdhci_msm_pdata = { |
---|
.. | .. |
---|
1729 | 2476 | .ops = &sdhci_msm_ops, |
---|
1730 | 2477 | }; |
---|
1731 | 2478 | |
---|
| 2479 | +static inline void sdhci_msm_get_of_property(struct platform_device *pdev, |
---|
| 2480 | + struct sdhci_host *host) |
---|
| 2481 | +{ |
---|
| 2482 | + struct device_node *node = pdev->dev.of_node; |
---|
| 2483 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 2484 | + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
---|
| 2485 | + |
---|
| 2486 | + if (of_property_read_u32(node, "qcom,ddr-config", |
---|
| 2487 | + &msm_host->ddr_config)) |
---|
| 2488 | + msm_host->ddr_config = DDR_CONFIG_POR_VAL; |
---|
| 2489 | + |
---|
| 2490 | + of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config); |
---|
| 2491 | + |
---|
| 2492 | + if (of_device_is_compatible(node, "qcom,msm8916-sdhci")) |
---|
| 2493 | + host->quirks2 |= SDHCI_QUIRK2_BROKEN_64_BIT_DMA; |
---|
| 2494 | +} |
---|
| 2495 | + |
---|
| 2496 | +static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host) |
---|
| 2497 | +{ |
---|
| 2498 | + struct reset_control *reset; |
---|
| 2499 | + int ret = 0; |
---|
| 2500 | + |
---|
| 2501 | + reset = reset_control_get_optional_exclusive(dev, NULL); |
---|
| 2502 | + if (IS_ERR(reset)) |
---|
| 2503 | + return dev_err_probe(dev, PTR_ERR(reset), |
---|
| 2504 | + "unable to acquire core_reset\n"); |
---|
| 2505 | + |
---|
| 2506 | + if (!reset) |
---|
| 2507 | + return ret; |
---|
| 2508 | + |
---|
| 2509 | + ret = reset_control_assert(reset); |
---|
| 2510 | + if (ret) { |
---|
| 2511 | + reset_control_put(reset); |
---|
| 2512 | + return dev_err_probe(dev, ret, "core_reset assert failed\n"); |
---|
| 2513 | + } |
---|
| 2514 | + |
---|
| 2515 | + /* |
---|
| 2516 | + * The hardware requirement for delay between assert/deassert |
---|
| 2517 | + * is at least 3-4 sleep clock (32.7KHz) cycles, which comes to |
---|
| 2518 | + * ~125us (4/32768). To be on the safe side add 200us delay. |
---|
| 2519 | + */ |
---|
| 2520 | + usleep_range(200, 210); |
---|
| 2521 | + |
---|
| 2522 | + ret = reset_control_deassert(reset); |
---|
| 2523 | + if (ret) { |
---|
| 2524 | + reset_control_put(reset); |
---|
| 2525 | + return dev_err_probe(dev, ret, "core_reset deassert failed\n"); |
---|
| 2526 | + } |
---|
| 2527 | + |
---|
| 2528 | + usleep_range(200, 210); |
---|
| 2529 | + reset_control_put(reset); |
---|
| 2530 | + |
---|
| 2531 | + return ret; |
---|
| 2532 | +} |
---|
| 2533 | + |
---|
1732 | 2534 | static int sdhci_msm_probe(struct platform_device *pdev) |
---|
1733 | 2535 | { |
---|
1734 | 2536 | struct sdhci_host *host; |
---|
1735 | 2537 | struct sdhci_pltfm_host *pltfm_host; |
---|
1736 | 2538 | struct sdhci_msm_host *msm_host; |
---|
1737 | | - struct resource *core_memres; |
---|
1738 | 2539 | struct clk *clk; |
---|
1739 | 2540 | int ret; |
---|
1740 | 2541 | u16 host_version, core_minor; |
---|
.. | .. |
---|
1742 | 2543 | u8 core_major; |
---|
1743 | 2544 | const struct sdhci_msm_offset *msm_offset; |
---|
1744 | 2545 | const struct sdhci_msm_variant_info *var_info; |
---|
| 2546 | + struct device_node *node = pdev->dev.of_node; |
---|
1745 | 2547 | |
---|
1746 | 2548 | host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host)); |
---|
1747 | 2549 | if (IS_ERR(host)) |
---|
.. | .. |
---|
1764 | 2566 | var_info = of_device_get_match_data(&pdev->dev); |
---|
1765 | 2567 | |
---|
1766 | 2568 | msm_host->mci_removed = var_info->mci_removed; |
---|
| 2569 | + msm_host->restore_dll_config = var_info->restore_dll_config; |
---|
1767 | 2570 | msm_host->var_ops = var_info->var_ops; |
---|
1768 | 2571 | msm_host->offset = var_info->offset; |
---|
| 2572 | + msm_host->uses_tassadar_dll = var_info->uses_tassadar_dll; |
---|
1769 | 2573 | |
---|
1770 | 2574 | msm_offset = msm_host->offset; |
---|
1771 | 2575 | |
---|
1772 | 2576 | sdhci_get_of_property(pdev); |
---|
| 2577 | + sdhci_msm_get_of_property(pdev, host); |
---|
1773 | 2578 | |
---|
1774 | 2579 | msm_host->saved_tuning_phase = INVALID_TUNING_PHASE; |
---|
| 2580 | + |
---|
| 2581 | + ret = sdhci_msm_gcc_reset(&pdev->dev, host); |
---|
| 2582 | + if (ret) |
---|
| 2583 | + goto pltfm_free; |
---|
1775 | 2584 | |
---|
1776 | 2585 | /* Setup SDCC bus voter clock. */ |
---|
1777 | 2586 | msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); |
---|
.. | .. |
---|
1803 | 2612 | } |
---|
1804 | 2613 | msm_host->bulk_clks[0].clk = clk; |
---|
1805 | 2614 | |
---|
| 2615 | + /* Check for optional interconnect paths */ |
---|
| 2616 | + ret = dev_pm_opp_of_find_icc_paths(&pdev->dev, NULL); |
---|
| 2617 | + if (ret) |
---|
| 2618 | + goto bus_clk_disable; |
---|
| 2619 | + |
---|
| 2620 | + msm_host->opp_table = dev_pm_opp_set_clkname(&pdev->dev, "core"); |
---|
| 2621 | + if (IS_ERR(msm_host->opp_table)) { |
---|
| 2622 | + ret = PTR_ERR(msm_host->opp_table); |
---|
| 2623 | + goto bus_clk_disable; |
---|
| 2624 | + } |
---|
| 2625 | + |
---|
| 2626 | + /* OPP table is optional */ |
---|
| 2627 | + ret = dev_pm_opp_of_add_table(&pdev->dev); |
---|
| 2628 | + if (ret && ret != -ENODEV) { |
---|
| 2629 | + dev_err(&pdev->dev, "Invalid OPP table in Device tree\n"); |
---|
| 2630 | + goto opp_put_clkname; |
---|
| 2631 | + } |
---|
| 2632 | + |
---|
1806 | 2633 | /* Vote for maximum clock rate for maximum performance */ |
---|
1807 | | - ret = clk_set_rate(clk, INT_MAX); |
---|
| 2634 | + ret = dev_pm_opp_set_rate(&pdev->dev, INT_MAX); |
---|
1808 | 2635 | if (ret) |
---|
1809 | 2636 | dev_warn(&pdev->dev, "core clock boost failed\n"); |
---|
1810 | 2637 | |
---|
.. | .. |
---|
1818 | 2645 | clk = NULL; |
---|
1819 | 2646 | msm_host->bulk_clks[3].clk = clk; |
---|
1820 | 2647 | |
---|
| 2648 | + clk = sdhci_msm_ice_get_clk(&pdev->dev); |
---|
| 2649 | + if (IS_ERR(clk)) |
---|
| 2650 | + clk = NULL; |
---|
| 2651 | + msm_host->bulk_clks[4].clk = clk; |
---|
| 2652 | + |
---|
1821 | 2653 | ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks), |
---|
1822 | 2654 | msm_host->bulk_clks); |
---|
1823 | 2655 | if (ret) |
---|
1824 | | - goto bus_clk_disable; |
---|
| 2656 | + goto opp_cleanup; |
---|
1825 | 2657 | |
---|
1826 | 2658 | /* |
---|
1827 | 2659 | * xo clock is needed for FLL feature of cm_dll. |
---|
.. | .. |
---|
1834 | 2666 | } |
---|
1835 | 2667 | |
---|
1836 | 2668 | if (!msm_host->mci_removed) { |
---|
1837 | | - core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
---|
1838 | | - msm_host->core_mem = devm_ioremap_resource(&pdev->dev, |
---|
1839 | | - core_memres); |
---|
1840 | | - |
---|
| 2669 | + msm_host->core_mem = devm_platform_ioremap_resource(pdev, 1); |
---|
1841 | 2670 | if (IS_ERR(msm_host->core_mem)) { |
---|
1842 | 2671 | ret = PTR_ERR(msm_host->core_mem); |
---|
1843 | 2672 | goto clk_disable; |
---|
.. | .. |
---|
1896 | 2725 | if (core_major == 1 && core_minor >= 0x49) |
---|
1897 | 2726 | msm_host->updated_ddr_cfg = true; |
---|
1898 | 2727 | |
---|
| 2728 | + ret = sdhci_msm_register_vreg(msm_host); |
---|
| 2729 | + if (ret) |
---|
| 2730 | + goto clk_disable; |
---|
| 2731 | + |
---|
1899 | 2732 | /* |
---|
1900 | 2733 | * Power on reset state may trigger power irq if previous status of |
---|
1901 | 2734 | * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq |
---|
.. | .. |
---|
1914 | 2747 | /* Setup IRQ for handling power/voltage tasks with PMIC */ |
---|
1915 | 2748 | msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq"); |
---|
1916 | 2749 | if (msm_host->pwr_irq < 0) { |
---|
1917 | | - dev_err(&pdev->dev, "Get pwr_irq failed (%d)\n", |
---|
1918 | | - msm_host->pwr_irq); |
---|
1919 | 2750 | ret = msm_host->pwr_irq; |
---|
1920 | 2751 | goto clk_disable; |
---|
1921 | 2752 | } |
---|
.. | .. |
---|
1942 | 2773 | MSM_MMC_AUTOSUSPEND_DELAY_MS); |
---|
1943 | 2774 | pm_runtime_use_autosuspend(&pdev->dev); |
---|
1944 | 2775 | |
---|
| 2776 | + host->mmc_host_ops.start_signal_voltage_switch = |
---|
| 2777 | + sdhci_msm_start_signal_voltage_switch; |
---|
1945 | 2778 | host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning; |
---|
1946 | | - ret = sdhci_add_host(host); |
---|
| 2779 | + if (of_property_read_bool(node, "supports-cqe")) |
---|
| 2780 | + ret = sdhci_msm_cqe_add_host(host, pdev); |
---|
| 2781 | + else |
---|
| 2782 | + ret = sdhci_add_host(host); |
---|
1947 | 2783 | if (ret) |
---|
1948 | 2784 | goto pm_runtime_disable; |
---|
1949 | | - sdhci_msm_set_regulator_caps(msm_host); |
---|
1950 | 2785 | |
---|
1951 | 2786 | pm_runtime_mark_last_busy(&pdev->dev); |
---|
1952 | 2787 | pm_runtime_put_autosuspend(&pdev->dev); |
---|
.. | .. |
---|
1960 | 2795 | clk_disable: |
---|
1961 | 2796 | clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks), |
---|
1962 | 2797 | msm_host->bulk_clks); |
---|
| 2798 | +opp_cleanup: |
---|
| 2799 | + dev_pm_opp_of_remove_table(&pdev->dev); |
---|
| 2800 | +opp_put_clkname: |
---|
| 2801 | + dev_pm_opp_put_clkname(msm_host->opp_table); |
---|
1963 | 2802 | bus_clk_disable: |
---|
1964 | 2803 | if (!IS_ERR(msm_host->bus_clk)) |
---|
1965 | 2804 | clk_disable_unprepare(msm_host->bus_clk); |
---|
.. | .. |
---|
1978 | 2817 | |
---|
1979 | 2818 | sdhci_remove_host(host, dead); |
---|
1980 | 2819 | |
---|
| 2820 | + dev_pm_opp_of_remove_table(&pdev->dev); |
---|
| 2821 | + dev_pm_opp_put_clkname(msm_host->opp_table); |
---|
1981 | 2822 | pm_runtime_get_sync(&pdev->dev); |
---|
1982 | 2823 | pm_runtime_disable(&pdev->dev); |
---|
1983 | 2824 | pm_runtime_put_noidle(&pdev->dev); |
---|
.. | .. |
---|
1990 | 2831 | return 0; |
---|
1991 | 2832 | } |
---|
1992 | 2833 | |
---|
1993 | | -#ifdef CONFIG_PM |
---|
1994 | | -static int sdhci_msm_runtime_suspend(struct device *dev) |
---|
| 2834 | +static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev) |
---|
1995 | 2835 | { |
---|
1996 | 2836 | struct sdhci_host *host = dev_get_drvdata(dev); |
---|
1997 | 2837 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
1998 | 2838 | struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
---|
1999 | 2839 | |
---|
| 2840 | + /* Drop the performance vote */ |
---|
| 2841 | + dev_pm_opp_set_rate(dev, 0); |
---|
2000 | 2842 | clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks), |
---|
2001 | 2843 | msm_host->bulk_clks); |
---|
2002 | 2844 | |
---|
2003 | 2845 | return 0; |
---|
2004 | 2846 | } |
---|
2005 | 2847 | |
---|
2006 | | -static int sdhci_msm_runtime_resume(struct device *dev) |
---|
| 2848 | +static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev) |
---|
2007 | 2849 | { |
---|
2008 | 2850 | struct sdhci_host *host = dev_get_drvdata(dev); |
---|
2009 | 2851 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
2010 | 2852 | struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
---|
| 2853 | + int ret; |
---|
2011 | 2854 | |
---|
2012 | | - return clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks), |
---|
| 2855 | + ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks), |
---|
2013 | 2856 | msm_host->bulk_clks); |
---|
| 2857 | + if (ret) |
---|
| 2858 | + return ret; |
---|
| 2859 | + /* |
---|
| 2860 | + * Whenever core-clock is gated dynamically, it's needed to |
---|
| 2861 | + * restore the SDR DLL settings when the clock is ungated. |
---|
| 2862 | + */ |
---|
| 2863 | + if (msm_host->restore_dll_config && msm_host->clk_rate) { |
---|
| 2864 | + ret = sdhci_msm_restore_sdr_dll_config(host); |
---|
| 2865 | + if (ret) |
---|
| 2866 | + return ret; |
---|
| 2867 | + } |
---|
| 2868 | + |
---|
| 2869 | + dev_pm_opp_set_rate(dev, msm_host->clk_rate); |
---|
| 2870 | + |
---|
| 2871 | + return sdhci_msm_ice_resume(msm_host); |
---|
2014 | 2872 | } |
---|
2015 | | -#endif |
---|
2016 | 2873 | |
---|
2017 | 2874 | static const struct dev_pm_ops sdhci_msm_pm_ops = { |
---|
2018 | 2875 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, |
---|
.. | .. |
---|
2029 | 2886 | .name = "sdhci_msm", |
---|
2030 | 2887 | .of_match_table = sdhci_msm_dt_match, |
---|
2031 | 2888 | .pm = &sdhci_msm_pm_ops, |
---|
| 2889 | + .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
---|
2032 | 2890 | }, |
---|
2033 | 2891 | }; |
---|
2034 | 2892 | |
---|