Bug fixes to mmc_spi
Add Aspeed SD driver
Fix dw_mmc timeout calculation
Fix timeout values passed to mmc_wait_dat0
sdhci dt caps/mask update

[trini: Fix evb-ast2500_defconfig CONFIG_MMC line]
Signed-off-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
Tom Rini 2019-09-08 21:14:22 -04:00
commit 40e362a9ab
23 changed files with 288 additions and 65 deletions

View file

@ -59,3 +59,17 @@
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mac2link_default &pinctrl_mdio2_default>; pinctrl-0 = <&pinctrl_mac2link_default &pinctrl_mdio2_default>;
}; };
&sdhci0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sd1_default>;
};
&sdhci1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sd2_default>;
};

View file

@ -34,6 +34,22 @@
apb { apb {
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
sdhci0: sdhci@1e740100 {
compatible = "aspeed,ast2500-sdhci";
reg = <0x1e740100>;
#reset-cells = <1>;
clocks = <&scu BCLK_SDCLK>;
resets = <&rst AST_RESET_SDIO>;
};
sdhci1: sdhci@1e740200 {
compatible = "aspeed,ast2500-sdhci";
reg = <0x1e740200>;
#reset-cells = <1>;
clocks = <&scu BCLK_SDCLK>;
resets = <&rst AST_RESET_SDIO>;
};
}; };
}; };

View file

@ -22,6 +22,8 @@
#define SCU_MPLL_POST_MASK (0x3f << SCU_MPLL_POST_SHIFT) #define SCU_MPLL_POST_MASK (0x3f << SCU_MPLL_POST_SHIFT)
#define SCU_PCLK_DIV_SHIFT 23 #define SCU_PCLK_DIV_SHIFT 23
#define SCU_PCLK_DIV_MASK (7 << SCU_PCLK_DIV_SHIFT) #define SCU_PCLK_DIV_MASK (7 << SCU_PCLK_DIV_SHIFT)
#define SCU_SDCLK_DIV_SHIFT 12
#define SCU_SDCLK_DIV_MASK (7 << SCU_SDCLK_DIV_SHIFT)
#define SCU_HPLL_DENUM_SHIFT 0 #define SCU_HPLL_DENUM_SHIFT 0
#define SCU_HPLL_DENUM_MASK 0x1f #define SCU_HPLL_DENUM_MASK 0x1f
#define SCU_HPLL_NUM_SHIFT 5 #define SCU_HPLL_NUM_SHIFT 5
@ -107,6 +109,7 @@
#define SCU_CLKSTOP_MAC1 (1 << 20) #define SCU_CLKSTOP_MAC1 (1 << 20)
#define SCU_CLKSTOP_MAC2 (1 << 21) #define SCU_CLKSTOP_MAC2 (1 << 21)
#define SCU_CLKSTOP_SDCLK (1 << 27)
#define SCU_D2PLL_EXT1_OFF (1 << 0) #define SCU_D2PLL_EXT1_OFF (1 << 0)
#define SCU_D2PLL_EXT1_BYPASS (1 << 1) #define SCU_D2PLL_EXT1_BYPASS (1 << 1)

View file

@ -2,7 +2,8 @@
!defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \ !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \
!defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \ !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \
!defined(CONFIG_ARCH_LX2160A) && !defined(CONFIG_ARCH_LS1028A) && \ !defined(CONFIG_ARCH_LX2160A) && !defined(CONFIG_ARCH_LS1028A) && \
!defined(CONFIG_ARCH_LS2080A) && !defined(CONFIG_ARCH_LS1088A) !defined(CONFIG_ARCH_LS2080A) && !defined(CONFIG_ARCH_LS1088A) && \
!defined(CONFIG_ARCH_ASPEED)
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
#endif #endif
#include <asm-generic/gpio.h> #include <asm-generic/gpio.h>

View file

@ -16,6 +16,7 @@ CONFIG_HUSH_PARSER=y
CONFIG_CMD_I2C=y CONFIG_CMD_I2C=y
CONFIG_CMD_DHCP=y CONFIG_CMD_DHCP=y
CONFIG_CMD_MII=y CONFIG_CMD_MII=y
CONFIG_CMD_MMC=y
CONFIG_CMD_PING=y CONFIG_CMD_PING=y
CONFIG_DEFAULT_DEVICE_TREE="ast2500-evb" CONFIG_DEFAULT_DEVICE_TREE="ast2500-evb"
CONFIG_NET_RANDOM_ETHADDR=y CONFIG_NET_RANDOM_ETHADDR=y
@ -23,7 +24,6 @@ CONFIG_REGMAP=y
CONFIG_CLK=y CONFIG_CLK=y
CONFIG_DM_I2C=y CONFIG_DM_I2C=y
CONFIG_SYS_I2C_ASPEED=y CONFIG_SYS_I2C_ASPEED=y
# CONFIG_MMC is not set
CONFIG_PHY_REALTEK=y CONFIG_PHY_REALTEK=y
CONFIG_DM_ETH=y CONFIG_DM_ETH=y
CONFIG_FTGMAC100=y CONFIG_FTGMAC100=y
@ -36,3 +36,10 @@ CONFIG_SYS_NS16550=y
CONFIG_SYSRESET=y CONFIG_SYSRESET=y
CONFIG_TIMER=y CONFIG_TIMER=y
CONFIG_WDT=y CONFIG_WDT=y
CONFIG_MMC=y
CONFIG_DM_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ASPEED=y
CONFIG_MMC_VERBOSE=y
CONFIG_OF_CONTROL=y
CONFIG_OF_EMBED=y

View file

@ -143,6 +143,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
rate = rate / apb_div; rate = rate / apb_div;
} }
break; break;
case BCLK_SDCLK:
{
ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
& SCU_SDCLK_DIV_MASK)
>> SCU_SDCLK_DIV_SHIFT);
rate = ast2500_get_hpll_rate(clkin,
readl(&priv->
scu->h_pll_param));
rate = rate / apb_div;
}
break;
case PCLK_UART1: case PCLK_UART1:
rate = ast2500_get_uart_clk_rate(priv->scu, 1); rate = ast2500_get_uart_clk_rate(priv->scu, 1);
break; break;
@ -436,6 +447,22 @@ static int ast2500_clk_enable(struct clk *clk)
struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
switch (clk->id) { switch (clk->id) {
case BCLK_SDCLK:
if (readl(&priv->scu->clk_stop_ctrl1) & SCU_CLKSTOP_SDCLK) {
ast_scu_unlock(priv->scu);
setbits_le32(&priv->scu->sysreset_ctrl1,
SCU_SYSRESET_SDIO);
udelay(100);
clrbits_le32(&priv->scu->clk_stop_ctrl1,
SCU_CLKSTOP_SDCLK);
mdelay(10);
clrbits_le32(&priv->scu->sysreset_ctrl1,
SCU_SYSRESET_SDIO);
ast_scu_lock(priv->scu);
}
break;
/* /*
* For MAC clocks the clock rate is * For MAC clocks the clock rate is
* configured based on whether RGMII or RMII mode has been selected * configured based on whether RGMII or RMII mode has been selected

View file

@ -79,7 +79,7 @@ int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
return 0; return 0;
} }
int ofnode_read_u64_default(ofnode node, const char *propname, u64 def) u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
{ {
assert(ofnode_valid(node)); assert(ofnode_valid(node));
ofnode_read_u64(node, propname, &def); ofnode_read_u64(node, propname, &def);

View file

@ -44,6 +44,16 @@ int dev_read_u32u(struct udevice *dev, const char *propname, uint *outp)
return 0; return 0;
} }
int dev_read_u64(struct udevice *dev, const char *propname, u64 *outp)
{
return ofnode_read_u64(dev_ofnode(dev), propname, outp);
}
u64 dev_read_u64_default(struct udevice *dev, const char *propname, u64 def)
{
return ofnode_read_u64_default(dev_ofnode(dev), propname, def);
}
const char *dev_read_string(struct udevice *dev, const char *propname) const char *dev_read_string(struct udevice *dev, const char *propname)
{ {
return ofnode_read_string(dev_ofnode(dev), propname); return ofnode_read_string(dev_ofnode(dev), propname);

View file

@ -421,6 +421,17 @@ config SPL_MMC_SDHCI_ADMA
This enables support for the ADMA (Advanced DMA) defined This enables support for the ADMA (Advanced DMA) defined
in the SD Host Controller Standard Specification Version 3.00 in SPL. in the SD Host Controller Standard Specification Version 3.00 in SPL.
config MMC_SDHCI_ASPEED
bool "Aspeed SDHCI controller"
depends on ARCH_ASPEED
depends on DM_MMC
depends on MMC_SDHCI
help
Enables support for the Aspeed SDHCI 2.0 controller present on Aspeed
SoCs. This device is compatible with SD 3.0 and/or MMC 4.3
specifications. On the AST2600, the device is also compatible with
MMC 5.1 and eMMC 3.0.
config MMC_SDHCI_ATMEL config MMC_SDHCI_ATMEL
bool "Atmel SDHCI controller support" bool "Atmel SDHCI controller support"
depends on ARCH_AT91 depends on ARCH_AT91

View file

@ -46,6 +46,7 @@ obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o
# SDHCI # SDHCI
obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_ASPEED) += aspeed_sdhci.o
obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o
obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o
obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o

View file

@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 IBM Corp.
* Eddie James <eajames@linux.ibm.com>
*/
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <malloc.h>
#include <sdhci.h>
struct aspeed_sdhci_plat {
struct mmc_config cfg;
struct mmc mmc;
};
static int aspeed_sdhci_probe(struct udevice *dev)
{
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct aspeed_sdhci_plat *plat = dev_get_platdata(dev);
struct sdhci_host *host = dev_get_priv(dev);
u32 max_clk;
struct clk clk;
int ret;
ret = clk_get_by_index(dev, 0, &clk);
if (ret)
return ret;
ret = clk_enable(&clk);
if (ret)
goto free;
host->name = dev->name;
host->ioaddr = (void *)devfdt_get_addr(dev);
max_clk = clk_get_rate(&clk);
if (IS_ERR_VALUE(max_clk)) {
ret = max_clk;
goto err;
}
host->max_clk = max_clk;
host->mmc = &plat->mmc;
host->mmc->dev = dev;
host->mmc->priv = host;
upriv->mmc = host->mmc;
ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
if (ret)
goto err;
ret = sdhci_probe(dev);
if (ret)
goto err;
return 0;
err:
clk_disable(&clk);
free:
clk_free(&clk);
return ret;
}
static int aspeed_sdhci_bind(struct udevice *dev)
{
struct aspeed_sdhci_plat *plat = dev_get_platdata(dev);
return sdhci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct udevice_id aspeed_sdhci_ids[] = {
{ .compatible = "aspeed,ast2400-sdhci" },
{ .compatible = "aspeed,ast2500-sdhci" },
{ .compatible = "aspeed,ast2600-sdhci" },
{ }
};
U_BOOT_DRIVER(aspeed_sdhci_drv) = {
.name = "aspeed_sdhci",
.id = UCLASS_MMC,
.of_match = aspeed_sdhci_ids,
.ops = &sdhci_ops,
.bind = aspeed_sdhci_bind,
.probe = aspeed_sdhci_probe,
.priv_auto_alloc_size = sizeof(struct sdhci_host),
.platdata_auto_alloc_size = sizeof(struct aspeed_sdhci_plat),
};

View file

@ -119,11 +119,12 @@ static unsigned int dwmci_get_timeout(struct mmc *mmc, const unsigned int size)
{ {
unsigned int timeout; unsigned int timeout;
timeout = size * 8 * 1000; /* counting in bits and msec */ timeout = size * 8; /* counting in bits */
timeout *= 2; /* wait twice as long */ timeout *= 10; /* wait 10 times as long */
timeout /= mmc->clock; timeout /= mmc->clock;
timeout /= mmc->bus_width; timeout /= mmc->bus_width;
timeout /= mmc->ddr_mode ? 2 : 1; timeout /= mmc->ddr_mode ? 2 : 1;
timeout *= 1000; /* counting in msec */
timeout = (timeout < 1000) ? 1000 : timeout; timeout = (timeout < 1000) ? 1000 : timeout;
return timeout; return timeout;

View file

@ -47,18 +47,18 @@ int mmc_set_ios(struct mmc *mmc)
return dm_mmc_set_ios(mmc->dev); return dm_mmc_set_ios(mmc->dev);
} }
int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout) int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us)
{ {
struct dm_mmc_ops *ops = mmc_get_ops(dev); struct dm_mmc_ops *ops = mmc_get_ops(dev);
if (!ops->wait_dat0) if (!ops->wait_dat0)
return -ENOSYS; return -ENOSYS;
return ops->wait_dat0(dev, state, timeout); return ops->wait_dat0(dev, state, timeout_us);
} }
int mmc_wait_dat0(struct mmc *mmc, int state, int timeout) int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us)
{ {
return dm_mmc_wait_dat0(mmc->dev, state, timeout); return dm_mmc_wait_dat0(mmc->dev, state, timeout_us);
} }
int dm_mmc_get_wp(struct udevice *dev) int dm_mmc_get_wp(struct udevice *dev)
@ -427,10 +427,6 @@ U_BOOT_DRIVER(mmc_blk) = {
}; };
#endif /* CONFIG_BLK */ #endif /* CONFIG_BLK */
U_BOOT_DRIVER(mmc) = {
.name = "mmc",
.id = UCLASS_MMC,
};
UCLASS_DRIVER(mmc) = { UCLASS_DRIVER(mmc) = {
.id = UCLASS_MMC, .id = UCLASS_MMC,

View file

@ -31,7 +31,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps);
#if !CONFIG_IS_ENABLED(DM_MMC) #if !CONFIG_IS_ENABLED(DM_MMC)
static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout) static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us)
{ {
return -ENOSYS; return -ENOSYS;
} }
@ -230,12 +230,12 @@ int mmc_send_status(struct mmc *mmc, unsigned int *status)
return -ECOMM; return -ECOMM;
} }
int mmc_poll_for_busy(struct mmc *mmc, int timeout) int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
{ {
unsigned int status; unsigned int status;
int err; int err;
err = mmc_wait_dat0(mmc, 1, timeout); err = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
if (err != -ENOSYS) if (err != -ENOSYS)
return err; return err;
@ -256,13 +256,13 @@ int mmc_poll_for_busy(struct mmc *mmc, int timeout)
return -ECOMM; return -ECOMM;
} }
if (timeout-- <= 0) if (timeout_ms-- <= 0)
break; break;
udelay(1000); udelay(1000);
} }
if (timeout <= 0) { if (timeout_ms <= 0) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
pr_err("Timeout waiting card ready\n"); pr_err("Timeout waiting card ready\n");
#endif #endif
@ -750,17 +750,17 @@ static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
{ {
unsigned int status, start; unsigned int status, start;
struct mmc_cmd cmd; struct mmc_cmd cmd;
int timeout = DEFAULT_CMD6_TIMEOUT_MS; int timeout_ms = DEFAULT_CMD6_TIMEOUT_MS;
bool is_part_switch = (set == EXT_CSD_CMD_SET_NORMAL) && bool is_part_switch = (set == EXT_CSD_CMD_SET_NORMAL) &&
(index == EXT_CSD_PART_CONF); (index == EXT_CSD_PART_CONF);
int retries = 3; int retries = 3;
int ret; int ret;
if (mmc->gen_cmd6_time) if (mmc->gen_cmd6_time)
timeout = mmc->gen_cmd6_time * 10; timeout_ms = mmc->gen_cmd6_time * 10;
if (is_part_switch && mmc->part_switch_time) if (is_part_switch && mmc->part_switch_time)
timeout = mmc->part_switch_time * 10; timeout_ms = mmc->part_switch_time * 10;
cmd.cmdidx = MMC_CMD_SWITCH; cmd.cmdidx = MMC_CMD_SWITCH;
cmd.resp_type = MMC_RSP_R1b; cmd.resp_type = MMC_RSP_R1b;
@ -778,7 +778,7 @@ static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
start = get_timer(0); start = get_timer(0);
/* poll dat0 for rdy/buys status */ /* poll dat0 for rdy/buys status */
ret = mmc_wait_dat0(mmc, 1, timeout); ret = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
if (ret && ret != -ENOSYS) if (ret && ret != -ENOSYS)
return ret; return ret;
@ -788,11 +788,11 @@ static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
* stated timeout to be sufficient. * stated timeout to be sufficient.
*/ */
if (ret == -ENOSYS && !send_status) if (ret == -ENOSYS && !send_status)
mdelay(timeout); mdelay(timeout_ms);
/* Finally wait until the card is ready or indicates a failure /* Finally wait until the card is ready or indicates a failure
* to switch. It doesn't hurt to use CMD13 here even if send_status * to switch. It doesn't hurt to use CMD13 here even if send_status
* is false, because by now (after 'timeout' ms) the bus should be * is false, because by now (after 'timeout_ms' ms) the bus should be
* reliable. * reliable.
*/ */
do { do {
@ -806,7 +806,7 @@ static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
if (!ret && (status & MMC_STATUS_RDY_FOR_DATA)) if (!ret && (status & MMC_STATUS_RDY_FOR_DATA))
return 0; return 0;
udelay(100); udelay(100);
} while (get_timer(start) < timeout); } while (get_timer(start) < timeout_ms);
return -ETIMEDOUT; return -ETIMEDOUT;
} }

View file

@ -58,12 +58,15 @@
#define READ_TIMEOUT 3000000 /* 1 sec */ #define READ_TIMEOUT 3000000 /* 1 sec */
#define WRITE_TIMEOUT 3000000 /* 1 sec */ #define WRITE_TIMEOUT 3000000 /* 1 sec */
struct mmc_spi_priv { struct mmc_spi_plat {
struct spi_slave *spi;
struct mmc_config cfg; struct mmc_config cfg;
struct mmc mmc; struct mmc mmc;
}; };
struct mmc_spi_priv {
struct spi_slave *spi;
};
static int mmc_spi_sendcmd(struct udevice *dev, static int mmc_spi_sendcmd(struct udevice *dev,
ushort cmdidx, u32 cmdarg, u32 resp_type, ushort cmdidx, u32 cmdarg, u32 resp_type,
u8 *resp, u32 resp_size, u8 *resp, u32 resp_size,
@ -370,6 +373,7 @@ done:
static int mmc_spi_probe(struct udevice *dev) static int mmc_spi_probe(struct udevice *dev)
{ {
struct mmc_spi_priv *priv = dev_get_priv(dev); struct mmc_spi_priv *priv = dev_get_priv(dev);
struct mmc_spi_plat *plat = dev_get_platdata(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
char *name; char *name;
@ -385,28 +389,28 @@ static int mmc_spi_probe(struct udevice *dev)
return -ENOMEM; return -ENOMEM;
sprintf(name, "%s:%s", dev->parent->name, dev->name); sprintf(name, "%s:%s", dev->parent->name, dev->name);
priv->cfg.name = name; plat->cfg.name = name;
priv->cfg.host_caps = MMC_MODE_SPI; plat->cfg.host_caps = MMC_MODE_SPI;
priv->cfg.voltages = MMC_SPI_VOLTAGE; plat->cfg.voltages = MMC_SPI_VOLTAGE;
priv->cfg.f_min = MMC_SPI_MIN_CLOCK; plat->cfg.f_min = MMC_SPI_MIN_CLOCK;
priv->cfg.f_max = priv->spi->max_hz; plat->cfg.f_max = priv->spi->max_hz;
priv->cfg.part_type = PART_TYPE_DOS; plat->cfg.part_type = PART_TYPE_DOS;
priv->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
priv->mmc.cfg = &priv->cfg; plat->mmc.cfg = &plat->cfg;
priv->mmc.priv = priv; plat->mmc.priv = priv;
priv->mmc.dev = dev; plat->mmc.dev = dev;
upriv->mmc = &priv->mmc; upriv->mmc = &plat->mmc;
return 0; return 0;
} }
static int mmc_spi_bind(struct udevice *dev) static int mmc_spi_bind(struct udevice *dev)
{ {
struct mmc_spi_priv *priv = dev_get_priv(dev); struct mmc_spi_plat *plat = dev_get_platdata(dev);
return mmc_bind(dev, &priv->mmc, &priv->cfg); return mmc_bind(dev, &plat->mmc, &plat->cfg);
} }
static const struct dm_mmc_ops mmc_spi_ops = { static const struct dm_mmc_ops mmc_spi_ops = {
@ -426,5 +430,6 @@ U_BOOT_DRIVER(mmc_spi) = {
.ops = &mmc_spi_ops, .ops = &mmc_spi_ops,
.probe = mmc_spi_probe, .probe = mmc_spi_probe,
.bind = mmc_spi_bind, .bind = mmc_spi_bind,
.platdata_auto_alloc_size = sizeof(struct mmc_spi_plat),
.priv_auto_alloc_size = sizeof(struct mmc_spi_priv), .priv_auto_alloc_size = sizeof(struct mmc_spi_priv),
}; };

View file

@ -79,7 +79,7 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
u32 start_rem, blkcnt_rem; u32 start_rem, blkcnt_rem;
struct mmc *mmc = find_mmc_device(dev_num); struct mmc *mmc = find_mmc_device(dev_num);
lbaint_t blk = 0, blk_r = 0; lbaint_t blk = 0, blk_r = 0;
int timeout = 1000; int timeout_ms = 1000;
if (!mmc) if (!mmc)
return -1; return -1;
@ -119,7 +119,7 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
blk += blk_r; blk += blk_r;
/* Waiting for the ready status */ /* Waiting for the ready status */
if (mmc_poll_for_busy(mmc, timeout)) if (mmc_poll_for_busy(mmc, timeout_ms))
return 0; return 0;
} }
@ -131,7 +131,7 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
{ {
struct mmc_cmd cmd; struct mmc_cmd cmd;
struct mmc_data data; struct mmc_data data;
int timeout = 1000; int timeout_ms = 1000;
if ((start + blkcnt) > mmc_get_blk_desc(mmc)->lba) { if ((start + blkcnt) > mmc_get_blk_desc(mmc)->lba) {
printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n", printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
@ -177,7 +177,7 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
} }
/* Waiting for the ready status */ /* Waiting for the ready status */
if (mmc_poll_for_busy(mmc, timeout)) if (mmc_poll_for_busy(mmc, timeout_ms))
return 0; return 0;
return blkcnt; return blkcnt;

View file

@ -430,7 +430,7 @@ static void omap_hsmmc_conf_bus_power(struct mmc *mmc, uint signal_voltage)
writel(ac12, &mmc_base->ac12); writel(ac12, &mmc_base->ac12);
} }
static int omap_hsmmc_wait_dat0(struct udevice *dev, int state, int timeout) static int omap_hsmmc_wait_dat0(struct udevice *dev, int state, int timeout_us)
{ {
int ret = -ETIMEDOUT; int ret = -ETIMEDOUT;
u32 con; u32 con;
@ -442,8 +442,8 @@ static int omap_hsmmc_wait_dat0(struct udevice *dev, int state, int timeout)
con = readl(&mmc_base->con); con = readl(&mmc_base->con);
writel(con | CON_CLKEXTFREE | CON_PADEN, &mmc_base->con); writel(con | CON_CLKEXTFREE | CON_PADEN, &mmc_base->con);
timeout = DIV_ROUND_UP(timeout, 10); /* check every 10 us. */ timeout_us = DIV_ROUND_UP(timeout_us, 10); /* check every 10 us. */
while (timeout--) { while (timeout_us--) {
dat0_high = !!(readl(&mmc_base->pstate) & PSTATE_DLEV_DAT0); dat0_high = !!(readl(&mmc_base->pstate) & PSTATE_DLEV_DAT0);
if (dat0_high == target_dat0_high) { if (dat0_high == target_dat0_high) {
ret = 0; ret = 0;

View file

@ -499,15 +499,16 @@ static int renesas_sdhi_set_ios(struct udevice *dev)
} }
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
static int renesas_sdhi_wait_dat0(struct udevice *dev, int state, int timeout) static int renesas_sdhi_wait_dat0(struct udevice *dev, int state,
int timeout_us)
{ {
int ret = -ETIMEDOUT; int ret = -ETIMEDOUT;
bool dat0_high; bool dat0_high;
bool target_dat0_high = !!state; bool target_dat0_high = !!state;
struct tmio_sd_priv *priv = dev_get_priv(dev); struct tmio_sd_priv *priv = dev_get_priv(dev);
timeout = DIV_ROUND_UP(timeout, 10); /* check every 10 us. */ timeout_us = DIV_ROUND_UP(timeout_us, 10); /* check every 10 us. */
while (timeout--) { while (timeout_us--) {
dat0_high = !!(tmio_sd_readl(priv, TMIO_SD_INFO2) & TMIO_SD_INFO2_DAT0); dat0_high = !!(tmio_sd_readl(priv, TMIO_SD_INFO2) & TMIO_SD_INFO2_DAT0);
if (dat0_high == target_dat0_high) { if (dat0_high == target_dat0_high) {
ret = 0; ret = 0;

View file

@ -711,17 +711,19 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
{ {
u32 caps, caps_1 = 0; u32 caps, caps_1 = 0;
#if CONFIG_IS_ENABLED(DM_MMC) #if CONFIG_IS_ENABLED(DM_MMC)
u32 mask[2] = {0}; u64 dt_caps, dt_caps_mask;
int ret;
ret = dev_read_u32_array(host->mmc->dev, "sdhci-caps-mask",
mask, 2);
if (ret && ret != -1)
return ret;
caps = ~mask[1] & sdhci_readl(host, SDHCI_CAPABILITIES); dt_caps_mask = dev_read_u64_default(host->mmc->dev,
"sdhci-caps-mask", 0);
dt_caps = dev_read_u64_default(host->mmc->dev,
"sdhci-caps", 0);
caps = ~(u32)dt_caps_mask &
sdhci_readl(host, SDHCI_CAPABILITIES);
caps |= (u32)dt_caps;
#else #else
caps = sdhci_readl(host, SDHCI_CAPABILITIES); caps = sdhci_readl(host, SDHCI_CAPABILITIES);
#endif #endif
debug("%s, caps: 0x%x\n", __func__, caps);
#ifdef CONFIG_MMC_SDHCI_SDMA #ifdef CONFIG_MMC_SDHCI_SDMA
if (!(caps & SDHCI_CAN_DO_SDMA)) { if (!(caps & SDHCI_CAN_DO_SDMA)) {
@ -762,10 +764,13 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
/* Check whether the clock multiplier is supported or not */ /* Check whether the clock multiplier is supported or not */
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
#if CONFIG_IS_ENABLED(DM_MMC) #if CONFIG_IS_ENABLED(DM_MMC)
caps_1 = ~mask[0] & sdhci_readl(host, SDHCI_CAPABILITIES_1); caps_1 = ~(u32)(dt_caps_mask >> 32) &
sdhci_readl(host, SDHCI_CAPABILITIES_1);
caps_1 |= (u32)(dt_caps >> 32);
#else #else
caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
#endif #endif
debug("%s, caps_1: 0x%x\n", __func__, caps_1);
host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >> host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
SDHCI_CLOCK_MUL_SHIFT; SDHCI_CLOCK_MUL_SHIFT;
} }

View file

@ -58,6 +58,8 @@ static const struct ast2500_group_config ast2500_groups[] = {
{ "MDIO1", 3, (1 << 31) | (1 << 30) }, { "MDIO1", 3, (1 << 31) | (1 << 30) },
{ "MAC2LINK", 1, (1 << 1) }, { "MAC2LINK", 1, (1 << 1) },
{ "MDIO2", 5, (1 << 2) }, { "MDIO2", 5, (1 << 2) },
{ "SD1", 5, (1 << 0) },
{ "SD2", 5, (1 << 1) },
}; };
static int ast2500_pinctrl_get_groups_count(struct udevice *dev) static int ast2500_pinctrl_get_groups_count(struct udevice *dev)

View file

@ -254,7 +254,7 @@ int ofnode_read_u64(ofnode node, const char *propname, u64 *outp);
* @def: default value to return if the property has no value * @def: default value to return if the property has no value
* @return property value, or @def if not found * @return property value, or @def if not found
*/ */
int ofnode_read_u64_default(ofnode node, const char *propname, u64 def); u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def);
/** /**
* ofnode_read_string() - Read a string from a property * ofnode_read_string() - Read a string from a property

View file

@ -44,6 +44,7 @@ static inline bool dev_of_valid(struct udevice *dev)
} }
#ifndef CONFIG_DM_DEV_READ_INLINE #ifndef CONFIG_DM_DEV_READ_INLINE
/** /**
* dev_read_u32() - read a 32-bit integer from a device's DT property * dev_read_u32() - read a 32-bit integer from a device's DT property
* *
@ -96,6 +97,26 @@ int dev_read_s32_default(struct udevice *dev, const char *propname, int def);
*/ */
int dev_read_u32u(struct udevice *dev, const char *propname, uint *outp); int dev_read_u32u(struct udevice *dev, const char *propname, uint *outp);
/**
* dev_read_u64() - read a 64-bit integer from a device's DT property
*
* @dev: device to read DT property from
* @propname: name of the property to read from
* @outp: place to put value (if found)
* @return 0 if OK, -ve on error
*/
int dev_read_u64(struct udevice *dev, const char *propname, u64 *outp);
/**
* dev_read_u64_default() - read a 64-bit integer from a device's DT property
*
* @dev: device to read DT property from
* @propname: name of the property to read from
* @def: default value to return if the property has no value
* @return property value, or @def if not found
*/
u64 dev_read_u64_default(struct udevice *dev, const char *propname, u64 def);
/** /**
* dev_read_string() - Read a string from a device's DT property * dev_read_string() - Read a string from a device's DT property
* *
@ -601,6 +622,18 @@ static inline int dev_read_u32u(struct udevice *dev,
return 0; return 0;
} }
static inline int dev_read_u64(struct udevice *dev,
const char *propname, u64 *outp)
{
return ofnode_read_u64(dev_ofnode(dev), propname, outp);
}
static inline u64 dev_read_u64_default(struct udevice *dev,
const char *propname, u64 def)
{
return ofnode_read_u64_default(dev_ofnode(dev), propname, def);
}
static inline const char *dev_read_string(struct udevice *dev, static inline const char *dev_read_string(struct udevice *dev,
const char *propname) const char *propname)
{ {

View file

@ -457,10 +457,10 @@ struct dm_mmc_ops {
* *
* @dev: Device to check * @dev: Device to check
* @state: target state * @state: target state
* @timeout: timeout in us * @timeout_us: timeout in us
* @return 0 if dat0 is in the target state, -ve on error * @return 0 if dat0 is in the target state, -ve on error
*/ */
int (*wait_dat0)(struct udevice *dev, int state, int timeout); int (*wait_dat0)(struct udevice *dev, int state, int timeout_us);
#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT) #if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
/* set_enhanced_strobe() - set HS400 enhanced strobe */ /* set_enhanced_strobe() - set HS400 enhanced strobe */
@ -476,14 +476,14 @@ int dm_mmc_set_ios(struct udevice *dev);
int dm_mmc_get_cd(struct udevice *dev); int dm_mmc_get_cd(struct udevice *dev);
int dm_mmc_get_wp(struct udevice *dev); int dm_mmc_get_wp(struct udevice *dev);
int dm_mmc_execute_tuning(struct udevice *dev, uint opcode); int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout); int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us);
/* Transition functions for compatibility */ /* Transition functions for compatibility */
int mmc_set_ios(struct mmc *mmc); int mmc_set_ios(struct mmc *mmc);
int mmc_getcd(struct mmc *mmc); int mmc_getcd(struct mmc *mmc);
int mmc_getwp(struct mmc *mmc); int mmc_getwp(struct mmc *mmc);
int mmc_execute_tuning(struct mmc *mmc, uint opcode); int mmc_execute_tuning(struct mmc *mmc, uint opcode);
int mmc_wait_dat0(struct mmc *mmc, int state, int timeout); int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us);
int mmc_set_enhanced_strobe(struct mmc *mmc); int mmc_set_enhanced_strobe(struct mmc *mmc);
#else #else
@ -602,8 +602,8 @@ struct mmc {
u8 part_attr; u8 part_attr;
u8 wr_rel_set; u8 wr_rel_set;
u8 part_config; u8 part_config;
u8 gen_cmd6_time; u8 gen_cmd6_time; /* units: 10 ms */
u8 part_switch_time; u8 part_switch_time; /* units: 10 ms */
uint tran_speed; uint tran_speed;
uint legacy_speed; /* speed for the legacy mode provided by the card */ uint legacy_speed; /* speed for the legacy mode provided by the card */
uint read_bl_len; uint read_bl_len;