Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: sdhci-of-arasan: Add support for Intel Keem Bay

Intel Keem Bay SoC eMMC/SD/SDIO controller is based on
Arasan SD 3.0 / eMMC 5.1 host controller IP.

However, it does not support 64-bit access as its AXI interface
has 32-bit address ports.

Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad@intel.com>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Link: https://lore.kernel.org/r/20200526062758.17642-3-wan.ahmad.zainie.wan.mohamad@intel.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Wan Ahmad Zainie and committed by
Ulf Hansson
36c6aada ce3fefac

+123
+123
drivers/mmc/host/sdhci-of-arasan.c
··· 75 75 * 76 76 * @baseclkfreq: Where to find corecfg_baseclkfreq 77 77 * @clockmultiplier: Where to find corecfg_clockmultiplier 78 + * @support64b: Where to find SUPPORT64B bit 78 79 * @hiword_update: If true, use HIWORD_UPDATE to access the syscon 79 80 * 80 81 * It's up to the licensee of the Arsan IP block to make these available ··· 85 84 struct sdhci_arasan_soc_ctl_map { 86 85 struct sdhci_arasan_soc_ctl_field baseclkfreq; 87 86 struct sdhci_arasan_soc_ctl_field clockmultiplier; 87 + struct sdhci_arasan_soc_ctl_field support64b; 88 88 bool hiword_update; 89 89 }; 90 90 ··· 183 181 static const struct sdhci_arasan_soc_ctl_map intel_lgm_sdxc_soc_ctl_map = { 184 182 .baseclkfreq = { .reg = 0x80, .width = 8, .shift = 2 }, 185 183 .clockmultiplier = { .reg = 0, .width = -1, .shift = -1 }, 184 + .hiword_update = false, 185 + }; 186 + 187 + static const struct sdhci_arasan_soc_ctl_map intel_keembay_soc_ctl_map = { 188 + .baseclkfreq = { .reg = 0x0, .width = 8, .shift = 14 }, 189 + .clockmultiplier = { .reg = 0x4, .width = 8, .shift = 14 }, 190 + .support64b = { .reg = 0x4, .width = 1, .shift = 24 }, 186 191 .hiword_update = false, 187 192 }; 188 193 ··· 1122 1113 .clk_ops = &arasan_clk_ops, 1123 1114 }; 1124 1115 1116 + static const struct sdhci_pltfm_data sdhci_keembay_emmc_pdata = { 1117 + .ops = &sdhci_arasan_cqe_ops, 1118 + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | 1119 + SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 1120 + SDHCI_QUIRK_NO_LED | 1121 + SDHCI_QUIRK_32BIT_DMA_ADDR | 1122 + SDHCI_QUIRK_32BIT_DMA_SIZE | 1123 + SDHCI_QUIRK_32BIT_ADMA_SIZE, 1124 + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 1125 + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | 1126 + SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | 1127 + SDHCI_QUIRK2_STOP_WITH_TC | 1128 + SDHCI_QUIRK2_BROKEN_64_BIT_DMA, 1129 + }; 1130 + 1131 + static const struct sdhci_pltfm_data sdhci_keembay_sd_pdata = { 1132 + .ops = &sdhci_arasan_ops, 1133 + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | 1134 + SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 1135 + SDHCI_QUIRK_NO_LED | 1136 + SDHCI_QUIRK_32BIT_DMA_ADDR | 1137 + SDHCI_QUIRK_32BIT_DMA_SIZE | 1138 + SDHCI_QUIRK_32BIT_ADMA_SIZE, 1139 + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 1140 + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | 1141 + SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | 1142 + SDHCI_QUIRK2_STOP_WITH_TC | 1143 + SDHCI_QUIRK2_BROKEN_64_BIT_DMA, 1144 + }; 1145 + 1146 + static const struct sdhci_pltfm_data sdhci_keembay_sdio_pdata = { 1147 + .ops = &sdhci_arasan_ops, 1148 + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | 1149 + SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 1150 + SDHCI_QUIRK_NO_LED | 1151 + SDHCI_QUIRK_32BIT_DMA_ADDR | 1152 + SDHCI_QUIRK_32BIT_DMA_SIZE | 1153 + SDHCI_QUIRK_32BIT_ADMA_SIZE, 1154 + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 1155 + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | 1156 + SDHCI_QUIRK2_HOST_OFF_CARD_ON | 1157 + SDHCI_QUIRK2_BROKEN_64_BIT_DMA, 1158 + }; 1159 + 1125 1160 static struct sdhci_arasan_of_data sdhci_arasan_rk3399_data = { 1126 1161 .soc_ctl_map = &rk3399_soc_ctl_map, 1127 1162 .pdata = &sdhci_arasan_cqe_pdata, ··· 1211 1158 .clk_ops = &versal_clk_ops, 1212 1159 }; 1213 1160 1161 + static struct sdhci_arasan_of_data intel_keembay_emmc_data = { 1162 + .soc_ctl_map = &intel_keembay_soc_ctl_map, 1163 + .pdata = &sdhci_keembay_emmc_pdata, 1164 + }; 1165 + 1166 + static struct sdhci_arasan_of_data intel_keembay_sd_data = { 1167 + .soc_ctl_map = &intel_keembay_soc_ctl_map, 1168 + .pdata = &sdhci_keembay_sd_pdata, 1169 + }; 1170 + 1171 + static struct sdhci_arasan_of_data intel_keembay_sdio_data = { 1172 + .soc_ctl_map = &intel_keembay_soc_ctl_map, 1173 + .pdata = &sdhci_keembay_sdio_pdata, 1174 + }; 1175 + 1214 1176 static const struct of_device_id sdhci_arasan_of_match[] = { 1215 1177 /* SoC-specific compatible strings w/ soc_ctl_map */ 1216 1178 { ··· 1239 1171 { 1240 1172 .compatible = "intel,lgm-sdhci-5.1-sdxc", 1241 1173 .data = &intel_lgm_sdxc_data, 1174 + }, 1175 + { 1176 + .compatible = "intel,keembay-sdhci-5.1-emmc", 1177 + .data = &intel_keembay_emmc_data, 1178 + }, 1179 + { 1180 + .compatible = "intel,keembay-sdhci-5.1-sd", 1181 + .data = &intel_keembay_sd_data, 1182 + }, 1183 + { 1184 + .compatible = "intel,keembay-sdhci-5.1-sdio", 1185 + .data = &intel_keembay_sdio_data, 1242 1186 }, 1243 1187 /* Generic compatible below here */ 1244 1188 { ··· 1393 1313 return; 1394 1314 1395 1315 of_clk_del_provider(dev->of_node); 1316 + } 1317 + 1318 + /** 1319 + * sdhci_arasan_update_support64b - Set SUPPORT_64B (64-bit System Bus Support) 1320 + * 1321 + * This should be set based on the System Address Bus. 1322 + * 0: the Core supports only 32-bit System Address Bus. 1323 + * 1: the Core supports 64-bit System Address Bus. 1324 + * 1325 + * NOTES: 1326 + * - For Keem Bay, it is required to clear this bit. Its default value is 1'b1. 1327 + * Keem Bay does not support 64-bit access. 1328 + * 1329 + * @host The sdhci_host 1330 + */ 1331 + static void sdhci_arasan_update_support64b(struct sdhci_host *host, u32 value) 1332 + { 1333 + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1334 + struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); 1335 + const struct sdhci_arasan_soc_ctl_map *soc_ctl_map = 1336 + sdhci_arasan->soc_ctl_map; 1337 + 1338 + /* Having a map is optional */ 1339 + if (!soc_ctl_map) 1340 + return; 1341 + 1342 + /* If we have a map, we expect to have a syscon */ 1343 + if (!sdhci_arasan->soc_ctl_base) { 1344 + pr_warn("%s: Have regmap, but no soc-ctl-syscon\n", 1345 + mmc_hostname(host->mmc)); 1346 + return; 1347 + } 1348 + 1349 + sdhci_arasan_syscon_write(host, &soc_ctl_map->support64b, value); 1396 1350 } 1397 1351 1398 1352 /** ··· 1600 1486 if (of_device_is_compatible(pdev->dev.of_node, 1601 1487 "rockchip,rk3399-sdhci-5.1")) 1602 1488 sdhci_arasan_update_clockmultiplier(host, 0x0); 1489 + 1490 + if (of_device_is_compatible(np, "intel,keembay-sdhci-5.1-emmc") || 1491 + of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sd") || 1492 + of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sdio")) { 1493 + sdhci_arasan_update_clockmultiplier(host, 0x0); 1494 + sdhci_arasan_update_support64b(host, 0x0); 1495 + 1496 + host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; 1497 + } 1603 1498 1604 1499 sdhci_arasan_update_baseclkfreq(host); 1605 1500