1111 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * sdhci_am654.c - SDHCI driver for TI's AM654 SOCs4 *5 * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com6 *7 */8#include <linux/clk.h>9#include <linux/iopoll.h>10#include <linux/of.h>11#include <linux/module.h>12#include <linux/pm_runtime.h>13#include <linux/property.h>14#include <linux/regmap.h>15#include <linux/sys_soc.h>16 17#include "cqhci.h"18#include "sdhci-cqhci.h"19#include "sdhci-pltfm.h"20 21/* CTL_CFG Registers */22#define CTL_CFG_2 0x1423#define CTL_CFG_3 0x1824 25#define SLOTTYPE_MASK GENMASK(31, 30)26#define SLOTTYPE_EMBEDDED BIT(30)27#define TUNINGFORSDR50_MASK BIT(13)28 29/* PHY Registers */30#define PHY_CTRL1 0x10031#define PHY_CTRL2 0x10432#define PHY_CTRL3 0x10833#define PHY_CTRL4 0x10C34#define PHY_CTRL5 0x11035#define PHY_CTRL6 0x11436#define PHY_STAT1 0x13037#define PHY_STAT2 0x13438 39#define IOMUX_ENABLE_SHIFT 3140#define IOMUX_ENABLE_MASK BIT(IOMUX_ENABLE_SHIFT)41#define OTAPDLYENA_SHIFT 2042#define OTAPDLYENA_MASK BIT(OTAPDLYENA_SHIFT)43#define OTAPDLYSEL_SHIFT 1244#define OTAPDLYSEL_MASK GENMASK(15, 12)45#define STRBSEL_SHIFT 2446#define STRBSEL_4BIT_MASK GENMASK(27, 24)47#define STRBSEL_8BIT_MASK GENMASK(31, 24)48#define SEL50_SHIFT 849#define SEL50_MASK BIT(SEL50_SHIFT)50#define SEL100_SHIFT 951#define SEL100_MASK BIT(SEL100_SHIFT)52#define FREQSEL_SHIFT 853#define FREQSEL_MASK GENMASK(10, 8)54#define CLKBUFSEL_SHIFT 055#define CLKBUFSEL_MASK GENMASK(2, 0)56#define DLL_TRIM_ICP_SHIFT 457#define DLL_TRIM_ICP_MASK GENMASK(7, 4)58#define DR_TY_SHIFT 2059#define DR_TY_MASK GENMASK(22, 20)60#define ENDLL_SHIFT 161#define ENDLL_MASK BIT(ENDLL_SHIFT)62#define DLLRDY_SHIFT 063#define DLLRDY_MASK BIT(DLLRDY_SHIFT)64#define PDB_SHIFT 065#define PDB_MASK BIT(PDB_SHIFT)66#define CALDONE_SHIFT 167#define CALDONE_MASK BIT(CALDONE_SHIFT)68#define RETRIM_SHIFT 1769#define RETRIM_MASK BIT(RETRIM_SHIFT)70#define SELDLYTXCLK_SHIFT 1771#define SELDLYTXCLK_MASK BIT(SELDLYTXCLK_SHIFT)72#define SELDLYRXCLK_SHIFT 1673#define SELDLYRXCLK_MASK BIT(SELDLYRXCLK_SHIFT)74#define ITAPDLYSEL_SHIFT 075#define ITAPDLYSEL_MASK GENMASK(4, 0)76#define ITAPDLYENA_SHIFT 877#define ITAPDLYENA_MASK BIT(ITAPDLYENA_SHIFT)78#define ITAPCHGWIN_SHIFT 979#define ITAPCHGWIN_MASK BIT(ITAPCHGWIN_SHIFT)80 81#define DRIVER_STRENGTH_50_OHM 0x082#define DRIVER_STRENGTH_33_OHM 0x183#define DRIVER_STRENGTH_66_OHM 0x284#define DRIVER_STRENGTH_100_OHM 0x385#define DRIVER_STRENGTH_40_OHM 0x486 87#define CLOCK_TOO_SLOW_HZ 5000000088#define SDHCI_AM654_AUTOSUSPEND_DELAY -189#define RETRY_TUNING_MAX 1090 91/* Command Queue Host Controller Interface Base address */92#define SDHCI_AM654_CQE_BASE_ADDR 0x20093 94static const struct regmap_config sdhci_am654_regmap_config = {95 .reg_bits = 32,96 .val_bits = 32,97 .reg_stride = 4,98 .fast_io = true,99};100 101struct timing_data {102 const char *otap_binding;103 const char *itap_binding;104 u32 capability;105};106 107static const struct timing_data td[] = {108 [MMC_TIMING_LEGACY] = {"ti,otap-del-sel-legacy",109 "ti,itap-del-sel-legacy",110 0},111 [MMC_TIMING_MMC_HS] = {"ti,otap-del-sel-mmc-hs",112 "ti,itap-del-sel-mmc-hs",113 MMC_CAP_MMC_HIGHSPEED},114 [MMC_TIMING_SD_HS] = {"ti,otap-del-sel-sd-hs",115 "ti,itap-del-sel-sd-hs",116 MMC_CAP_SD_HIGHSPEED},117 [MMC_TIMING_UHS_SDR12] = {"ti,otap-del-sel-sdr12",118 "ti,itap-del-sel-sdr12",119 MMC_CAP_UHS_SDR12},120 [MMC_TIMING_UHS_SDR25] = {"ti,otap-del-sel-sdr25",121 "ti,itap-del-sel-sdr25",122 MMC_CAP_UHS_SDR25},123 [MMC_TIMING_UHS_SDR50] = {"ti,otap-del-sel-sdr50",124 NULL,125 MMC_CAP_UHS_SDR50},126 [MMC_TIMING_UHS_SDR104] = {"ti,otap-del-sel-sdr104",127 NULL,128 MMC_CAP_UHS_SDR104},129 [MMC_TIMING_UHS_DDR50] = {"ti,otap-del-sel-ddr50",130 NULL,131 MMC_CAP_UHS_DDR50},132 [MMC_TIMING_MMC_DDR52] = {"ti,otap-del-sel-ddr52",133 "ti,itap-del-sel-ddr52",134 MMC_CAP_DDR},135 [MMC_TIMING_MMC_HS200] = {"ti,otap-del-sel-hs200",136 NULL,137 MMC_CAP2_HS200},138 [MMC_TIMING_MMC_HS400] = {"ti,otap-del-sel-hs400",139 NULL,140 MMC_CAP2_HS400},141};142 143struct sdhci_am654_data {144 struct regmap *base;145 u32 otap_del_sel[ARRAY_SIZE(td)];146 u32 itap_del_sel[ARRAY_SIZE(td)];147 u32 itap_del_ena[ARRAY_SIZE(td)];148 int clkbuf_sel;149 int trm_icp;150 int drv_strength;151 int strb_sel;152 u32 flags;153 u32 quirks;154 bool dll_enable;155 u32 tuning_loop;156 157#define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0)158};159 160struct window {161 u8 start;162 u8 end;163 u8 length;164};165 166struct sdhci_am654_driver_data {167 const struct sdhci_pltfm_data *pdata;168 u32 flags;169#define IOMUX_PRESENT (1 << 0)170#define FREQSEL_2_BIT (1 << 1)171#define STRBSEL_4_BIT (1 << 2)172#define DLL_PRESENT (1 << 3)173#define DLL_CALIB (1 << 4)174};175 176static void sdhci_am654_setup_dll(struct sdhci_host *host, unsigned int clock)177{178 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);179 struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);180 int sel50, sel100, freqsel;181 u32 mask, val;182 int ret;183 184 /* Disable delay chain mode */185 regmap_update_bits(sdhci_am654->base, PHY_CTRL5,186 SELDLYTXCLK_MASK | SELDLYRXCLK_MASK, 0);187 188 if (sdhci_am654->flags & FREQSEL_2_BIT) {189 switch (clock) {190 case 200000000:191 sel50 = 0;192 sel100 = 0;193 break;194 case 100000000:195 sel50 = 0;196 sel100 = 1;197 break;198 default:199 sel50 = 1;200 sel100 = 0;201 }202 203 /* Configure PHY DLL frequency */204 mask = SEL50_MASK | SEL100_MASK;205 val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);206 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val);207 208 } else {209 switch (clock) {210 case 200000000:211 freqsel = 0x0;212 break;213 default:214 freqsel = 0x4;215 }216 217 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, FREQSEL_MASK,218 freqsel << FREQSEL_SHIFT);219 }220 /* Configure DLL TRIM */221 mask = DLL_TRIM_ICP_MASK;222 val = sdhci_am654->trm_icp << DLL_TRIM_ICP_SHIFT;223 224 /* Configure DLL driver strength */225 mask |= DR_TY_MASK;226 val |= sdhci_am654->drv_strength << DR_TY_SHIFT;227 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, mask, val);228 229 /* Enable DLL */230 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK,231 0x1 << ENDLL_SHIFT);232 /*233 * Poll for DLL ready. Use a one second timeout.234 * Works in all experiments done so far235 */236 ret = regmap_read_poll_timeout(sdhci_am654->base, PHY_STAT1, val,237 val & DLLRDY_MASK, 1000, 1000000);238 if (ret) {239 dev_err(mmc_dev(host->mmc), "DLL failed to relock\n");240 return;241 }242}243 244static void sdhci_am654_write_itapdly(struct sdhci_am654_data *sdhci_am654,245 u32 itapdly, u32 enable)246{247 /* Set ITAPCHGWIN before writing to ITAPDLY */248 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK,249 1 << ITAPCHGWIN_SHIFT);250 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK,251 enable << ITAPDLYENA_SHIFT);252 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYSEL_MASK,253 itapdly << ITAPDLYSEL_SHIFT);254 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);255}256 257static void sdhci_am654_setup_delay_chain(struct sdhci_am654_data *sdhci_am654,258 unsigned char timing)259{260 u32 mask, val;261 262 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0);263 264 val = 1 << SELDLYTXCLK_SHIFT | 1 << SELDLYRXCLK_SHIFT;265 mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK;266 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val);267 268 sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing],269 sdhci_am654->itap_del_ena[timing]);270}271 272static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)273{274 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);275 struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);276 unsigned char timing = host->mmc->ios.timing;277 u32 otap_del_sel;278 u32 mask, val;279 280 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0);281 282 sdhci_set_clock(host, clock);283 284 /* Setup Output TAP delay */285 otap_del_sel = sdhci_am654->otap_del_sel[timing];286 287 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;288 val = (0x1 << OTAPDLYENA_SHIFT) |289 (otap_del_sel << OTAPDLYSEL_SHIFT);290 291 /* Write to STRBSEL for HS400 speed mode */292 if (timing == MMC_TIMING_MMC_HS400) {293 if (sdhci_am654->flags & STRBSEL_4_BIT)294 mask |= STRBSEL_4BIT_MASK;295 else296 mask |= STRBSEL_8BIT_MASK;297 298 val |= sdhci_am654->strb_sel << STRBSEL_SHIFT;299 }300 301 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val);302 303 if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) {304 sdhci_am654_setup_dll(host, clock);305 sdhci_am654->dll_enable = true;306 307 if (timing == MMC_TIMING_MMC_HS400) {308 sdhci_am654->itap_del_ena[timing] = 0x1;309 sdhci_am654->itap_del_sel[timing] = sdhci_am654->itap_del_sel[timing - 1];310 }311 312 sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing],313 sdhci_am654->itap_del_ena[timing]);314 } else {315 sdhci_am654_setup_delay_chain(sdhci_am654, timing);316 sdhci_am654->dll_enable = false;317 }318 319 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK,320 sdhci_am654->clkbuf_sel);321}322 323static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host,324 unsigned int clock)325{326 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);327 struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);328 unsigned char timing = host->mmc->ios.timing;329 u32 otap_del_sel;330 u32 itap_del_ena;331 u32 itap_del_sel;332 u32 mask, val;333 334 /* Setup Output TAP delay */335 otap_del_sel = sdhci_am654->otap_del_sel[timing];336 337 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;338 val = (0x1 << OTAPDLYENA_SHIFT) |339 (otap_del_sel << OTAPDLYSEL_SHIFT);340 341 /* Setup Input TAP delay */342 itap_del_ena = sdhci_am654->itap_del_ena[timing];343 itap_del_sel = sdhci_am654->itap_del_sel[timing];344 345 mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;346 val |= (itap_del_ena << ITAPDLYENA_SHIFT) |347 (itap_del_sel << ITAPDLYSEL_SHIFT);348 349 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK,350 1 << ITAPCHGWIN_SHIFT);351 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val);352 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);353 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK,354 sdhci_am654->clkbuf_sel);355 356 sdhci_set_clock(host, clock);357}358 359static u8 sdhci_am654_write_power_on(struct sdhci_host *host, u8 val, int reg)360{361 writeb(val, host->ioaddr + reg);362 usleep_range(1000, 10000);363 return readb(host->ioaddr + reg);364}365 366#define MAX_POWER_ON_TIMEOUT 1500000 /* us */367static void sdhci_am654_write_b(struct sdhci_host *host, u8 val, int reg)368{369 unsigned char timing = host->mmc->ios.timing;370 u8 pwr;371 int ret;372 373 if (reg == SDHCI_HOST_CONTROL) {374 switch (timing) {375 /*376 * According to the data manual, HISPD bit377 * should not be set in these speed modes.378 */379 case MMC_TIMING_SD_HS:380 case MMC_TIMING_MMC_HS:381 val &= ~SDHCI_CTRL_HISPD;382 }383 }384 385 writeb(val, host->ioaddr + reg);386 if (reg == SDHCI_POWER_CONTROL && (val & SDHCI_POWER_ON)) {387 /*388 * Power on will not happen until the card detect debounce389 * timer expires. Wait at least 1.5 seconds for the power on390 * bit to be set391 */392 ret = read_poll_timeout(sdhci_am654_write_power_on, pwr,393 pwr & SDHCI_POWER_ON, 0,394 MAX_POWER_ON_TIMEOUT, false, host, val,395 reg);396 if (ret)397 dev_info(mmc_dev(host->mmc), "Power on failed\n");398 }399}400 401static void sdhci_am654_reset(struct sdhci_host *host, u8 mask)402{403 u8 ctrl;404 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);405 struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);406 407 sdhci_and_cqhci_reset(host, mask);408 409 if (sdhci_am654->quirks & SDHCI_AM654_QUIRK_FORCE_CDTEST) {410 ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);411 ctrl |= SDHCI_CTRL_CDTEST_INS | SDHCI_CTRL_CDTEST_EN;412 sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);413 }414}415 416static int sdhci_am654_execute_tuning(struct mmc_host *mmc, u32 opcode)417{418 struct sdhci_host *host = mmc_priv(mmc);419 int err = sdhci_execute_tuning(mmc, opcode);420 421 if (err)422 return err;423 /*424 * Tuning data remains in the buffer after tuning.425 * Do a command and data reset to get rid of it426 */427 sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);428 429 return 0;430}431 432static u32 sdhci_am654_cqhci_irq(struct sdhci_host *host, u32 intmask)433{434 int cmd_error = 0;435 int data_error = 0;436 437 if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))438 return intmask;439 440 cqhci_irq(host->mmc, intmask, cmd_error, data_error);441 442 return 0;443}444 445#define ITAPDLY_LENGTH 32446#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1)447 448static int sdhci_am654_calculate_itap(struct sdhci_host *host, struct window449 *fail_window, u8 num_fails, bool circular_buffer)450{451 u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0;452 u8 first_fail_start = 0, last_fail_end = 0;453 struct device *dev = mmc_dev(host->mmc);454 struct window pass_window = {0, 0, 0};455 int prev_fail_end = -1;456 u8 i;457 458 if (!num_fails) {459 /* Retry tuning */460 dev_dbg(dev, "No failing region found, retry tuning\n");461 return -1;462 }463 464 if (fail_window->length == ITAPDLY_LENGTH) {465 /* Retry tuning */466 dev_dbg(dev, "No passing itapdly, retry tuning\n");467 return -1;468 }469 470 first_fail_start = fail_window->start;471 last_fail_end = fail_window[num_fails - 1].end;472 473 for (i = 0; i < num_fails; i++) {474 start_fail = fail_window[i].start;475 end_fail = fail_window[i].end;476 pass_length = start_fail - (prev_fail_end + 1);477 478 if (pass_length > pass_window.length) {479 pass_window.start = prev_fail_end + 1;480 pass_window.length = pass_length;481 }482 prev_fail_end = end_fail;483 }484 485 if (!circular_buffer)486 pass_length = ITAPDLY_LAST_INDEX - last_fail_end;487 else488 pass_length = ITAPDLY_LAST_INDEX - last_fail_end + first_fail_start;489 490 if (pass_length > pass_window.length) {491 pass_window.start = last_fail_end + 1;492 pass_window.length = pass_length;493 }494 495 if (!circular_buffer)496 itap = pass_window.start + (pass_window.length >> 1);497 else498 itap = (pass_window.start + (pass_window.length >> 1)) % ITAPDLY_LENGTH;499 500 return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap;501}502 503static int sdhci_am654_do_tuning(struct sdhci_host *host,504 u32 opcode)505{506 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);507 struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);508 unsigned char timing = host->mmc->ios.timing;509 struct window fail_window[ITAPDLY_LENGTH];510 struct device *dev = mmc_dev(host->mmc);511 u8 curr_pass, itap;512 u8 fail_index = 0;513 u8 prev_pass = 1;514 515 memset(fail_window, 0, sizeof(fail_window));516 517 /* Enable ITAPDLY */518 sdhci_am654->itap_del_ena[timing] = 0x1;519 520 for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {521 sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]);522 523 curr_pass = !mmc_send_tuning(host->mmc, opcode, NULL);524 525 if (!curr_pass && prev_pass)526 fail_window[fail_index].start = itap;527 528 if (!curr_pass) {529 fail_window[fail_index].end = itap;530 fail_window[fail_index].length++;531 dev_dbg(dev, "Failed itapdly=%d\n", itap);532 }533 534 if (curr_pass && !prev_pass)535 fail_index++;536 537 prev_pass = curr_pass;538 }539 540 if (fail_window[fail_index].length != 0)541 fail_index++;542 543 return sdhci_am654_calculate_itap(host, fail_window, fail_index,544 sdhci_am654->dll_enable);545}546 547static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host,548 u32 opcode)549{550 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);551 struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);552 unsigned char timing = host->mmc->ios.timing;553 struct device *dev = mmc_dev(host->mmc);554 int itapdly;555 556 do {557 itapdly = sdhci_am654_do_tuning(host, opcode);558 if (itapdly >= 0)559 break;560 } while (++sdhci_am654->tuning_loop < RETRY_TUNING_MAX);561 562 if (itapdly < 0) {563 dev_err(dev, "Failed to find itapdly, fail tuning\n");564 return -1;565 }566 567 dev_dbg(dev, "Passed tuning, final itapdly=%d\n", itapdly);568 sdhci_am654_write_itapdly(sdhci_am654, itapdly, sdhci_am654->itap_del_ena[timing]);569 /* Save ITAPDLY */570 sdhci_am654->itap_del_sel[timing] = itapdly;571 572 return 0;573}574 575static const struct sdhci_ops sdhci_am654_ops = {576 .platform_execute_tuning = sdhci_am654_platform_execute_tuning,577 .get_max_clock = sdhci_pltfm_clk_get_max_clock,578 .get_timeout_clock = sdhci_pltfm_clk_get_max_clock,579 .set_uhs_signaling = sdhci_set_uhs_signaling,580 .set_bus_width = sdhci_set_bus_width,581 .set_power = sdhci_set_power_and_bus_voltage,582 .set_clock = sdhci_am654_set_clock,583 .write_b = sdhci_am654_write_b,584 .irq = sdhci_am654_cqhci_irq,585 .reset = sdhci_and_cqhci_reset,586};587 588static const struct sdhci_pltfm_data sdhci_am654_pdata = {589 .ops = &sdhci_am654_ops,590 .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,591 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,592};593 594static const struct sdhci_am654_driver_data sdhci_am654_sr1_drvdata = {595 .pdata = &sdhci_am654_pdata,596 .flags = IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT | DLL_PRESENT |597 DLL_CALIB,598};599 600static const struct sdhci_am654_driver_data sdhci_am654_drvdata = {601 .pdata = &sdhci_am654_pdata,602 .flags = IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT | DLL_PRESENT,603};604 605static const struct sdhci_ops sdhci_j721e_8bit_ops = {606 .platform_execute_tuning = sdhci_am654_platform_execute_tuning,607 .get_max_clock = sdhci_pltfm_clk_get_max_clock,608 .get_timeout_clock = sdhci_pltfm_clk_get_max_clock,609 .set_uhs_signaling = sdhci_set_uhs_signaling,610 .set_bus_width = sdhci_set_bus_width,611 .set_power = sdhci_set_power_and_bus_voltage,612 .set_clock = sdhci_am654_set_clock,613 .write_b = sdhci_am654_write_b,614 .irq = sdhci_am654_cqhci_irq,615 .reset = sdhci_and_cqhci_reset,616};617 618static const struct sdhci_pltfm_data sdhci_j721e_8bit_pdata = {619 .ops = &sdhci_j721e_8bit_ops,620 .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,621 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,622};623 624static const struct sdhci_am654_driver_data sdhci_j721e_8bit_drvdata = {625 .pdata = &sdhci_j721e_8bit_pdata,626 .flags = DLL_PRESENT | DLL_CALIB,627};628 629static const struct sdhci_ops sdhci_j721e_4bit_ops = {630 .platform_execute_tuning = sdhci_am654_platform_execute_tuning,631 .get_max_clock = sdhci_pltfm_clk_get_max_clock,632 .get_timeout_clock = sdhci_pltfm_clk_get_max_clock,633 .set_uhs_signaling = sdhci_set_uhs_signaling,634 .set_bus_width = sdhci_set_bus_width,635 .set_power = sdhci_set_power_and_bus_voltage,636 .set_clock = sdhci_j721e_4bit_set_clock,637 .write_b = sdhci_am654_write_b,638 .irq = sdhci_am654_cqhci_irq,639 .reset = sdhci_am654_reset,640};641 642static const struct sdhci_pltfm_data sdhci_j721e_4bit_pdata = {643 .ops = &sdhci_j721e_4bit_ops,644 .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,645 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,646};647 648static const struct sdhci_am654_driver_data sdhci_j721e_4bit_drvdata = {649 .pdata = &sdhci_j721e_4bit_pdata,650 .flags = IOMUX_PRESENT,651};652 653static const struct soc_device_attribute sdhci_am654_devices[] = {654 { .family = "AM65X",655 .revision = "SR1.0",656 .data = &sdhci_am654_sr1_drvdata657 },658 {/* sentinel */}659};660 661static void sdhci_am654_dumpregs(struct mmc_host *mmc)662{663 sdhci_dumpregs(mmc_priv(mmc));664}665 666static const struct cqhci_host_ops sdhci_am654_cqhci_ops = {667 .enable = sdhci_cqe_enable,668 .disable = sdhci_cqe_disable,669 .dumpregs = sdhci_am654_dumpregs,670};671 672static int sdhci_am654_cqe_add_host(struct sdhci_host *host)673{674 struct cqhci_host *cq_host;675 676 cq_host = devm_kzalloc(mmc_dev(host->mmc), sizeof(struct cqhci_host),677 GFP_KERNEL);678 if (!cq_host)679 return -ENOMEM;680 681 cq_host->mmio = host->ioaddr + SDHCI_AM654_CQE_BASE_ADDR;682 cq_host->quirks |= CQHCI_QUIRK_SHORT_TXFR_DESC_SZ;683 cq_host->caps |= CQHCI_TASK_DESC_SZ_128;684 cq_host->ops = &sdhci_am654_cqhci_ops;685 686 host->mmc->caps2 |= MMC_CAP2_CQE;687 688 return cqhci_init(cq_host, host->mmc, 1);689}690 691static int sdhci_am654_get_otap_delay(struct sdhci_host *host,692 struct sdhci_am654_data *sdhci_am654)693{694 struct device *dev = mmc_dev(host->mmc);695 int i;696 int ret;697 698 for (i = MMC_TIMING_LEGACY; i <= MMC_TIMING_MMC_HS400; i++) {699 700 ret = device_property_read_u32(dev, td[i].otap_binding,701 &sdhci_am654->otap_del_sel[i]);702 if (ret) {703 if (i == MMC_TIMING_LEGACY) {704 dev_err(dev, "Couldn't find mandatory ti,otap-del-sel-legacy\n");705 return ret;706 }707 dev_dbg(dev, "Couldn't find %s\n",708 td[i].otap_binding);709 /*710 * Remove the corresponding capability711 * if an otap-del-sel value is not found712 */713 if (i <= MMC_TIMING_MMC_DDR52)714 host->mmc->caps &= ~td[i].capability;715 else716 host->mmc->caps2 &= ~td[i].capability;717 }718 719 if (td[i].itap_binding) {720 ret = device_property_read_u32(dev, td[i].itap_binding,721 &sdhci_am654->itap_del_sel[i]);722 if (!ret)723 sdhci_am654->itap_del_ena[i] = 0x1;724 }725 }726 727 return 0;728}729 730static int sdhci_am654_init(struct sdhci_host *host)731{732 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);733 struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);734 u32 ctl_cfg_2 = 0;735 u32 mask;736 u32 val;737 int ret;738 739 /* Reset OTAP to default value */740 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;741 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, 0x0);742 743 if (sdhci_am654->flags & DLL_CALIB) {744 regmap_read(sdhci_am654->base, PHY_STAT1, &val);745 if (~val & CALDONE_MASK) {746 /* Calibrate IO lines */747 regmap_update_bits(sdhci_am654->base, PHY_CTRL1,748 PDB_MASK, PDB_MASK);749 ret = regmap_read_poll_timeout(sdhci_am654->base,750 PHY_STAT1, val,751 val & CALDONE_MASK,752 1, 20);753 if (ret)754 return ret;755 }756 }757 758 /* Enable pins by setting IO mux to 0 */759 if (sdhci_am654->flags & IOMUX_PRESENT)760 regmap_update_bits(sdhci_am654->base, PHY_CTRL1,761 IOMUX_ENABLE_MASK, 0);762 763 /* Set slot type based on SD or eMMC */764 if (host->mmc->caps & MMC_CAP_NONREMOVABLE)765 ctl_cfg_2 = SLOTTYPE_EMBEDDED;766 767 regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK,768 ctl_cfg_2);769 770 /* Enable tuning for SDR50 */771 regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK,772 TUNINGFORSDR50_MASK);773 774 /* Use to re-execute tuning */775 sdhci_am654->tuning_loop = 0;776 777 ret = sdhci_setup_host(host);778 if (ret)779 return ret;780 781 ret = sdhci_am654_cqe_add_host(host);782 if (ret)783 goto err_cleanup_host;784 785 ret = sdhci_am654_get_otap_delay(host, sdhci_am654);786 if (ret)787 goto err_cleanup_host;788 789 ret = __sdhci_add_host(host);790 if (ret)791 goto err_cleanup_host;792 793 return 0;794 795err_cleanup_host:796 sdhci_cleanup_host(host);797 return ret;798}799 800static int sdhci_am654_get_of_property(struct platform_device *pdev,801 struct sdhci_am654_data *sdhci_am654)802{803 struct device *dev = &pdev->dev;804 int drv_strength;805 int ret;806 807 if (sdhci_am654->flags & DLL_PRESENT) {808 ret = device_property_read_u32(dev, "ti,trm-icp",809 &sdhci_am654->trm_icp);810 if (ret)811 return ret;812 813 ret = device_property_read_u32(dev, "ti,driver-strength-ohm",814 &drv_strength);815 if (ret)816 return ret;817 818 switch (drv_strength) {819 case 50:820 sdhci_am654->drv_strength = DRIVER_STRENGTH_50_OHM;821 break;822 case 33:823 sdhci_am654->drv_strength = DRIVER_STRENGTH_33_OHM;824 break;825 case 66:826 sdhci_am654->drv_strength = DRIVER_STRENGTH_66_OHM;827 break;828 case 100:829 sdhci_am654->drv_strength = DRIVER_STRENGTH_100_OHM;830 break;831 case 40:832 sdhci_am654->drv_strength = DRIVER_STRENGTH_40_OHM;833 break;834 default:835 dev_err(dev, "Invalid driver strength\n");836 return -EINVAL;837 }838 }839 840 device_property_read_u32(dev, "ti,strobe-sel", &sdhci_am654->strb_sel);841 device_property_read_u32(dev, "ti,clkbuf-sel",842 &sdhci_am654->clkbuf_sel);843 844 if (device_property_read_bool(dev, "ti,fails-without-test-cd"))845 sdhci_am654->quirks |= SDHCI_AM654_QUIRK_FORCE_CDTEST;846 847 sdhci_get_of_property(pdev);848 849 return 0;850}851 852static const struct of_device_id sdhci_am654_of_match[] = {853 {854 .compatible = "ti,am654-sdhci-5.1",855 .data = &sdhci_am654_drvdata,856 },857 {858 .compatible = "ti,j721e-sdhci-8bit",859 .data = &sdhci_j721e_8bit_drvdata,860 },861 {862 .compatible = "ti,j721e-sdhci-4bit",863 .data = &sdhci_j721e_4bit_drvdata,864 },865 {866 .compatible = "ti,am64-sdhci-8bit",867 .data = &sdhci_j721e_8bit_drvdata,868 },869 {870 .compatible = "ti,am64-sdhci-4bit",871 .data = &sdhci_j721e_4bit_drvdata,872 },873 {874 .compatible = "ti,am62-sdhci",875 .data = &sdhci_j721e_4bit_drvdata,876 },877 { /* sentinel */ }878};879MODULE_DEVICE_TABLE(of, sdhci_am654_of_match);880 881static int sdhci_am654_probe(struct platform_device *pdev)882{883 const struct sdhci_am654_driver_data *drvdata;884 const struct soc_device_attribute *soc;885 struct sdhci_pltfm_host *pltfm_host;886 struct sdhci_am654_data *sdhci_am654;887 const struct of_device_id *match;888 struct sdhci_host *host;889 struct clk *clk_xin;890 struct device *dev = &pdev->dev;891 void __iomem *base;892 int ret;893 894 match = of_match_node(sdhci_am654_of_match, pdev->dev.of_node);895 drvdata = match->data;896 897 /* Update drvdata based on SoC revision */898 soc = soc_device_match(sdhci_am654_devices);899 if (soc && soc->data)900 drvdata = soc->data;901 902 host = sdhci_pltfm_init(pdev, drvdata->pdata, sizeof(*sdhci_am654));903 if (IS_ERR(host))904 return PTR_ERR(host);905 906 pltfm_host = sdhci_priv(host);907 sdhci_am654 = sdhci_pltfm_priv(pltfm_host);908 sdhci_am654->flags = drvdata->flags;909 910 clk_xin = devm_clk_get(dev, "clk_xin");911 if (IS_ERR(clk_xin)) {912 dev_err(dev, "clk_xin clock not found.\n");913 ret = PTR_ERR(clk_xin);914 goto err_pltfm_free;915 }916 917 pltfm_host->clk = clk_xin;918 919 base = devm_platform_ioremap_resource(pdev, 1);920 if (IS_ERR(base)) {921 ret = PTR_ERR(base);922 goto err_pltfm_free;923 }924 925 sdhci_am654->base = devm_regmap_init_mmio(dev, base,926 &sdhci_am654_regmap_config);927 if (IS_ERR(sdhci_am654->base)) {928 dev_err(dev, "Failed to initialize regmap\n");929 ret = PTR_ERR(sdhci_am654->base);930 goto err_pltfm_free;931 }932 933 ret = sdhci_am654_get_of_property(pdev, sdhci_am654);934 if (ret)935 goto err_pltfm_free;936 937 ret = mmc_of_parse(host->mmc);938 if (ret) {939 dev_err_probe(dev, ret, "parsing dt failed\n");940 goto err_pltfm_free;941 }942 943 host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning;944 945 pm_runtime_get_noresume(dev);946 ret = pm_runtime_set_active(dev);947 if (ret)948 goto pm_put;949 pm_runtime_enable(dev);950 ret = clk_prepare_enable(pltfm_host->clk);951 if (ret)952 goto pm_disable;953 954 ret = sdhci_am654_init(host);955 if (ret)956 goto clk_disable;957 958 /* Setting up autosuspend */959 pm_runtime_set_autosuspend_delay(dev, SDHCI_AM654_AUTOSUSPEND_DELAY);960 pm_runtime_use_autosuspend(dev);961 pm_runtime_mark_last_busy(dev);962 pm_runtime_put_autosuspend(dev);963 return 0;964 965clk_disable:966 clk_disable_unprepare(pltfm_host->clk);967pm_disable:968 pm_runtime_disable(dev);969pm_put:970 pm_runtime_put_noidle(dev);971err_pltfm_free:972 sdhci_pltfm_free(pdev);973 return ret;974}975 976static void sdhci_am654_remove(struct platform_device *pdev)977{978 struct sdhci_host *host = platform_get_drvdata(pdev);979 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);980 struct device *dev = &pdev->dev;981 int ret;982 983 ret = pm_runtime_get_sync(dev);984 if (ret < 0)985 dev_err(dev, "pm_runtime_get_sync() Failed\n");986 987 sdhci_remove_host(host, true);988 clk_disable_unprepare(pltfm_host->clk);989 pm_runtime_disable(dev);990 pm_runtime_put_noidle(dev);991 sdhci_pltfm_free(pdev);992}993 994#ifdef CONFIG_PM995static int sdhci_am654_restore(struct sdhci_host *host)996{997 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);998 struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);999 u32 ctl_cfg_2 = 0;1000 u32 val;1001 int ret;1002 1003 if (sdhci_am654->flags & DLL_CALIB) {1004 regmap_read(sdhci_am654->base, PHY_STAT1, &val);1005 if (~val & CALDONE_MASK) {1006 /* Calibrate IO lines */1007 regmap_update_bits(sdhci_am654->base, PHY_CTRL1,1008 PDB_MASK, PDB_MASK);1009 ret = regmap_read_poll_timeout(sdhci_am654->base,1010 PHY_STAT1, val,1011 val & CALDONE_MASK,1012 1, 20);1013 if (ret)1014 return ret;1015 }1016 }1017 1018 /* Enable pins by setting IO mux to 0 */1019 if (sdhci_am654->flags & IOMUX_PRESENT)1020 regmap_update_bits(sdhci_am654->base, PHY_CTRL1,1021 IOMUX_ENABLE_MASK, 0);1022 1023 /* Set slot type based on SD or eMMC */1024 if (host->mmc->caps & MMC_CAP_NONREMOVABLE)1025 ctl_cfg_2 = SLOTTYPE_EMBEDDED;1026 1027 regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK,1028 ctl_cfg_2);1029 1030 regmap_read(sdhci_am654->base, CTL_CFG_3, &val);1031 if (~val & TUNINGFORSDR50_MASK)1032 /* Enable tuning for SDR50 */1033 regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK,1034 TUNINGFORSDR50_MASK);1035 1036 return 0;1037}1038 1039static int sdhci_am654_runtime_suspend(struct device *dev)1040{1041 struct sdhci_host *host = dev_get_drvdata(dev);1042 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);1043 int ret;1044 1045 if (host->tuning_mode != SDHCI_TUNING_MODE_3)1046 mmc_retune_needed(host->mmc);1047 1048 ret = cqhci_suspend(host->mmc);1049 if (ret)1050 return ret;1051 1052 ret = sdhci_runtime_suspend_host(host);1053 if (ret)1054 return ret;1055 1056 /* disable the clock */1057 clk_disable_unprepare(pltfm_host->clk);1058 return 0;1059}1060 1061static int sdhci_am654_runtime_resume(struct device *dev)1062{1063 struct sdhci_host *host = dev_get_drvdata(dev);1064 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);1065 int ret;1066 1067 /* Enable the clock */1068 ret = clk_prepare_enable(pltfm_host->clk);1069 if (ret)1070 return ret;1071 1072 ret = sdhci_am654_restore(host);1073 if (ret)1074 return ret;1075 1076 ret = sdhci_runtime_resume_host(host, 0);1077 if (ret)1078 return ret;1079 1080 ret = cqhci_resume(host->mmc);1081 if (ret)1082 return ret;1083 1084 return 0;1085}1086#endif1087 1088static const struct dev_pm_ops sdhci_am654_dev_pm_ops = {1089 SET_RUNTIME_PM_OPS(sdhci_am654_runtime_suspend,1090 sdhci_am654_runtime_resume, NULL)1091 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,1092 pm_runtime_force_resume)1093};1094 1095static struct platform_driver sdhci_am654_driver = {1096 .driver = {1097 .name = "sdhci-am654",1098 .probe_type = PROBE_PREFER_ASYNCHRONOUS,1099 .pm = &sdhci_am654_dev_pm_ops,1100 .of_match_table = sdhci_am654_of_match,1101 },1102 .probe = sdhci_am654_probe,1103 .remove_new = sdhci_am654_remove,1104};1105 1106module_platform_driver(sdhci_am654_driver);1107 1108MODULE_DESCRIPTION("Driver for SDHCI Controller on TI's AM654 devices");1109MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>");1110MODULE_LICENSE("GPL");1111