diff options
author | Tom Rini <trini@konsulko.com> | 2021-02-05 09:39:31 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-02-05 09:39:31 -0500 |
commit | 8308a28af821d6498186b3dd7463db9874cd2daf (patch) | |
tree | 660426244992e77c43b3d1ce5be3e19f061a589b /drivers | |
parent | 55ffabec7f9108060350fae29b932fbd832f8296 (diff) | |
parent | 6239cc8c4e8484d908afc555eb59441a16a58b53 (diff) | |
download | u-boot-8308a28af821d6498186b3dd7463db9874cd2daf.zip u-boot-8308a28af821d6498186b3dd7463db9874cd2daf.tar.gz u-boot-8308a28af821d6498186b3dd7463db9874cd2daf.tar.bz2 |
Merge tag 'ti-v2021.04-rc2' of https://gitlab.denx.de/u-boot/custodians/u-boot-tiWIP/05Feb2021
- Sync DTS from Linux kernel for all K3 platforms
- Add MMC higher speed nodes for AM65x, J721e, J7200
- Convert Nokia RX-51 to use CONFIG_DM_MMC
- Minor fixes for LEGO MINDSTORMS
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mmc/am654_sdhci.c | 384 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 95 | ||||
-rw-r--r-- | drivers/remoteproc/ti_k3_r5f_rproc.c | 8 |
4 files changed, 376 insertions, 112 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 14d7913..f8ea921 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -526,6 +526,7 @@ config MMC_SDHCI_AM654 depends on MMC_SDHCI depends on DM_MMC && OF_CONTROL && BLK depends on REGMAP + select MMC_SDHCI_IO_ACCESSORS help Support for Secure Digital Host Controller Interface (SDHCI) controllers present on TI's AM654 SOCs. diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c index baa935e..11dcde1 100644 --- a/drivers/mmc/am654_sdhci.c +++ b/drivers/mmc/am654_sdhci.c @@ -9,9 +9,11 @@ #include <common.h> #include <dm.h> #include <malloc.h> +#include <mmc.h> #include <power-domain.h> #include <regmap.h> #include <sdhci.h> +#include <soc.h> #include <dm/device_compat.h> #include <linux/bitops.h> #include <linux/err.h> @@ -47,6 +49,8 @@ #define SEL100_MASK BIT(SEL100_SHIFT) #define FREQSEL_SHIFT 8 #define FREQSEL_MASK GENMASK(10, 8) +#define CLKBUFSEL_SHIFT 0 +#define CLKBUFSEL_MASK GENMASK(2, 0) #define DLL_TRIM_ICP_SHIFT 4 #define DLL_TRIM_ICP_MASK GENMASK(7, 4) #define DR_TY_SHIFT 20 @@ -61,6 +65,16 @@ #define CALDONE_MASK BIT(CALDONE_SHIFT) #define RETRIM_SHIFT 17 #define RETRIM_MASK BIT(RETRIM_SHIFT) +#define SELDLYTXCLK_SHIFT 17 +#define SELDLYTXCLK_MASK BIT(SELDLYTXCLK_SHIFT) +#define SELDLYRXCLK_SHIFT 16 +#define SELDLYRXCLK_MASK BIT(SELDLYRXCLK_SHIFT) +#define ITAPDLYSEL_SHIFT 0 +#define ITAPDLYSEL_MASK GENMASK(4, 0) +#define ITAPDLYENA_SHIFT 8 +#define ITAPDLYENA_MASK BIT(ITAPDLYENA_SHIFT) +#define ITAPCHGWIN_SHIFT 9 +#define ITAPCHGWIN_MASK BIT(ITAPCHGWIN_SHIFT) #define DRIVER_STRENGTH_50_OHM 0x0 #define DRIVER_STRENGTH_33_OHM 0x1 @@ -69,6 +83,7 @@ #define DRIVER_STRENGTH_40_OHM 0x4 #define AM654_SDHCI_MIN_FREQ 400000 +#define CLOCK_TOO_SLOW_HZ 50000000 struct am654_sdhci_plat { struct mmc_config cfg; @@ -76,34 +91,59 @@ struct am654_sdhci_plat { struct regmap *base; bool non_removable; u32 otap_del_sel[MMC_MODES_END]; + u32 itap_del_sel[MMC_MODES_END]; u32 trm_icp; u32 drv_strength; u32 strb_sel; + u32 clkbuf_sel; u32 flags; -#define DLL_PRESENT (1 << 0) -#define IOMUX_PRESENT (1 << 1) -#define FREQSEL_2_BIT (1 << 2) -#define STRBSEL_4_BIT (1 << 3) - bool dll_on; +#define DLL_PRESENT BIT(0) +#define IOMUX_PRESENT BIT(1) +#define FREQSEL_2_BIT BIT(2) +#define STRBSEL_4_BIT BIT(3) +#define DLL_CALIB BIT(4) }; struct timing_data { - const char *binding; + const char *otap_binding; + const char *itap_binding; u32 capability; }; static const struct timing_data td[] = { - [MMC_LEGACY] = {"ti,otap-del-sel-legacy", 0}, - [MMC_HS] = {"ti,otap-del-sel-mmc-hs", MMC_CAP(MMC_HS)}, - [SD_HS] = {"ti,otap-del-sel-sd-hs", MMC_CAP(SD_HS)}, - [UHS_SDR12] = {"ti,otap-del-sel-sdr12", MMC_CAP(UHS_SDR12)}, - [UHS_SDR25] = {"ti,otap-del-sel-sdr25", MMC_CAP(UHS_SDR25)}, - [UHS_SDR50] = {"ti,otap-del-sel-sdr50", MMC_CAP(UHS_SDR50)}, - [UHS_SDR104] = {"ti,otap-del-sel-sdr104", MMC_CAP(UHS_SDR104)}, - [UHS_DDR50] = {"ti,otap-del-sel-ddr50", MMC_CAP(UHS_DDR50)}, - [MMC_DDR_52] = {"ti,otap-del-sel-ddr52", MMC_CAP(MMC_DDR_52)}, - [MMC_HS_200] = {"ti,otap-del-sel-hs200", MMC_CAP(MMC_HS_200)}, - [MMC_HS_400] = {"ti,otap-del-sel-hs400", MMC_CAP(MMC_HS_400)}, + [MMC_LEGACY] = {"ti,otap-del-sel-legacy", + "ti,itap-del-sel-legacy", + 0}, + [MMC_HS] = {"ti,otap-del-sel-mmc-hs", + "ti,itap-del-sel-mms-hs", + MMC_CAP(MMC_HS)}, + [SD_HS] = {"ti,otap-del-sel-sd-hs", + "ti,itap-del-sel-sd-hs", + MMC_CAP(SD_HS)}, + [UHS_SDR12] = {"ti,otap-del-sel-sdr12", + "ti,itap-del-sel-sdr12", + MMC_CAP(UHS_SDR12)}, + [UHS_SDR25] = {"ti,otap-del-sel-sdr25", + "ti,itap-del-sel-sdr25", + MMC_CAP(UHS_SDR25)}, + [UHS_SDR50] = {"ti,otap-del-sel-sdr50", + NULL, + MMC_CAP(UHS_SDR50)}, + [UHS_SDR104] = {"ti,otap-del-sel-sdr104", + NULL, + MMC_CAP(UHS_SDR104)}, + [UHS_DDR50] = {"ti,otap-del-sel-ddr50", + NULL, + MMC_CAP(UHS_DDR50)}, + [MMC_DDR_52] = {"ti,otap-del-sel-ddr52", + "ti,itap-del-sel-ddr52", + MMC_CAP(MMC_DDR_52)}, + [MMC_HS_200] = {"ti,otap-del-sel-hs200", + NULL, + MMC_CAP(MMC_HS_200)}, + [MMC_HS_400] = {"ti,otap-del-sel-hs400", + NULL, + MMC_CAP(MMC_HS_400)}, }; struct am654_driver_data { @@ -111,19 +151,91 @@ struct am654_driver_data { u32 flags; }; -static void am654_sdhci_set_control_reg(struct sdhci_host *host) +static int am654_sdhci_setup_dll(struct am654_sdhci_plat *plat, + unsigned int speed) { - struct mmc *mmc = (struct mmc *)host->mmc; - u32 reg; - - if (IS_SD(host->mmc) && - mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { - reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); - reg |= SDHCI_CTRL_VDD_180; - sdhci_writew(host, reg, SDHCI_HOST_CONTROL2); + int sel50, sel100, freqsel; + u32 mask, val; + int ret; + + /* Disable delay chain mode */ + regmap_update_bits(plat->base, PHY_CTRL5, + SELDLYTXCLK_MASK | SELDLYRXCLK_MASK, 0); + + if (plat->flags & FREQSEL_2_BIT) { + switch (speed) { + case 200000000: + sel50 = 0; + sel100 = 0; + break; + case 100000000: + sel50 = 0; + sel100 = 1; + break; + default: + sel50 = 1; + sel100 = 0; + } + + /* Configure PHY DLL frequency */ + mask = SEL50_MASK | SEL100_MASK; + val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT); + regmap_update_bits(plat->base, PHY_CTRL5, mask, val); + } else { + switch (speed) { + case 200000000: + freqsel = 0x0; + break; + default: + freqsel = 0x4; + } + regmap_update_bits(plat->base, PHY_CTRL5, FREQSEL_MASK, + freqsel << FREQSEL_SHIFT); } - sdhci_set_uhs_timing(host); + /* Configure DLL TRIM */ + mask = DLL_TRIM_ICP_MASK; + val = plat->trm_icp << DLL_TRIM_ICP_SHIFT; + + /* Configure DLL driver strength */ + mask |= DR_TY_MASK; + val |= plat->drv_strength << DR_TY_SHIFT; + regmap_update_bits(plat->base, PHY_CTRL1, mask, val); + + /* Enable DLL */ + regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, + 0x1 << ENDLL_SHIFT); + /* + * Poll for DLL ready. Use a one second timeout. + * Works in all experiments done so far + */ + ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val, + val & DLLRDY_MASK, 1000, 1000000); + + return ret; +} + +static void am654_sdhci_write_itapdly(struct am654_sdhci_plat *plat, + u32 itapdly) +{ + /* Set ITAPCHGWIN before writing to ITAPDLY */ + regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, + 1 << ITAPCHGWIN_SHIFT); + regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYSEL_MASK, + itapdly << ITAPDLYSEL_SHIFT); + regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); +} + +static void am654_sdhci_setup_delay_chain(struct am654_sdhci_plat *plat, + int mode) +{ + u32 mask, val; + + val = 1 << SELDLYTXCLK_SHIFT | 1 << SELDLYRXCLK_SHIFT; + mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK; + regmap_update_bits(plat->base, PHY_CTRL5, mask, val); + + am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode]); } static int am654_sdhci_set_ios_post(struct sdhci_host *host) @@ -131,7 +243,7 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host) struct udevice *dev = host->mmc->dev; struct am654_sdhci_plat *plat = dev_get_plat(dev); unsigned int speed = host->mmc->clock; - int sel50, sel100, freqsel; + int mode = host->mmc->selected_mode; u32 otap_del_sel; u32 mask, val; int ret; @@ -141,81 +253,40 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host) val &= ~SDHCI_CLOCK_CARD_EN; sdhci_writew(host, val, SDHCI_CLOCK_CONTROL); - /* power off phy */ - if (plat->dll_on) { - regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, 0); - - plat->dll_on = false; - } + regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, 0); /* restart clock */ sdhci_set_clock(host->mmc, speed); /* switch phy back on */ - if (speed > AM654_SDHCI_MIN_FREQ) { - otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode]; - mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; - val = (1 << OTAPDLYENA_SHIFT) | - (otap_del_sel << OTAPDLYSEL_SHIFT); - - /* Write to STRBSEL for HS400 speed mode */ - if (host->mmc->selected_mode == MMC_HS_400) { - if (plat->flags & STRBSEL_4_BIT) - mask |= STRBSEL_4BIT_MASK; - else - mask |= STRBSEL_8BIT_MASK; - - val |= plat->strb_sel << STRBSEL_SHIFT; - } + otap_del_sel = plat->otap_del_sel[mode]; + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; + val = (1 << OTAPDLYENA_SHIFT) | + (otap_del_sel << OTAPDLYSEL_SHIFT); - regmap_update_bits(plat->base, PHY_CTRL4, mask, val); - - if (plat->flags & FREQSEL_2_BIT) { - switch (speed) { - case 200000000: - sel50 = 0; - sel100 = 0; - break; - case 100000000: - sel50 = 0; - sel100 = 1; - break; - default: - sel50 = 1; - sel100 = 0; - } - - /* Configure PHY DLL frequency */ - mask = SEL50_MASK | SEL100_MASK; - val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT); - regmap_update_bits(plat->base, PHY_CTRL5, mask, val); - } else { - switch (speed) { - case 200000000: - freqsel = 0x0; - break; - default: - freqsel = 0x4; - } - regmap_update_bits(plat->base, PHY_CTRL5, FREQSEL_MASK, - freqsel << FREQSEL_SHIFT); - } + /* Write to STRBSEL for HS400 speed mode */ + if (host->mmc->selected_mode == MMC_HS_400) { + if (plat->flags & STRBSEL_4_BIT) + mask |= STRBSEL_4BIT_MASK; + else + mask |= STRBSEL_8BIT_MASK; - /* Enable DLL */ - regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, - 0x1 << ENDLL_SHIFT); - /* - * Poll for DLL ready. Use a one second timeout. - * Works in all experiments done so far - */ - ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val, - val & DLLRDY_MASK, 1000, 1000000); + val |= plat->strb_sel << STRBSEL_SHIFT; + } + + regmap_update_bits(plat->base, PHY_CTRL4, mask, val); + + if (mode > UHS_SDR25 && speed >= CLOCK_TOO_SLOW_HZ) { + ret = am654_sdhci_setup_dll(plat, speed); if (ret) return ret; - - plat->dll_on = true; + } else { + am654_sdhci_setup_delay_chain(plat, mode); } + regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK, + plat->clkbuf_sel); + return 0; } @@ -229,7 +300,7 @@ int am654_sdhci_init(struct am654_sdhci_plat *plat) mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; regmap_update_bits(plat->base, PHY_CTRL4, mask, 0x0); - if (plat->flags & DLL_PRESENT) { + if (plat->flags & DLL_CALIB) { regmap_read(plat->base, PHY_STAT1, &val); if (~val & CALDONE_MASK) { /* Calibrate IO lines */ @@ -241,15 +312,6 @@ int am654_sdhci_init(struct am654_sdhci_plat *plat) if (ret) return ret; } - - /* Configure DLL TRIM */ - mask = DLL_TRIM_ICP_MASK; - val = plat->trm_icp << DLL_TRIM_ICP_SHIFT; - - /* Configure DLL driver strength */ - mask |= DR_TY_MASK; - val |= plat->drv_strength << DR_TY_SHIFT; - regmap_update_bits(plat->base, PHY_CTRL1, mask, val); } /* Enable pins by setting IO mux to 0 */ @@ -292,20 +354,88 @@ static int am654_sdhci_deferred_probe(struct sdhci_host *host) return sdhci_probe(dev); } +static void am654_sdhci_write_b(struct sdhci_host *host, u8 val, int reg) +{ + if (reg == SDHCI_HOST_CONTROL) { + switch (host->mmc->selected_mode) { + /* + * According to the data manual, HISPD bit + * should not be set in these speed modes. + */ + case SD_HS: + case MMC_HS: + case UHS_SDR12: + case UHS_SDR25: + val &= ~SDHCI_CTRL_HISPD; + default: + break; + } + } + + writeb(val, host->ioaddr + reg); +} +#ifdef MMC_SUPPORTS_TUNING +#define ITAP_MAX 32 +static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) +{ + struct udevice *dev = mmc->dev; + struct am654_sdhci_plat *plat = dev_get_plat(dev); + int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len; + u32 itap; + + /* Enable ITAPDLY */ + regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK, + 1 << ITAPDLYENA_SHIFT); + + for (itap = 0; itap < ITAP_MAX; itap++) { + am654_sdhci_write_itapdly(plat, itap); + + cur_val = !mmc_send_tuning(mmc, opcode, NULL); + if (cur_val && !prev_val) + pass_window = itap; + + if (!cur_val) + fail_len++; + + prev_val = cur_val; + } + /* + * Having determined the length of the failing window and start of + * the passing window calculate the length of the passing window and + * set the final value halfway through it considering the range as a + * circular buffer + */ + pass_len = ITAP_MAX - fail_len; + itap = (pass_window + (pass_len >> 1)) % ITAP_MAX; + am654_sdhci_write_itapdly(plat, itap); + + return 0; +} +#endif const struct sdhci_ops am654_sdhci_ops = { +#ifdef MMC_SUPPORTS_TUNING + .platform_execute_tuning = am654_sdhci_execute_tuning, +#endif .deferred_probe = am654_sdhci_deferred_probe, .set_ios_post = &am654_sdhci_set_ios_post, - .set_control_reg = &am654_sdhci_set_control_reg, + .set_control_reg = sdhci_set_control_reg, + .write_b = am654_sdhci_write_b, }; const struct am654_driver_data am654_drv_data = { .ops = &am654_sdhci_ops, - .flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | STRBSEL_4_BIT, + .flags = DLL_PRESENT | IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT, +}; + +const struct am654_driver_data am654_sr1_drv_data = { + .ops = &am654_sdhci_ops, + .flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | DLL_CALIB | + STRBSEL_4_BIT, }; const struct am654_driver_data j721e_8bit_drv_data = { .ops = &am654_sdhci_ops, - .flags = DLL_PRESENT, + .flags = DLL_PRESENT | DLL_CALIB, }; static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host) @@ -319,12 +449,20 @@ static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host) val = (1 << OTAPDLYENA_SHIFT) | (otap_del_sel << OTAPDLYSEL_SHIFT); regmap_update_bits(plat->base, PHY_CTRL4, mask, val); + regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK, + plat->clkbuf_sel); + return 0; } const struct sdhci_ops j721e_4bit_sdhci_ops = { +#ifdef MMC_SUPPORTS_TUNING + .platform_execute_tuning = am654_sdhci_execute_tuning, +#endif .deferred_probe = am654_sdhci_deferred_probe, .set_ios_post = &j721e_4bit_sdhci_set_ios_post, + .set_control_reg = sdhci_set_control_reg, + .write_b = am654_sdhci_write_b, }; const struct am654_driver_data j721e_4bit_drv_data = { @@ -332,6 +470,11 @@ const struct am654_driver_data j721e_4bit_drv_data = { .flags = IOMUX_PRESENT, }; +const struct soc_attr am654_sdhci_soc_attr[] = { + { .family = "AM65X", .revision = "SR1.0", .data = &am654_sr1_drv_data}, + {/* sentinel */} +}; + static int sdhci_am654_get_otap_delay(struct udevice *dev, struct mmc_config *cfg) { @@ -349,15 +492,20 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev, * value is not found */ for (i = MMC_HS; i <= MMC_HS_400; i++) { - ret = dev_read_u32(dev, td[i].binding, &plat->otap_del_sel[i]); + ret = dev_read_u32(dev, td[i].otap_binding, + &plat->otap_del_sel[i]); if (ret) { - dev_dbg(dev, "Couldn't find %s\n", td[i].binding); + dev_dbg(dev, "Couldn't find %s\n", td[i].otap_binding); /* * Remove the corresponding capability * if an otap-del-sel value is not found */ cfg->host_caps &= ~td[i].capability; } + + if (td[i].itap_binding) + dev_read_u32(dev, td[i].itap_binding, + &plat->itap_del_sel[i]); } return 0; @@ -371,6 +519,8 @@ static int am654_sdhci_probe(struct udevice *dev) struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sdhci_host *host = dev_get_priv(dev); struct mmc_config *cfg = &plat->cfg; + const struct soc_attr *soc; + const struct am654_driver_data *soc_drv_data; struct clk clk; unsigned long clock; int ret; @@ -390,6 +540,7 @@ static int am654_sdhci_probe(struct udevice *dev) host->max_clk = clock; host->mmc = &plat->mmc; host->mmc->dev = dev; + host->ops = drv_data->ops; ret = sdhci_setup_cfg(cfg, host, cfg->f_max, AM654_SDHCI_MIN_FREQ); if (ret) @@ -399,7 +550,13 @@ static int am654_sdhci_probe(struct udevice *dev) if (ret) return ret; - host->ops = drv_data->ops; + /* Update ops based on SoC revision */ + soc = soc_device_match(am654_sdhci_soc_attr); + if (soc && soc->data) { + soc_drv_data = soc->data; + host->ops = soc_drv_data->ops; + } + host->mmc->priv = host; upriv->mmc = host->mmc; @@ -452,6 +609,8 @@ static int am654_sdhci_of_to_plat(struct udevice *dev) } } + dev_read_u32(dev, "ti,clkbuf-sel", &plat->clkbuf_sel); + ret = mmc_of_parse(dev, cfg); if (ret) return ret; @@ -464,9 +623,18 @@ static int am654_sdhci_bind(struct udevice *dev) struct am654_driver_data *drv_data = (struct am654_driver_data *)dev_get_driver_data(dev); struct am654_sdhci_plat *plat = dev_get_plat(dev); + const struct soc_attr *soc; + const struct am654_driver_data *soc_drv_data; plat->flags = drv_data->flags; + /* Update flags based on SoC revision */ + soc = soc_device_match(am654_sdhci_soc_attr); + if (soc && soc->data) { + soc_drv_data = soc->data; + plat->flags = soc_drv_data->flags; + } + return sdhci_bind(dev, &plat->mmc, &plat->cfg); } diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 0628934..ed0dc17 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -20,6 +20,7 @@ #include <linux/delay.h> #include <linux/dma-mapping.h> #include <phys2bus.h> +#include <power/regulator.h> static void sdhci_reset(struct sdhci_host *host, u8 mask) { @@ -509,6 +510,100 @@ void sdhci_set_uhs_timing(struct sdhci_host *host) sdhci_writew(host, reg, SDHCI_HOST_CONTROL2); } +static void sdhci_set_voltage(struct sdhci_host *host) +{ + if (IS_ENABLED(CONFIG_MMC_IO_VOLTAGE)) { + struct mmc *mmc = (struct mmc *)host->mmc; + u32 ctrl; + + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + + switch (mmc->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_330: +#if CONFIG_IS_ENABLED(DM_REGULATOR) + if (mmc->vqmmc_supply) { + if (regulator_set_enable_if_allowed(mmc->vqmmc_supply, false)) { + pr_err("failed to disable vqmmc-supply\n"); + return; + } + + if (regulator_set_value(mmc->vqmmc_supply, 3300000)) { + pr_err("failed to set vqmmc-voltage to 3.3V\n"); + return; + } + + if (regulator_set_enable_if_allowed(mmc->vqmmc_supply, true)) { + pr_err("failed to enable vqmmc-supply\n"); + return; + } + } +#endif + if (IS_SD(mmc)) { + ctrl &= ~SDHCI_CTRL_VDD_180; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + } + + /* Wait for 5ms */ + mdelay(5); + + /* 3.3V regulator output should be stable within 5 ms */ + if (IS_SD(mmc)) { + if (ctrl & SDHCI_CTRL_VDD_180) { + pr_err("3.3V regulator output did not become stable\n"); + return; + } + } + + break; + case MMC_SIGNAL_VOLTAGE_180: +#if CONFIG_IS_ENABLED(DM_REGULATOR) + if (mmc->vqmmc_supply) { + if (regulator_set_enable_if_allowed(mmc->vqmmc_supply, false)) { + pr_err("failed to disable vqmmc-supply\n"); + return; + } + + if (regulator_set_value(mmc->vqmmc_supply, 1800000)) { + pr_err("failed to set vqmmc-voltage to 1.8V\n"); + return; + } + + if (regulator_set_enable_if_allowed(mmc->vqmmc_supply, true)) { + pr_err("failed to enable vqmmc-supply\n"); + return; + } + } +#endif + if (IS_SD(mmc)) { + ctrl |= SDHCI_CTRL_VDD_180; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + } + + /* Wait for 5 ms */ + mdelay(5); + + /* 1.8V regulator output has to be stable within 5 ms */ + if (IS_SD(mmc)) { + if (!(ctrl & SDHCI_CTRL_VDD_180)) { + pr_err("1.8V regulator output did not become stable\n"); + return; + } + } + + break; + default: + /* No signal voltage switch required */ + return; + } + } +} + +void sdhci_set_control_reg(struct sdhci_host *host) +{ + sdhci_set_voltage(host); + sdhci_set_uhs_timing(host); +} + #ifdef CONFIG_DM_MMC static int sdhci_set_ios(struct udevice *dev) { diff --git a/drivers/remoteproc/ti_k3_r5f_rproc.c b/drivers/remoteproc/ti_k3_r5f_rproc.c index 10bc4e9..3c569a3 100644 --- a/drivers/remoteproc/ti_k3_r5f_rproc.c +++ b/drivers/remoteproc/ti_k3_r5f_rproc.c @@ -678,9 +678,9 @@ static int k3_r5f_of_to_priv(struct k3_r5f_core *core) dev_dbg(core->dev, "%s\n", __func__); - core->atcm_enable = dev_read_u32_default(core->dev, "atcm-enable", 0); - core->btcm_enable = dev_read_u32_default(core->dev, "btcm-enable", 1); - core->loczrama = dev_read_u32_default(core->dev, "loczrama", 1); + core->atcm_enable = dev_read_u32_default(core->dev, "ti,atcm-enable", 0); + core->btcm_enable = dev_read_u32_default(core->dev, "ti,btcm-enable", 1); + core->loczrama = dev_read_u32_default(core->dev, "ti,loczrama", 1); ret = ti_sci_proc_of_to_priv(core->dev, &core->tsp); if (ret) @@ -875,7 +875,7 @@ static int k3_r5f_cluster_probe(struct udevice *dev) dev_dbg(dev, "%s\n", __func__); - cluster->mode = dev_read_u32_default(dev, "lockstep-mode", + cluster->mode = dev_read_u32_default(dev, "ti,cluster-mode", CLUSTER_MODE_LOCKSTEP); if (device_get_child_count(dev) != 2) { |