- DM support for CAxxxx SoCs
- eMMC board for presidio-asic
- Add defer probe for mmc sdhci
- TI SoCs mmc misc update
This commit is contained in:
Tom Rini 2020-03-10 21:13:26 -04:00
commit 36bdcf7f3b
29 changed files with 531 additions and 84 deletions

View file

@ -180,6 +180,7 @@ F: board/cortina/common/
F: drivers/gpio/cortina_gpio.c
F: drivers/watchdog/cortina_wdt.c
F: drivers/serial/serial_cortina.c
F: drivers/mmc/ca_dw_mmc.c
ARM/CZ.NIC TURRIS MOX SUPPORT
M: Marek Behun <marek.behun@nic.cz>
@ -672,6 +673,7 @@ F: board/cortina/common/
F: drivers/gpio/cortina_gpio.c
F: drivers/watchdog/cortina_wdt.c
F: drivers/serial/serial_cortina.c
F: drivers/mmc/ca_dw_mmc.c
MIPS MSCC
M: Gregory CLEMENT <gregory.clement@bootlin.com>

View file

@ -98,7 +98,17 @@
interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
ti,otap-del-sel = <0x2>;
ti,otap-del-sel-legacy = <0x0>;
ti,otap-del-sel-mmc-hs = <0x0>;
ti,otap-del-sel-sd-hs = <0x0>;
ti,otap-del-sel-sdr12 = <0x0>;
ti,otap-del-sel-sdr25 = <0x0>;
ti,otap-del-sel-sdr50 = <0x8>;
ti,otap-del-sel-sdr104 = <0x5>;
ti,otap-del-sel-ddr50 = <0x5>;
ti,otap-del-sel-ddr52 = <0x5>;
ti,otap-del-sel-hs200 = <0x5>;
ti,otap-del-sel-hs400 = <0x0>;
ti,trm-icp = <0x8>;
dma-coherent;
};

View file

@ -29,7 +29,16 @@
clock-names = "clk_ahb", "clk_xin";
power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>;
max-frequency = <25000000>;
ti,otap-del-sel = <0x2>;
ti,otap-del-sel-legacy = <0x0>;
ti,otap-del-sel-mmc-hs = <0x0>;
ti,otap-del-sel-sd-hs = <0x0>;
ti,otap-del-sel-sdr12 = <0x0>;
ti,otap-del-sel-sdr25 = <0x0>;
ti,otap-del-sel-sdr50 = <0x8>;
ti,otap-del-sel-sdr104 = <0x7>;
ti,otap-del-sel-ddr50 = <0x4>;
ti,otap-del-sel-ddr52 = <0x4>;
ti,otap-del-sel-hs200 = <0x7>;
ti,trm-icp = <0x8>;
};

View file

@ -232,9 +232,14 @@
assigned-clocks = <&k3_clks 91 1>;
assigned-clock-parents = <&k3_clks 91 2>;
bus-width = <8>;
ti,otap-del-sel = <0x2>;
ti,trm-icp = <0x8>;
dma-coherent;
mmc-ddr-1_8v;
ti,otap-del-sel-legacy = <0x0>;
ti,otap-del-sel-mmc-hs = <0x0>;
ti,otap-del-sel-ddr52 = <0x5>;
ti,otap-del-sel-hs200 = <0x6>;
ti,otap-del-sel-hs400 = <0x0>;
};
main_sdhci1: sdhci@4fb0000 {
@ -246,7 +251,13 @@
clocks = <&k3_clks 92 0>, <&k3_clks 92 5>;
assigned-clocks = <&k3_clks 92 0>;
assigned-clock-parents = <&k3_clks 92 1>;
ti,otap-del-sel = <0x2>;
ti,otap-del-sel-legacy = <0x0>;
ti,otap-del-sel-sd-hs = <0xf>;
ti,otap-del-sel-sdr12 = <0xf>;
ti,otap-del-sel-sdr25 = <0xf>;
ti,otap-del-sel-sdr50 = <0xc>;
ti,otap-del-sel-sdr104 = <0x5>;
ti,otap-del-sel-ddr50 = <0xc>;
ti,trm-icp = <0x8>;
dma-coherent;
};

View file

@ -34,14 +34,14 @@
u-boot,dm-spl;
};
clk_200mhz: dummy_clock {
clk_200mhz: dummy_clock_200mhz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <200000000>;
u-boot,dm-spl;
};
clk_19_2mhz: dummy_clock {
clk_19_2mhz: dummy_clock_19_2mhz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <19200000>;

View file

@ -197,7 +197,8 @@ unsigned long spl_spi_get_uboot_offs(struct spi_flash *flash)
#endif
#ifdef CONFIG_SPL_MMC_SUPPORT
unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
unsigned long raw_sect)
{
int end;

View file

@ -17,6 +17,7 @@
#include <dm/uclass-internal.h>
#include <dm/pinctrl.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#include <mmc.h>
#ifdef CONFIG_SPL_BUILD
#ifdef CONFIG_K3_LOAD_SYSFW
@ -86,6 +87,33 @@ static void store_boot_index_from_rom(void)
bootindex = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX);
}
#if defined(CONFIG_K3_LOAD_SYSFW)
void k3_mmc_stop_clock(void)
{
if (spl_boot_device() == BOOT_DEVICE_MMC1) {
struct mmc *mmc = find_mmc_device(0);
if (!mmc)
return;
mmc->saved_clock = mmc->clock;
mmc_set_clock(mmc, 0, true);
}
}
void k3_mmc_restart_clock(void)
{
if (spl_boot_device() == BOOT_DEVICE_MMC1) {
struct mmc *mmc = find_mmc_device(0);
if (!mmc)
return;
mmc_set_clock(mmc, mmc->saved_clock, false);
}
}
#endif
void board_init_f(ulong dummy)
{
#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM654_DDRSS)
@ -138,7 +166,10 @@ void board_init_f(ulong dummy)
* callback hook, effectively switching on (or over) the console
* output.
*/
k3_sysfw_loader(preloader_console_init);
k3_sysfw_loader(k3_mmc_stop_clock, k3_mmc_restart_clock);
/* Prepare console output */
preloader_console_init();
/* Disable ROM configured firewalls right after loading sysfw */
#ifdef CONFIG_TI_SECURE_DEVICE

View file

@ -7,6 +7,6 @@
#ifndef _SYSFW_LOADER_H_
#define _SYSFW_LOADER_H_
void k3_sysfw_loader(void (*config_pm_done_callback)(void));
void k3_sysfw_loader(void (*config_pm_pre_callback)(void), void (*config_pm_done_callback)(void));
#endif

View file

@ -18,6 +18,7 @@
#include <dm.h>
#include <dm/uclass-internal.h>
#include <dm/pinctrl.h>
#include <mmc.h>
#ifdef CONFIG_SPL_BUILD
#ifdef CONFIG_K3_LOAD_SYSFW
@ -100,6 +101,33 @@ static void ctrl_mmr_unlock(void)
mmr_unlock(CTRL_MMR0_BASE, 7);
}
#if defined(CONFIG_K3_LOAD_SYSFW)
void k3_mmc_stop_clock(void)
{
if (spl_boot_device() == BOOT_DEVICE_MMC1) {
struct mmc *mmc = find_mmc_device(0);
if (!mmc)
return;
mmc->saved_clock = mmc->clock;
mmc_set_clock(mmc, 0, true);
}
}
void k3_mmc_restart_clock(void)
{
if (spl_boot_device() == BOOT_DEVICE_MMC1) {
struct mmc *mmc = find_mmc_device(0);
if (!mmc)
return;
mmc_set_clock(mmc, mmc->saved_clock, false);
}
}
#endif
/*
* This uninitialized global variable would normal end up in the .bss section,
* but the .bss is cleared between writing and reading this variable, so move
@ -154,7 +182,10 @@ void board_init_f(ulong dummy)
* callback hook, effectively switching on (or over) the console
* output.
*/
k3_sysfw_loader(preloader_console_init);
k3_sysfw_loader(k3_mmc_stop_clock, k3_mmc_restart_clock);
/* Prepare console output */
preloader_console_init();
/* Disable ROM configured firewalls right after loading sysfw */
#ifdef CONFIG_TI_SECURE_DEVICE

View file

@ -197,7 +197,8 @@ exit:
}
#endif
void k3_sysfw_loader(void (*config_pm_done_callback)(void))
void k3_sysfw_loader(void (*config_pm_pre_callback) (void),
void (*config_pm_done_callback)(void))
{
struct spl_image_info spl_image = { 0 };
struct spl_boot_device bootdev = { 0 };
@ -291,6 +292,9 @@ void k3_sysfw_loader(void (*config_pm_done_callback)(void))
/* Get handle for accessing SYSFW services */
ti_sci = get_ti_sci_handle();
if (config_pm_pre_callback)
config_pm_pre_callback();
/* Parse and apply the different SYSFW configuration fragments */
k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci);

View file

@ -317,13 +317,10 @@ int spl_boot_partition(const u32 boot_device)
}
#endif
unsigned long __weak spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
unsigned long __weak spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
unsigned long raw_sect)
{
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR;
#else
return 0;
#endif
return raw_sect;
}
int spl_mmc_load(struct spl_image_info *spl_image,
@ -392,7 +389,7 @@ int spl_mmc_load(struct spl_image_info *spl_image,
return err;
}
raw_sect = spl_mmc_get_uboot_raw_sector(mmc);
raw_sect = spl_mmc_get_uboot_raw_sector(mmc, raw_sect);
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
err = mmc_load_image_raw_partition(spl_image, mmc, raw_part,

View file

@ -74,6 +74,7 @@ CONFIG_DM_KEYBOARD=y
CONFIG_DM_MAILBOX=y
CONFIG_K3_SEC_PROXY=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ADMA=y
CONFIG_SPL_MMC_SDHCI_ADMA=y

View file

@ -73,6 +73,7 @@ CONFIG_K3_SEC_PROXY=y
CONFIG_MISC=y
CONFIG_K3_AVS0=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_SDHCI=y
CONFIG_SPL_MMC_SDHCI_ADMA=y
CONFIG_MMC_SDHCI_AM654=y

View file

@ -0,0 +1,33 @@
CONFIG_ARM=y
# CONFIG_SYS_ARCH_TIMER is not set
CONFIG_TARGET_PRESIDIO_ASIC=y
CONFIG_SYS_TEXT_BASE=0x04000000
CONFIG_ENV_SIZE=0x20000
CONFIG_DM_GPIO=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_IDENT_STRING="Presidio-SoC"
CONFIG_SHOW_BOOT_PROGRESS=y
CONFIG_BOOTDELAY=3
CONFIG_BOARD_EARLY_INIT_R=y
CONFIG_SYS_PROMPT="G3#"
CONFIG_CMD_MMC=y
CONFIG_CMD_PART=y
CONFIG_CMD_WDT=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_TIMER=y
CONFIG_CMD_SMC=y
CONFIG_CMD_EXT2=y
CONFIG_CMD_EXT4=y
CONFIG_OF_CONTROL=y
CONFIG_OF_LIVE=y
CONFIG_DEFAULT_DEVICE_TREE="ca-presidio-engboard"
# CONFIG_NET is not set
CONFIG_DM=y
CONFIG_CORTINA_GPIO=y
CONFIG_DM_MMC=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_CORTINA=y
CONFIG_DM_SERIAL=y
CONFIG_CORTINA_UART=y
CONFIG_WDT=y
CONFIG_WDT_CORTINA=y

View file

@ -29,6 +29,8 @@ CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_SEPARATE_BSS=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_SPL_DM_MAILBOX=y
@ -99,6 +101,7 @@ CONFIG_SYS_I2C_OMAP24XX=y
CONFIG_DM_MAILBOX=y
CONFIG_K3_SEC_PROXY=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ADMA=y
CONFIG_SPL_MMC_SDHCI_ADMA=y

View file

@ -27,6 +27,8 @@ CONFIG_USE_BOOTCOMMAND=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_SEPARATE_BSS=y
CONFIG_SPL_EARLY_BSS=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_SPL_DM_MAILBOX=y
@ -77,6 +79,7 @@ CONFIG_MISC=y
CONFIG_FS_LOADER=y
CONFIG_K3_AVS0=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_SDHCI=y
CONFIG_SPL_MMC_SDHCI_ADMA=y
CONFIG_MMC_SDHCI_AM654=y

View file

@ -205,6 +205,17 @@ config MMC_DW
block, this provides host support for SD and MMC interfaces, in both
PIO, internal DMA mode and external DMA mode.
config MMC_DW_CORTINA
bool "Cortina specific extensions for Synopsys DW Memory Card Interface"
depends on DM_MMC
depends on MMC_DW
depends on BLK
default n
help
This selects support for Cortina SoC specific extensions to the
Synopsys DesignWare Memory Card Interface driver. Select this option
for platforms based on Cortina CAxxxx Soc's.
config MMC_DW_EXYNOS
bool "Exynos specific extensions for Synopsys DW Memory Card Interface"
depends on ARCH_EXYNOS

View file

@ -20,6 +20,7 @@ endif
obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
obj-$(CONFIG_MMC_DAVINCI) += davinci_mmc.o
obj-$(CONFIG_MMC_DW) += dw_mmc.o
obj-$(CONFIG_MMC_DW_CORTINA) += ca_dw_mmc.o
obj-$(CONFIG_MMC_DW_EXYNOS) += exynos_dw_mmc.o
obj-$(CONFIG_MMC_DW_K3) += hi6220_dw_mmc.o
obj-$(CONFIG_MMC_DW_ROCKCHIP) += rockchip_dw_mmc.o

View file

@ -74,7 +74,7 @@ struct am654_sdhci_plat {
struct mmc mmc;
struct regmap *base;
bool non_removable;
u32 otap_del_sel;
u32 otap_del_sel[11];
u32 trm_icp;
u32 drv_strength;
u32 strb_sel;
@ -86,6 +86,25 @@ struct am654_sdhci_plat {
bool dll_on;
};
struct timing_data {
const char *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)},
};
struct am654_driver_data {
const struct sdhci_ops *ops;
u32 flags;
@ -112,6 +131,7 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host)
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
unsigned int speed = host->mmc->clock;
int sel50, sel100, freqsel;
u32 otap_del_sel;
u32 mask, val;
int ret;
@ -132,9 +152,10 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host)
/* 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) |
(plat->otap_del_sel << OTAPDLYSEL_SHIFT);
(otap_del_sel << OTAPDLYSEL_SHIFT);
/* Write to STRBSEL for HS400 speed mode */
if (host->mmc->selected_mode == MMC_HS_400) {
@ -197,44 +218,6 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host)
return 0;
}
const struct sdhci_ops am654_sdhci_ops = {
.set_ios_post = &am654_sdhci_set_ios_post,
.set_control_reg = &am654_sdhci_set_control_reg,
};
const struct am654_driver_data am654_drv_data = {
.ops = &am654_sdhci_ops,
.flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | STRBSEL_4_BIT,
};
const struct am654_driver_data j721e_8bit_drv_data = {
.ops = &am654_sdhci_ops,
.flags = DLL_PRESENT,
};
static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host)
{
struct udevice *dev = host->mmc->dev;
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
u32 mask, val;
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
val = (1 << OTAPDLYENA_SHIFT) |
(plat->otap_del_sel << OTAPDLYSEL_SHIFT);
regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
return 0;
}
const struct sdhci_ops j721e_4bit_sdhci_ops = {
.set_ios_post = &j721e_4bit_sdhci_set_ios_post,
};
const struct am654_driver_data j721e_4bit_drv_data = {
.ops = &j721e_4bit_sdhci_ops,
.flags = IOMUX_PRESENT,
};
int am654_sdhci_init(struct am654_sdhci_plat *plat)
{
u32 ctl_cfg_2 = 0;
@ -281,6 +264,104 @@ int am654_sdhci_init(struct am654_sdhci_plat *plat)
return 0;
}
#define MAX_SDCD_DEBOUNCE_TIME 2000
static int am654_sdhci_deferred_probe(struct sdhci_host *host)
{
struct udevice *dev = host->mmc->dev;
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
unsigned long start;
int val;
/*
* The controller takes about 1 second to debounce the card detect line
* and doesn't let us power on until that time is up. Instead of waiting
* for 1 second at every stage, poll on the CARD_PRESENT bit upto a
* maximum of 2 seconds to be safe..
*/
start = get_timer(0);
do {
if (get_timer(start) > MAX_SDCD_DEBOUNCE_TIME)
return -ENOMEDIUM;
val = mmc_getcd(host->mmc);
} while (!val);
am654_sdhci_init(plat);
return sdhci_probe(dev);
}
const struct sdhci_ops am654_sdhci_ops = {
.deferred_probe = am654_sdhci_deferred_probe,
.set_ios_post = &am654_sdhci_set_ios_post,
.set_control_reg = &am654_sdhci_set_control_reg,
};
const struct am654_driver_data am654_drv_data = {
.ops = &am654_sdhci_ops,
.flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | STRBSEL_4_BIT,
};
const struct am654_driver_data j721e_8bit_drv_data = {
.ops = &am654_sdhci_ops,
.flags = DLL_PRESENT,
};
static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host)
{
struct udevice *dev = host->mmc->dev;
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
u32 otap_del_sel, mask, val;
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);
regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
return 0;
}
const struct sdhci_ops j721e_4bit_sdhci_ops = {
.deferred_probe = am654_sdhci_deferred_probe,
.set_ios_post = &j721e_4bit_sdhci_set_ios_post,
};
const struct am654_driver_data j721e_4bit_drv_data = {
.ops = &j721e_4bit_sdhci_ops,
.flags = IOMUX_PRESENT,
};
static int sdhci_am654_get_otap_delay(struct udevice *dev,
struct mmc_config *cfg)
{
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
int ret;
int i;
/* ti,otap-del-sel-legacy is mandatory */
ret = dev_read_u32(dev, "ti,otap-del-sel-legacy",
&plat->otap_del_sel[0]);
if (ret)
return ret;
/*
* Remove the corresponding capability if an otap-del-sel
* 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]);
if (ret) {
dev_dbg(dev, "Couldn't find %s\n", td[i].binding);
/*
* Remove the corresponding capability
* if an otap-del-sel value is not found
*/
cfg->host_caps &= ~td[i].capability;
}
}
return 0;
}
static int am654_sdhci_probe(struct udevice *dev)
{
struct am654_driver_data *drv_data =
@ -313,15 +394,17 @@ static int am654_sdhci_probe(struct udevice *dev)
if (ret)
return ret;
ret = sdhci_am654_get_otap_delay(dev, cfg);
if (ret)
return ret;
host->ops = drv_data->ops;
host->mmc->priv = host;
upriv->mmc = host->mmc;
regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
am654_sdhci_init(plat);
return sdhci_probe(dev);
return 0;
}
static int am654_sdhci_ofdata_to_platdata(struct udevice *dev)
@ -336,10 +419,6 @@ static int am654_sdhci_ofdata_to_platdata(struct udevice *dev)
host->ioaddr = (void *)dev_read_addr(dev);
plat->non_removable = dev_read_bool(dev, "non-removable");
ret = dev_read_u32(dev, "ti,otap-del-sel", &plat->otap_del_sel);
if (ret)
return ret;
if (plat->flags & DLL_PRESENT) {
ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp);
if (ret)

181
drivers/mmc/ca_dw_mmc.c Normal file
View file

@ -0,0 +1,181 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2019 Cortina Access
* Arthur Li <arthur.li@cortina-access.com>
*/
#include <common.h>
#include <dwmmc.h>
#include <fdtdec.h>
#include <linux/libfdt.h>
#include <malloc.h>
#include <errno.h>
#include <dm.h>
#include <mapmem.h>
#define SD_CLK_SEL_MASK (0x3)
#define SD_DLL_DEFAULT (0x143000)
#define SD_SCLK_MAX (200000000)
#define SD_CLK_SEL_200MHZ (0x2)
#define SD_CLK_SEL_100MHZ (0x1)
#define IO_DRV_SD_DS_OFFSET (16)
#define IO_DRV_SD_DS_MASK (0xff << IO_DRV_SD_DS_OFFSET)
#define MIN_FREQ (400000)
DECLARE_GLOBAL_DATA_PTR;
struct ca_mmc_plat {
struct mmc_config cfg;
struct mmc mmc;
};
struct ca_dwmmc_priv_data {
struct dwmci_host host;
void __iomem *sd_dll_reg;
void __iomem *io_drv_reg;
u8 ds;
};
static void ca_dwmci_clksel(struct dwmci_host *host)
{
struct ca_dwmmc_priv_data *priv = host->priv;
u32 val = readl(priv->sd_dll_reg);
if (host->bus_hz >= 200000000) {
val &= ~SD_CLK_SEL_MASK;
val |= SD_CLK_SEL_200MHZ;
} else if (host->bus_hz >= 100000000) {
val &= ~SD_CLK_SEL_MASK;
val |= SD_CLK_SEL_100MHZ;
} else {
val &= ~SD_CLK_SEL_MASK;
}
writel(val, priv->sd_dll_reg);
}
static void ca_dwmci_board_init(struct dwmci_host *host)
{
struct ca_dwmmc_priv_data *priv = host->priv;
u32 val = readl(priv->io_drv_reg);
writel(SD_DLL_DEFAULT, priv->sd_dll_reg);
val &= ~IO_DRV_SD_DS_MASK;
if (priv && priv->ds)
val |= priv->ds << IO_DRV_SD_DS_OFFSET;
writel(val, priv->io_drv_reg);
}
unsigned int ca_dwmci_get_mmc_clock(struct dwmci_host *host, uint freq)
{
struct ca_dwmmc_priv_data *priv = host->priv;
u8 sd_clk_sel = readl(priv->sd_dll_reg) & SD_CLK_SEL_MASK;
u8 clk_div;
switch (sd_clk_sel) {
case 2:
clk_div = 1;
break;
case 1:
clk_div = 2;
break;
default:
clk_div = 4;
}
return SD_SCLK_MAX / clk_div / (host->div + 1);
}
static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
{
struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
u32 tmp;
host->name = dev->name;
host->dev_index = 0;
host->buswidth = dev_read_u32_default(dev, "bus-width", 1);
if (host->buswidth != 1 && host->buswidth != 4)
return -EINVAL;
host->bus_hz = dev_read_u32_default(dev, "max-frequency", 50000000);
priv->ds = dev_read_u32_default(dev, "io_ds", 0x33);
host->fifo_mode = dev_read_bool(dev, "fifo-mode");
dev_read_u32(dev, "sd_dll_ctrl", &tmp);
priv->sd_dll_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
if (!priv->sd_dll_reg)
return -EINVAL;
dev_read_u32(dev, "io_drv_ctrl", &tmp);
priv->io_drv_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
if (!priv->io_drv_reg)
return -EINVAL;
host->ioaddr = dev_read_addr_ptr(dev);
if (host->ioaddr == (void *)FDT_ADDR_T_NONE) {
printf("DWMMC: base address is invalid\n");
return -EINVAL;
}
host->priv = priv;
return 0;
}
struct dm_mmc_ops ca_dwmci_dm_ops;
static int ca_dwmmc_probe(struct udevice *dev)
{
struct ca_mmc_plat *plat = dev_get_platdata(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
memcpy(&ca_dwmci_dm_ops, &dm_dwmci_ops, sizeof(struct dm_mmc_ops));
dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, MIN_FREQ);
if (host->buswidth == 1) {
(&plat->cfg)->host_caps &= ~MMC_MODE_8BIT;
(&plat->cfg)->host_caps &= ~MMC_MODE_4BIT;
}
host->mmc = &plat->mmc;
host->mmc->priv = &priv->host;
upriv->mmc = host->mmc;
host->mmc->dev = dev;
host->clksel = ca_dwmci_clksel;
host->board_init = ca_dwmci_board_init;
host->get_mmc_clk = ca_dwmci_get_mmc_clock;
return dwmci_probe(dev);
}
static int ca_dwmmc_bind(struct udevice *dev)
{
struct ca_mmc_plat *plat = dev_get_platdata(dev);
return dwmci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct udevice_id ca_dwmmc_ids[] = {
{ .compatible = "snps,dw-cortina" },
{ }
};
U_BOOT_DRIVER(ca_dwmmc_drv) = {
.name = "cortina_dwmmc",
.id = UCLASS_MMC,
.of_match = ca_dwmmc_ids,
.ofdata_to_platdata = ca_dwmmc_ofdata_to_platdata,
.bind = ca_dwmmc_bind,
.ops = &ca_dwmci_dm_ops,
.probe = ca_dwmmc_probe,
.priv_auto_alloc_size = sizeof(struct ca_dwmmc_priv_data),
.platdata_auto_alloc_size = sizeof(struct ca_mmc_plat),
};

View file

@ -743,7 +743,6 @@ static int esdhc_set_timing(struct mmc *mmc)
switch (mmc->selected_mode) {
case MMC_LEGACY:
case SD_LEGACY:
esdhc_reset_tuning(mmc);
writel(mixctrl, &regs->mixctrl);
break;

View file

@ -138,6 +138,21 @@ int mmc_host_power_cycle(struct mmc *mmc)
return dm_mmc_host_power_cycle(mmc->dev);
}
int dm_mmc_deferred_probe(struct udevice *dev)
{
struct dm_mmc_ops *ops = mmc_get_ops(dev);
if (ops->deferred_probe)
return ops->deferred_probe(dev);
return 0;
}
int mmc_deferred_probe(struct mmc *mmc)
{
return dm_mmc_deferred_probe(mmc->dev);
}
int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
{
int val;

View file

@ -132,7 +132,6 @@ const char *mmc_mode_name(enum bus_mode mode)
{
static const char *const names[] = {
[MMC_LEGACY] = "MMC legacy",
[SD_LEGACY] = "SD Legacy",
[MMC_HS] = "MMC High Speed (26MHz)",
[SD_HS] = "SD High Speed (50MHz)",
[UHS_SDR12] = "UHS SDR12 (25MHz)",
@ -158,7 +157,6 @@ static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
{
static const int freqs[] = {
[MMC_LEGACY] = 25000000,
[SD_LEGACY] = 25000000,
[MMC_HS] = 26000000,
[SD_HS] = 50000000,
[MMC_HS_52] = 52000000,
@ -1239,7 +1237,7 @@ static int sd_get_capabilities(struct mmc *mmc)
u32 sd3_bus_mode;
#endif
mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(SD_LEGACY);
mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
if (mmc_host_is_spi(mmc))
return 0;
@ -1352,7 +1350,7 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
return 0;
switch (mode) {
case SD_LEGACY:
case MMC_LEGACY:
speed = UHS_SDR12_BUS_SPEED;
break;
case SD_HS:
@ -1695,7 +1693,7 @@ static const struct mode_width_tuning sd_modes_by_pref[] = {
},
#endif
{
.mode = SD_LEGACY,
.mode = MMC_LEGACY,
.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
}
};
@ -1725,7 +1723,7 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
if (mmc_host_is_spi(mmc)) {
mmc_set_bus_width(mmc, 1);
mmc_select_mode(mmc, SD_LEGACY);
mmc_select_mode(mmc, MMC_LEGACY);
mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
return 0;
}
@ -1784,7 +1782,7 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
error:
/* revert to a safer bus speed */
mmc_select_mode(mmc, SD_LEGACY);
mmc_select_mode(mmc, MMC_LEGACY);
mmc_set_clock(mmc, mmc->tran_speed,
MMC_CLK_ENABLE);
}
@ -2561,7 +2559,7 @@ static int mmc_startup(struct mmc *mmc)
#if CONFIG_IS_ENABLED(MMC_TINY)
mmc_set_clock(mmc, mmc->legacy_speed, false);
mmc_select_mode(mmc, IS_SD(mmc) ? SD_LEGACY : MMC_LEGACY);
mmc_select_mode(mmc, MMC_LEGACY);
mmc_set_bus_width(mmc, 1);
#else
if (IS_SD(mmc)) {
@ -2843,9 +2841,11 @@ int mmc_start_init(struct mmc *mmc)
* all hosts are capable of 1 bit bus-width and able to use the legacy
* timings.
*/
mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(SD_LEGACY) |
mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) |
MMC_CAP(MMC_LEGACY) | MMC_MODE_1BIT;
#if CONFIG_IS_ENABLED(DM_MMC)
mmc_deferred_probe(mmc);
#endif
#if !defined(CONFIG_MMC_BROKEN_CD)
no_card = mmc_getcd(mmc) == 0;
#else

View file

@ -392,7 +392,6 @@ static void omap_hsmmc_set_timing(struct mmc *mmc)
break;
case MMC_LEGACY:
case MMC_HS:
case SD_LEGACY:
case UHS_SDR12:
val |= AC12_UHSMC_SDR12;
break;

View file

@ -658,6 +658,20 @@ int sdhci_probe(struct udevice *dev)
return sdhci_init(mmc);
}
static int sdhci_deferred_probe(struct udevice *dev)
{
int err;
struct mmc *mmc = mmc_get_mmc_dev(dev);
struct sdhci_host *host = mmc->priv;
if (host->ops && host->ops->deferred_probe) {
err = host->ops->deferred_probe(host);
if (err)
return err;
}
return 0;
}
static int sdhci_get_cd(struct udevice *dev)
{
struct mmc *mmc = mmc_get_mmc_dev(dev);
@ -692,6 +706,7 @@ const struct dm_mmc_ops sdhci_ops = {
.send_cmd = sdhci_send_command,
.set_ios = sdhci_set_ios,
.get_cd = sdhci_get_cd,
.deferred_probe = sdhci_deferred_probe,
#ifdef MMC_SUPPORTS_TUNING
.execute_tuning = sdhci_execute_tuning,
#endif

View file

@ -37,7 +37,6 @@ struct arasan_sdhci_priv {
static const u8 mode2timing[] = {
[MMC_LEGACY] = UHS_SDR12_BUS_SPEED,
[SD_LEGACY] = UHS_SDR12_BUS_SPEED,
[MMC_HS] = HIGH_SPEED_BUS_SPEED,
[SD_HS] = HIGH_SPEED_BUS_SPEED,
[MMC_HS_52] = HIGH_SPEED_BUS_SPEED,

View file

@ -127,8 +127,6 @@
#define CONFIG_SYS_MMC_ENV_PART 1
#endif
#define CONFIG_SUPPORT_EMMC_BOOT
/* Now for the remaining common defines */
#include <configs/ti_armv7_common.h>

View file

@ -15,6 +15,8 @@
#include <linux/dma-direction.h>
#include <part.h>
struct bd_info;
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
#define MMC_SUPPORTS_TUNING
#endif
@ -407,6 +409,14 @@ struct mmc;
#if CONFIG_IS_ENABLED(DM_MMC)
struct dm_mmc_ops {
/**
* deferred_probe() - Some configurations that need to be deferred
* to just before enumerating the device
*
* @dev: Device to init
* @return 0 if Ok, -ve if error
*/
int (*deferred_probe)(struct udevice *dev);
/**
* send_cmd() - Send a command to the MMC device
*
@ -490,6 +500,7 @@ int dm_mmc_get_wp(struct udevice *dev);
int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us);
int dm_mmc_host_power_cycle(struct udevice *dev);
int dm_mmc_deferred_probe(struct udevice *dev);
/* Transition functions for compatibility */
int mmc_set_ios(struct mmc *mmc);
@ -499,6 +510,7 @@ int mmc_execute_tuning(struct mmc *mmc, uint opcode);
int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us);
int mmc_set_enhanced_strobe(struct mmc *mmc);
int mmc_host_power_cycle(struct mmc *mmc);
int mmc_deferred_probe(struct mmc *mmc);
#else
struct mmc_ops {
@ -533,7 +545,6 @@ struct sd_ssr {
enum bus_mode {
MMC_LEGACY,
SD_LEGACY,
MMC_HS,
SD_HS,
MMC_HS_52,
@ -603,6 +614,7 @@ struct mmc {
bool clk_disable; /* true if the clock can be turned off */
uint bus_width;
uint clock;
uint saved_clock;
enum mmc_voltage signal_voltage;
uint card_caps;
uint host_caps;
@ -712,7 +724,7 @@ void mmc_destroy(struct mmc *mmc);
* @return 0 if OK, -ve on error
*/
int mmc_unbind(struct udevice *dev);
int mmc_initialize(bd_t *bis);
int mmc_initialize(struct bd_info *bis);
int mmc_init_device(int num);
int mmc_init(struct mmc *mmc);
int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
@ -857,8 +869,8 @@ void mmc_set_preinit(struct mmc *mmc, int preinit);
#endif
void board_mmc_power_init(void);
int board_mmc_init(bd_t *bis);
int cpu_mmc_init(bd_t *bis);
int board_mmc_init(struct bd_info *bis);
int cpu_mmc_init(struct bd_info *bis);
int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
# ifdef CONFIG_SYS_MMC_ENV_PART
extern uint mmc_get_env_part(struct mmc *mmc);

View file

@ -268,6 +268,7 @@ struct sdhci_ops {
void (*set_clock)(struct sdhci_host *host, u32 div);
int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
void (*set_delay)(struct sdhci_host *host);
int (*deferred_probe)(struct sdhci_host *host);
};
#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)