Merge branch 'master' of git://git.denx.de/u-boot-mmc

This commit is contained in:
Tom Rini
2017-08-18 18:24:36 -04:00
67 changed files with 1520 additions and 1045 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __FSL_SATA_H__
#define __FSL_SATA_H__
#ifndef __DWC_AHSATA_PRIV_H__
#define __DWC_AHSATA_PRIV_H__
#define DWC_AHSATA_MAX_CMD_SLOTS 32
@@ -317,4 +317,4 @@
#define READ_CMD 0
#define WRITE_CMD 1
#endif /* __FSL_SATA_H__ */
#endif /* __DWC_AHSATA_H__ */

View File

@@ -11,17 +11,52 @@
*/
#include <common.h>
#include <ahci.h>
#include <dm.h>
#include <sata.h>
#ifndef CONFIG_AHCI
struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
#endif
int sata_reset(struct udevice *dev)
{
struct ahci_ops *ops = ahci_get_ops(dev);
if (!ops->reset)
return -ENOSYS;
return ops->reset(dev);
}
int sata_dm_port_status(struct udevice *dev, int port)
{
struct ahci_ops *ops = ahci_get_ops(dev);
if (!ops->port_status)
return -ENOSYS;
return ops->port_status(dev, port);
}
int sata_scan(struct udevice *dev)
{
struct ahci_ops *ops = ahci_get_ops(dev);
if (!ops->scan)
return -ENOSYS;
return ops->scan(dev);
}
#ifndef CONFIG_AHCI
#ifdef CONFIG_PARTITIONS
struct blk_desc *sata_get_dev(int dev)
{
return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL;
}
#endif
#endif
#ifdef CONFIG_BLK
static unsigned long sata_bread(struct udevice *dev, lbaint_t start,
@@ -49,6 +84,7 @@ static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start,
}
#endif
#ifndef CONFIG_AHCI
int __sata_initialize(void)
{
int rc, ret = -1;
@@ -95,6 +131,7 @@ __weak int __sata_stop(void)
return err;
}
int sata_stop(void) __attribute__((weak, alias("__sata_stop")));
#endif
#ifdef CONFIG_BLK
static const struct blk_ops sata_blk_ops = {

View File

@@ -57,6 +57,11 @@ static enum uclass_id if_type_to_uclass_id(enum if_type if_type)
return if_type_uclass_id[if_type];
}
const char *blk_get_if_type_name(enum if_type if_type)
{
return if_typename_str[if_type];
}
struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
{
struct blk_desc *desc;
@@ -591,7 +596,7 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name,
}
device_set_name_alloced(*devp);
return ret;
return 0;
}
int blk_unbind_all(int if_type)

View File

@@ -38,6 +38,13 @@ static struct blk_driver *blk_driver_lookup_typename(const char *if_typename)
return NULL;
}
const char *blk_get_if_type_name(enum if_type if_type)
{
struct blk_driver *drv = blk_driver_lookup_type(if_type);
return drv ? drv->if_typename : NULL;
}
/**
* get_desc() - Get the block device descriptor for the given device number
*

View File

@@ -104,5 +104,8 @@ static const struct udevice_id generic_syscon_ids[] = {
U_BOOT_DRIVER(generic_syscon) = {
.name = "syscon",
.id = UCLASS_SYSCON,
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
.bind = dm_scan_fdt_dev,
#endif
.of_match = generic_syscon_ids,
};

View File

@@ -20,16 +20,6 @@ config DM_MMC
appear as block devices in U-Boot and can support filesystems such
as EXT4 and FAT.
config DM_MMC_OPS
bool "Support MMC controller operations using Driver Model"
depends on DM_MMC
default y if DM_MMC
help
Driver model provides a means of supporting device operations. This
option moves MMC operations under the control of driver model. The
option will be removed as soon as all DM_MMC drivers use it, as it
will the only supported behaviour.
config SPL_DM_MMC
bool "Enable MMC controllers using Driver Model in SPL"
depends on SPL_DM && DM_MMC
@@ -41,16 +31,6 @@ config SPL_DM_MMC
appear as block devices in U-Boot and can support filesystems such
as EXT4 and FAT.
config SPL_DM_MMC_OPS
bool "Support MMC controller operations using Driver Model in SPL"
depends on SPL_DM && DM_MMC_OPS
default y
help
Driver model provides a means of supporting device operations. This
option moves MMC operations under the control of driver model. The
option will be removed as soon as all DM_MMC drivers use it, as it
will the only supported behaviour.
if MMC
config SPL_MMC_TINY
@@ -124,7 +104,7 @@ config MMC_DW_SOCFPGA
config MMC_MESON_GX
bool "Meson GX EMMC controller support"
depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_MESON
depends on DM_MMC && BLK && ARCH_MESON
help
Support for EMMC host controller on Meson GX ARM SoCs platform (S905)
@@ -155,7 +135,7 @@ config MMC_PCI
config MMC_OMAP_HS
bool "TI OMAP High Speed Multimedia Card Interface support"
select DM_MMC_OPS if DM_MMC
select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR
help
This selects the TI OMAP High Speed Multimedia card Interface.
If you have an omap2plus board with a Multimedia Card slot,
@@ -184,7 +164,7 @@ config SH_SDHI
config MMC_UNIPHIER
bool "UniPhier SD/MMC Host Controller support"
depends on ARCH_UNIPHIER
depends on BLK && DM_MMC_OPS
depends on BLK && DM_MMC
depends on OF_CONTROL
help
This selects support for the SD/MMC Host Controller on UniPhier SoCs.
@@ -192,7 +172,7 @@ config MMC_UNIPHIER
config MMC_SANDBOX
bool "Sandbox MMC support"
depends on SANDBOX
depends on BLK && DM_MMC_OPS && OF_CONTROL
depends on BLK && DM_MMC && OF_CONTROL
help
This select a dummy sandbox MMC driver. At present this does nothing
other than allow sandbox to be build with MMC support. This
@@ -227,7 +207,7 @@ config MMC_SDHCI_SDMA
config MMC_SDHCI_ATMEL
bool "Atmel SDHCI controller support"
depends on ARCH_AT91
depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91
depends on DM_MMC && BLK && ARCH_AT91
depends on MMC_SDHCI
help
This enables support for the Atmel SDHCI controller, which supports
@@ -251,7 +231,7 @@ config MMC_SDHCI_BCM2835
config MMC_SDHCI_CADENCE
bool "SDHCI support for the Cadence SD/SDIO/eMMC controller"
depends on BLK && DM_MMC_OPS
depends on BLK && DM_MMC
depends on MMC_SDHCI
depends on OF_CONTROL
help
@@ -273,7 +253,7 @@ config MMC_SDHCI_KONA
config MMC_SDHCI_MSM
bool "Qualcomm SDHCI controller"
depends on BLK && DM_MMC_OPS
depends on BLK && DM_MMC
depends on MMC_SDHCI
help
Enables support for SDHCI 2.0 controller present on some Qualcomm
@@ -303,7 +283,7 @@ config MMC_SDHCI_PIC32
config MMC_SDHCI_ROCKCHIP
bool "Arasan SDHCI controller for Rockchip support"
depends on ARCH_ROCKCHIP
depends on DM_MMC && BLK && DM_MMC_OPS
depends on DM_MMC && BLK
depends on MMC_SDHCI
help
Support for Arasan SDHCI host controller on Rockchip ARM SoCs platform
@@ -376,7 +356,7 @@ config MMC_SDHCI_TEGRA
config MMC_SDHCI_ZYNQ
bool "Arasan SDHCI controller support"
depends on ARCH_ZYNQ || ARCH_ZYNQMP
depends on DM_MMC && OF_CONTROL && BLK && DM_MMC_OPS
depends on DM_MMC && OF_CONTROL && BLK
depends on MMC_SDHCI
help
Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs platform
@@ -391,7 +371,7 @@ config MMC_SUNXI
config GENERIC_ATMEL_MCI
bool "Atmel Multimedia Card Interface support"
depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91
depends on DM_MMC && BLK && ARCH_AT91
help
This enables support for Atmel High Speed Multimedia Card Interface
(HSMCI), which supports the MultiMedia Card (MMC) Specification V4.3,

View File

@@ -184,7 +184,7 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host,
return mode;
}
#ifdef CONFIG_DM_MMC_OPS
#ifdef CONFIG_DM_MMC
static int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
@@ -383,7 +383,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
return 0;
}
#ifdef CONFIG_DM_MMC_OPS
#ifdef CONFIG_DM_MMC
static int dwmci_set_ios(struct udevice *dev)
{
struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -466,7 +466,7 @@ static int dwmci_init(struct mmc *mmc)
return 0;
}
#ifdef CONFIG_DM_MMC_OPS
#ifdef CONFIG_DM_MMC
int dwmci_probe(struct udevice *dev)
{
struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -491,7 +491,7 @@ void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host,
u32 max_clk, u32 min_clk)
{
cfg->name = host->name;
#ifndef CONFIG_DM_MMC_OPS
#ifndef CONFIG_DM_MMC
cfg->ops = &dwmci_ops;
#endif
cfg->f_min = min_clk;

View File

@@ -81,6 +81,11 @@ struct fsl_esdhc {
uint scr; /* eSDHC control register */
};
struct fsl_esdhc_plat {
struct mmc_config cfg;
struct mmc mmc;
};
/**
* struct fsl_esdhc_priv
*
@@ -101,8 +106,9 @@ struct fsl_esdhc_priv {
struct fsl_esdhc *esdhc_regs;
unsigned int sdhc_clk;
unsigned int bus_width;
struct mmc_config cfg;
#if !CONFIG_IS_ENABLED(BLK)
struct mmc *mmc;
#endif
struct udevice *dev;
int non_removable;
int wp_enable;
@@ -156,10 +162,9 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
/*
* PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
*/
static void
esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv,
struct mmc_data *data)
{
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
uint blocks;
char *buffer;
@@ -218,10 +223,10 @@ esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
}
#endif
static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
struct mmc_data *data)
{
int timeout;
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
dma_addr_t addr;
@@ -349,13 +354,12 @@ static void check_and_invalidate_dcache_range
* Sends a command out on the bus. Takes the mmc pointer,
* a command pointer, and an optional data pointer.
*/
static int
esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
struct mmc_cmd *cmd, struct mmc_data *data)
{
int err = 0;
uint xfertyp;
uint irqstat;
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
@@ -384,7 +388,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
/* Set up for a data transfer if we have one */
if (data) {
err = esdhc_setup_data(mmc, data);
err = esdhc_setup_data(priv, mmc, data);
if(err)
return err;
@@ -470,7 +474,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
/* Wait until all of the blocks are transferred */
if (data) {
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
esdhc_pio_read_write(mmc, data);
esdhc_pio_read_write(priv, data);
#else
do {
irqstat = esdhc_read32(&regs->irqstat);
@@ -522,7 +526,7 @@ out:
return err;
}
static void set_sysctl(struct mmc *mmc, uint clock)
static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
{
int div = 1;
#ifdef ARCH_MXC
@@ -531,7 +535,6 @@ static void set_sysctl(struct mmc *mmc, uint clock)
int pre_div = 2;
#endif
int ddr_pre_div = mmc->ddr_mode ? 2 : 1;
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
int sdhc_clk = priv->sdhc_clk;
uint clk;
@@ -569,9 +572,8 @@ static void set_sysctl(struct mmc *mmc, uint clock)
}
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
static void esdhc_clock_control(struct mmc *mmc, bool enable)
static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
{
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
u32 value;
u32 time_out;
@@ -598,19 +600,18 @@ static void esdhc_clock_control(struct mmc *mmc, bool enable)
}
#endif
static int esdhc_set_ios(struct mmc *mmc)
static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
/* Select to use peripheral clock */
esdhc_clock_control(mmc, false);
esdhc_clock_control(priv, false);
esdhc_setbits32(&regs->scr, ESDHCCTL_PCS);
esdhc_clock_control(mmc, true);
esdhc_clock_control(priv, true);
#endif
/* Set the clock speed */
set_sysctl(mmc, mmc->clock);
set_sysctl(priv, mmc, mmc->clock);
/* Set the bus width */
esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
@@ -623,18 +624,20 @@ static int esdhc_set_ios(struct mmc *mmc)
return 0;
}
static int esdhc_init(struct mmc *mmc)
static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
int timeout = 1000;
ulong start;
/* Reset the entire host controller */
esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
/* Wait until the controller is available */
while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
udelay(1000);
start = get_timer(0);
while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) {
if (get_timer(start) > 1000)
return -ETIMEDOUT;
}
#if defined(CONFIG_FSL_USDHC)
/* RSTA doesn't reset MMC_BOOT register, so manually reset it */
@@ -679,9 +682,8 @@ static int esdhc_init(struct mmc *mmc)
return 0;
}
static int esdhc_getcd(struct mmc *mmc)
static int esdhc_getcd_common(struct fsl_esdhc_priv *priv)
{
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
int timeout = 1000;
@@ -690,7 +692,7 @@ static int esdhc_getcd(struct mmc *mmc)
return 1;
#endif
#ifdef CONFIG_DM_MMC
#if CONFIG_IS_ENABLED(DM_MMC)
if (priv->non_removable)
return 1;
#ifdef CONFIG_DM_GPIO
@@ -705,32 +707,70 @@ static int esdhc_getcd(struct mmc *mmc)
return timeout > 0;
}
static void esdhc_reset(struct fsl_esdhc *regs)
static int esdhc_reset(struct fsl_esdhc *regs)
{
unsigned long timeout = 100; /* wait max 100 ms */
ulong start;
/* reset the controller */
esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
/* hardware clears the bit when it is done */
while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
udelay(1000);
if (!timeout)
printf("MMC/SD: Reset never completed.\n");
start = get_timer(0);
while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) {
if (get_timer(start) > 100) {
printf("MMC/SD: Reset never completed.\n");
return -ETIMEDOUT;
}
}
return 0;
}
#if !CONFIG_IS_ENABLED(DM_MMC)
static int esdhc_getcd(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_getcd_common(priv);
}
static int esdhc_init(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_init_common(priv, mmc);
}
static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_send_cmd_common(priv, mmc, cmd, data);
}
static int esdhc_set_ios(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
return esdhc_set_ios_common(priv, mmc);
}
static const struct mmc_ops esdhc_ops = {
.getcd = esdhc_getcd,
.init = esdhc_init,
.send_cmd = esdhc_send_cmd,
.set_ios = esdhc_set_ios,
.init = esdhc_init,
.getcd = esdhc_getcd,
};
#endif
static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
static int fsl_esdhc_init(struct fsl_esdhc_priv *priv,
struct fsl_esdhc_plat *plat)
{
struct mmc_config *cfg;
struct fsl_esdhc *regs;
struct mmc *mmc;
u32 caps, voltage_caps;
int ret;
if (!priv)
return -EINVAL;
@@ -738,7 +778,9 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
regs = priv->esdhc_regs;
/* First reset the eSDHC controller */
esdhc_reset(regs);
ret = esdhc_reset(regs);
if (ret)
return ret;
#ifndef CONFIG_FSL_USDHC
esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
@@ -752,7 +794,10 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
memset(&priv->cfg, 0, sizeof(priv->cfg));
cfg = &plat->cfg;
#ifndef CONFIG_DM_MMC
memset(cfg, '\0', sizeof(*cfg));
#endif
voltage_caps = 0;
caps = esdhc_read32(&regs->hostcapblt);
@@ -774,58 +819,54 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
if (caps & ESDHC_HOSTCAPBLT_VS33)
voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
priv->cfg.name = "FSL_SDHC";
priv->cfg.ops = &esdhc_ops;
#ifdef CONFIG_SYS_SD_VOLTAGE
priv->cfg.voltages = CONFIG_SYS_SD_VOLTAGE;
#else
priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
cfg->name = "FSL_SDHC";
#if !CONFIG_IS_ENABLED(DM_MMC)
cfg->ops = &esdhc_ops;
#endif
if ((priv->cfg.voltages & voltage_caps) == 0) {
#ifdef CONFIG_SYS_SD_VOLTAGE
cfg->voltages = CONFIG_SYS_SD_VOLTAGE;
#else
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
#endif
if ((cfg->voltages & voltage_caps) == 0) {
printf("voltage not supported by controller\n");
return -1;
}
if (priv->bus_width == 8)
priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
else if (priv->bus_width == 4)
priv->cfg.host_caps = MMC_MODE_4BIT;
cfg->host_caps = MMC_MODE_4BIT;
priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
#ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE
priv->cfg.host_caps |= MMC_MODE_DDR_52MHz;
cfg->host_caps |= MMC_MODE_DDR_52MHz;
#endif
if (priv->bus_width > 0) {
if (priv->bus_width < 8)
priv->cfg.host_caps &= ~MMC_MODE_8BIT;
cfg->host_caps &= ~MMC_MODE_8BIT;
if (priv->bus_width < 4)
priv->cfg.host_caps &= ~MMC_MODE_4BIT;
cfg->host_caps &= ~MMC_MODE_4BIT;
}
if (caps & ESDHC_HOSTCAPBLT_HSS)
priv->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
priv->cfg.host_caps &= ~MMC_MODE_8BIT;
cfg->host_caps &= ~MMC_MODE_8BIT;
#endif
priv->cfg.f_min = 400000;
priv->cfg.f_max = min(priv->sdhc_clk, (u32)52000000);
cfg->f_min = 400000;
cfg->f_max = min(priv->sdhc_clk, (u32)52000000);
priv->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
mmc = mmc_create(&priv->cfg, priv);
if (mmc == NULL)
return -1;
priv->mmc = mmc;
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
return 0;
}
#ifndef CONFIG_DM_MMC
#if !CONFIG_IS_ENABLED(DM_MMC)
static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg,
struct fsl_esdhc_priv *priv)
{
@@ -843,7 +884,9 @@ static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg,
int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
{
struct fsl_esdhc_plat *plat;
struct fsl_esdhc_priv *priv;
struct mmc *mmc;
int ret;
if (!cfg)
@@ -852,21 +895,34 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
priv = calloc(sizeof(struct fsl_esdhc_priv), 1);
if (!priv)
return -ENOMEM;
plat = calloc(sizeof(struct fsl_esdhc_plat), 1);
if (!plat) {
free(priv);
return -ENOMEM;
}
ret = fsl_esdhc_cfg_to_priv(cfg, priv);
if (ret) {
debug("%s xlate failure\n", __func__);
free(plat);
free(priv);
return ret;
}
ret = fsl_esdhc_init(priv);
ret = fsl_esdhc_init(priv, plat);
if (ret) {
debug("%s init failure\n", __func__);
free(plat);
free(priv);
return ret;
}
mmc = mmc_create(&plat->cfg, priv);
if (!mmc)
return -EIO;
priv->mmc = mmc;
return 0;
}
@@ -954,7 +1010,7 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd)
}
#endif
#ifdef CONFIG_DM_MMC
#if CONFIG_IS_ENABLED(DM_MMC)
#include <asm/arch/clock.h>
__weak void init_clk_usdhc(u32 index)
{
@@ -963,24 +1019,24 @@ __weak void init_clk_usdhc(u32 index)
static int fsl_esdhc_probe(struct udevice *dev)
{
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
const void *fdt = gd->fdt_blob;
int node = dev_of_offset(dev);
#ifdef CONFIG_DM_REGULATOR
struct udevice *vqmmc_dev;
#endif
fdt_addr_t addr;
unsigned int val;
struct mmc *mmc;
int ret;
addr = devfdt_get_addr(dev);
addr = dev_read_addr(dev);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
priv->esdhc_regs = (struct fsl_esdhc *)addr;
priv->dev = dev;
val = fdtdec_get_int(fdt, node, "bus-width", -1);
val = dev_read_u32_default(dev, "bus-width", -1);
if (val == 8)
priv->bus_width = 8;
else if (val == 4)
@@ -988,21 +1044,21 @@ static int fsl_esdhc_probe(struct udevice *dev)
else
priv->bus_width = 1;
if (fdt_get_property(fdt, node, "non-removable", NULL)) {
if (dev_read_bool(dev, "non-removable")) {
priv->non_removable = 1;
} else {
priv->non_removable = 0;
#ifdef CONFIG_DM_GPIO
gpio_request_by_name_nodev(offset_to_ofnode(node), "cd-gpios",
0, &priv->cd_gpio, GPIOD_IS_IN);
gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
GPIOD_IS_IN);
#endif
}
priv->wp_enable = 1;
#ifdef CONFIG_DM_GPIO
ret = gpio_request_by_name_nodev(offset_to_ofnode(node), "wp-gpios", 0,
&priv->wp_gpio, GPIOD_IS_IN);
ret = gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio,
GPIOD_IS_IN);
if (ret)
priv->wp_enable = 0;
#endif
@@ -1057,18 +1113,53 @@ static int fsl_esdhc_probe(struct udevice *dev)
return -EINVAL;
}
ret = fsl_esdhc_init(priv);
ret = fsl_esdhc_init(priv, plat);
if (ret) {
dev_err(dev, "fsl_esdhc_init failure\n");
return ret;
}
upriv->mmc = priv->mmc;
priv->mmc->dev = dev;
mmc = &plat->mmc;
mmc->cfg = &plat->cfg;
mmc->dev = dev;
upriv->mmc = mmc;
return 0;
return esdhc_init_common(priv, mmc);
}
#if CONFIG_IS_ENABLED(DM_MMC)
static int fsl_esdhc_get_cd(struct udevice *dev)
{
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
return true;
return esdhc_getcd_common(priv);
}
static int fsl_esdhc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
return esdhc_send_cmd_common(priv, &plat->mmc, cmd, data);
}
static int fsl_esdhc_set_ios(struct udevice *dev)
{
struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
return esdhc_set_ios_common(priv, &plat->mmc);
}
static const struct dm_mmc_ops fsl_esdhc_ops = {
.get_cd = fsl_esdhc_get_cd,
.send_cmd = fsl_esdhc_send_cmd,
.set_ios = fsl_esdhc_set_ios,
};
#endif
static const struct udevice_id fsl_esdhc_ids[] = {
{ .compatible = "fsl,imx6ul-usdhc", },
{ .compatible = "fsl,imx6sx-usdhc", },
@@ -1080,11 +1171,25 @@ static const struct udevice_id fsl_esdhc_ids[] = {
{ /* sentinel */ }
};
#if CONFIG_IS_ENABLED(BLK)
static int fsl_esdhc_bind(struct udevice *dev)
{
struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
return mmc_bind(dev, &plat->mmc, &plat->cfg);
}
#endif
U_BOOT_DRIVER(fsl_esdhc) = {
.name = "fsl-esdhc-mmc",
.id = UCLASS_MMC,
.of_match = fsl_esdhc_ids,
.ops = &fsl_esdhc_ops,
#if CONFIG_IS_ENABLED(BLK)
.bind = fsl_esdhc_bind,
#endif
.probe = fsl_esdhc_probe,
.platdata_auto_alloc_size = sizeof(struct fsl_esdhc_plat),
.priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv),
};
#endif

View File

@@ -36,13 +36,22 @@ DECLARE_GLOBAL_DATA_PTR;
# define MCI_BUS 0
#endif
struct atmel_mci_priv {
#ifdef CONFIG_DM_MMC
struct atmel_mci_plat {
struct mmc mmc;
struct mmc_config cfg;
struct atmel_mci *mci;
};
#endif
struct atmel_mci_priv {
#ifndef CONFIG_DM_MMC
struct mmc_config cfg;
struct atmel_mci *mci;
#endif
unsigned int initialized:1;
unsigned int curr_clk;
#ifdef CONFIG_DM_MMC
struct mmc mmc;
ulong bus_clk_rate;
#endif
};
@@ -67,18 +76,21 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
/* Setup for MCI Clock and Block Size */
#ifdef CONFIG_DM_MMC
static void mci_set_mode(struct atmel_mci_priv *priv, u32 hz, u32 blklen)
static void mci_set_mode(struct udevice *dev, u32 hz, u32 blklen)
{
struct mmc *mmc = &priv->mmc;
struct atmel_mci_plat *plat = dev_get_platdata(dev);
struct atmel_mci_priv *priv = dev_get_priv(dev);
struct mmc *mmc = &plat->mmc;
u32 bus_hz = priv->bus_clk_rate;
atmel_mci_t *mci = plat->mci;
#else
static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
{
struct atmel_mci_priv *priv = mmc->priv;
u32 bus_hz = get_mci_clk_rate();
atmel_mci_t *mci = priv->mci;
#endif
atmel_mci_t *mci = priv->mci;
u32 clkdiv = 255;
unsigned int version = atmel_mci_get_version(mci);
u32 clkodd = 0;
@@ -222,15 +234,17 @@ io_fail:
static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct atmel_mci_plat *plat = dev_get_platdata(dev);
struct atmel_mci_priv *priv = dev_get_priv(dev);
struct mmc *mmc = mmc_get_mmc_dev(dev);
atmel_mci_t *mci = plat->mci;
#else
static int
mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
struct atmel_mci_priv *priv = mmc->priv;
#endif
atmel_mci_t *mci = priv->mci;
#endif
u32 cmdr;
u32 error_flags = 0;
u32 status;
@@ -362,22 +376,23 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
#ifdef CONFIG_DM_MMC
static int atmel_mci_set_ios(struct udevice *dev)
{
struct atmel_mci_priv *priv = dev_get_priv(dev);
struct atmel_mci_plat *plat = dev_get_platdata(dev);
struct mmc *mmc = mmc_get_mmc_dev(dev);
atmel_mci_t *mci = plat->mci;
#else
/* Entered into mmc structure during driver init */
static int mci_set_ios(struct mmc *mmc)
{
struct atmel_mci_priv *priv = mmc->priv;
#endif
atmel_mci_t *mci = priv->mci;
#endif
int bus_width = mmc->bus_width;
unsigned int version = atmel_mci_get_version(mci);
int busw;
/* Set the clock speed */
#ifdef CONFIG_DM_MMC
mci_set_mode(priv, mmc->clock, MMC_DEFAULT_BLKLEN);
mci_set_mode(dev, mmc->clock, MMC_DEFAULT_BLKLEN);
#else
mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
#endif
@@ -410,15 +425,17 @@ static int mci_set_ios(struct mmc *mmc)
}
#ifdef CONFIG_DM_MMC
static int atmel_mci_hw_init(struct atmel_mci_priv *priv)
static int atmel_mci_hw_init(struct udevice *dev)
{
struct atmel_mci_plat *plat = dev_get_platdata(dev);
atmel_mci_t *mci = plat->mci;
#else
/* Entered into mmc structure during driver init */
static int mci_init(struct mmc *mmc)
{
struct atmel_mci_priv *priv = mmc->priv;
#endif
atmel_mci_t *mci = priv->mci;
#endif
/* Initialize controller */
writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */
@@ -433,7 +450,7 @@ static int mci_init(struct mmc *mmc)
/* Set default clocks and blocklen */
#ifdef CONFIG_DM_MMC
mci_set_mode(priv, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
mci_set_mode(dev, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
#else
mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
#endif
@@ -509,12 +526,14 @@ static const struct dm_mmc_ops atmel_mci_mmc_ops = {
.set_ios = atmel_mci_set_ios,
};
static void atmel_mci_setup_cfg(struct atmel_mci_priv *priv)
static void atmel_mci_setup_cfg(struct udevice *dev)
{
struct atmel_mci_plat *plat = dev_get_platdata(dev);
struct atmel_mci_priv *priv = dev_get_priv(dev);
struct mmc_config *cfg;
u32 version;
cfg = &priv->cfg;
cfg = &plat->cfg;
cfg->name = "Atmel mci";
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
@@ -522,7 +541,7 @@ static void atmel_mci_setup_cfg(struct atmel_mci_priv *priv)
* If the version is above 3.0, the capabilities of the 8-bit
* bus width and high speed are supported.
*/
version = atmel_mci_get_version(priv->mci);
version = atmel_mci_get_version(plat->mci);
if ((version & 0xf00) >= 0x300) {
cfg->host_caps = MMC_MODE_8BIT |
MMC_MODE_HS | MMC_MODE_HS_52MHz;
@@ -568,7 +587,7 @@ failed:
static int atmel_mci_probe(struct udevice *dev)
{
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct atmel_mci_priv *priv = dev_get_priv(dev);
struct atmel_mci_plat *plat = dev_get_platdata(dev);
struct mmc *mmc;
int ret;
@@ -576,25 +595,25 @@ static int atmel_mci_probe(struct udevice *dev)
if (ret)
return ret;
priv->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev);
plat->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev);
atmel_mci_setup_cfg(priv);
atmel_mci_setup_cfg(dev);
mmc = &priv->mmc;
mmc->cfg = &priv->cfg;
mmc = &plat->mmc;
mmc->cfg = &plat->cfg;
mmc->dev = dev;
upriv->mmc = mmc;
atmel_mci_hw_init(priv);
atmel_mci_hw_init(dev);
return 0;
}
static int atmel_mci_bind(struct udevice *dev)
{
struct atmel_mci_priv *priv = dev_get_priv(dev);
struct atmel_mci_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 udevice_id atmel_mci_ids[] = {
@@ -608,6 +627,7 @@ U_BOOT_DRIVER(atmel_mci) = {
.of_match = atmel_mci_ids,
.bind = atmel_mci_bind,
.probe = atmel_mci_probe,
.platdata_auto_alloc_size = sizeof(struct atmel_mci_plat),
.priv_auto_alloc_size = sizeof(struct atmel_mci_priv),
.ops = &atmel_mci_mmc_ops,
};

View File

@@ -15,7 +15,6 @@
DECLARE_GLOBAL_DATA_PTR;
#if CONFIG_IS_ENABLED(DM_MMC_OPS)
int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
@@ -79,7 +78,6 @@ int mmc_getcd(struct mmc *mmc)
{
return dm_mmc_get_cd(mmc->dev);
}
#endif
struct mmc *mmc_get_mmc_dev(struct udevice *dev)
{
@@ -198,10 +196,8 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
struct udevice *bdev;
int ret, devnum = -1;
#if CONFIG_IS_ENABLED(DM_MMC_OPS)
if (!mmc_get_ops(dev))
return -ENOSYS;
#endif
#ifndef CONFIG_SPL_BUILD
/* Use the fixed index with aliase node's index */
ret = dev_read_alias_seq(dev, &devnum);

View File

@@ -53,7 +53,7 @@ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
}
#endif
#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
#if !CONFIG_IS_ENABLED(DM_MMC)
__weak int board_mmc_getwp(struct mmc *mmc)
{
return -1;
@@ -149,7 +149,7 @@ void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
}
#endif
#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
#if !CONFIG_IS_ENABLED(DM_MMC)
int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
int ret;
@@ -839,7 +839,7 @@ int mmc_hwpart_config(struct mmc *mmc,
return 0;
}
#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
#if !CONFIG_IS_ENABLED(DM_MMC)
int mmc_getcd(struct mmc *mmc)
{
int cd;
@@ -1075,7 +1075,7 @@ static const u8 multipliers[] = {
80,
};
#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
#if !CONFIG_IS_ENABLED(DM_MMC)
static void mmc_set_ios(struct mmc *mmc)
{
if (mmc->cfg->ops->set_ios)
@@ -1652,7 +1652,7 @@ int mmc_start_init(struct mmc *mmc)
/* we pretend there's no card when init is NULL */
no_card = mmc_getcd(mmc) == 0;
#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
#if !CONFIG_IS_ENABLED(DM_MMC)
no_card = no_card || (mmc->cfg->ops->init == NULL);
#endif
if (no_card) {
@@ -1673,7 +1673,7 @@ int mmc_start_init(struct mmc *mmc)
if (err)
return err;
#if CONFIG_IS_ENABLED(DM_MMC_OPS)
#if CONFIG_IS_ENABLED(DM_MMC)
/* The device has already been probed ready for use */
#else
/* made sure it's not NULL earlier */

View File

@@ -100,10 +100,19 @@ int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
*/
int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
{
return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
EXT_CSD_BOOT_ACK(ack) |
EXT_CSD_BOOT_PART_NUM(part_num) |
EXT_CSD_PARTITION_ACCESS(access));
int ret;
u8 part_conf;
part_conf = EXT_CSD_BOOT_ACK(ack) |
EXT_CSD_BOOT_PART_NUM(part_num) |
EXT_CSD_PARTITION_ACCESS(access);
ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
part_conf);
if (!ret)
mmc->part_config = part_conf;
return ret;
}
/*

View File

@@ -150,7 +150,7 @@ struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
cfg->f_max == 0 || cfg->b_max == 0)
return NULL;
#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
#if !CONFIG_IS_ENABLED(DM_MMC)
if (cfg->ops == NULL || cfg->ops->send_cmd == NULL)
return NULL;
#endif

View File

@@ -64,12 +64,7 @@ U_BOOT_DRIVER(pci_mmc) = {
};
static struct pci_device_id mmc_supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_SDIO) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_SD) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_EMMC2) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_SDIO) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_0) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_1) },
{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_SDHCI << 8, 0xffff00) },
{},
};

View File

@@ -134,7 +134,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
#define SDHCI_CMD_DEFAULT_TIMEOUT 100
#define SDHCI_READ_STATUS_TIMEOUT 1000
#ifdef CONFIG_DM_MMC_OPS
#ifdef CONFIG_DM_MMC
static int sdhci_send_command(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
@@ -422,7 +422,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
}
#ifdef CONFIG_DM_MMC_OPS
#ifdef CONFIG_DM_MMC
static int sdhci_set_ios(struct udevice *dev)
{
struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -502,7 +502,7 @@ static int sdhci_init(struct mmc *mmc)
return 0;
}
#ifdef CONFIG_DM_MMC_OPS
#ifdef CONFIG_DM_MMC
int sdhci_probe(struct udevice *dev)
{
struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -543,7 +543,7 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
cfg->name = host->name;
#ifndef CONFIG_DM_MMC_OPS
#ifndef CONFIG_DM_MMC
cfg->ops = &sdhci_ops;
#endif

View File

@@ -13,21 +13,26 @@
#include <common.h>
#include <malloc.h>
#include <mmc.h>
#include <dm.h>
#include <linux/errno.h>
#include <asm/io.h>
#include <linux/compat.h>
#include <linux/io.h>
#include <linux/sizes.h>
#include <asm/arch/rmobile.h>
#include <asm/arch/sh_sdhi.h>
#include <clk.h>
#define DRIVER_NAME "sh-sdhi"
struct sh_sdhi_host {
unsigned long addr;
void __iomem *addr;
int ch;
int bus_shift;
unsigned long quirks;
unsigned char wait_int;
unsigned char sd_error;
unsigned char detect_waiting;
unsigned char app_cmd;
};
static inline void sh_sdhi_writeq(struct sh_sdhi_host *host, int reg, u64 val)
@@ -50,11 +55,6 @@ static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
return readw(host->addr + (reg << host->bus_shift));
}
static void *mmc_priv(struct mmc *mmc)
{
return (void *)mmc->priv;
}
static void sh_sdhi_detect(struct sh_sdhi_host *host)
{
sh_sdhi_writew(host, SDHI_OPTION,
@@ -477,65 +477,64 @@ static void sh_sdhi_get_response(struct sh_sdhi_host *host, struct mmc_cmd *cmd)
static unsigned short sh_sdhi_set_cmd(struct sh_sdhi_host *host,
struct mmc_data *data, unsigned short opc)
{
switch (opc) {
case SD_CMD_APP_SEND_OP_COND:
case SD_CMD_APP_SEND_SCR:
opc |= SDHI_APP;
break;
case SD_CMD_APP_SET_BUS_WIDTH:
/* SD_APP_SET_BUS_WIDTH*/
if (host->app_cmd) {
if (!data)
opc |= SDHI_APP;
else /* SD_SWITCH */
opc = SDHI_SD_SWITCH;
break;
case MMC_CMD_SEND_OP_COND:
opc = SDHI_MMC_SEND_OP_COND;
break;
case MMC_CMD_SEND_EXT_CSD:
if (data)
opc = SDHI_MMC_SEND_EXT_CSD;
break;
default:
break;
host->app_cmd = 0;
return opc | BIT(6);
}
switch (opc) {
case MMC_CMD_SWITCH:
return opc | (data ? 0x1c00 : 0x40);
case MMC_CMD_SEND_EXT_CSD:
return opc | (data ? 0x1c00 : 0);
case MMC_CMD_SEND_OP_COND:
return opc | 0x0700;
case MMC_CMD_APP_CMD:
host->app_cmd = 1;
default:
return opc;
}
return opc;
}
static unsigned short sh_sdhi_data_trans(struct sh_sdhi_host *host,
struct mmc_data *data, unsigned short opc)
{
unsigned short ret;
switch (opc) {
case MMC_CMD_READ_MULTIPLE_BLOCK:
ret = sh_sdhi_multi_read(host, data);
break;
case MMC_CMD_WRITE_MULTIPLE_BLOCK:
ret = sh_sdhi_multi_write(host, data);
break;
case MMC_CMD_WRITE_SINGLE_BLOCK:
ret = sh_sdhi_single_write(host, data);
break;
case MMC_CMD_READ_SINGLE_BLOCK:
case SDHI_SD_APP_SEND_SCR:
case SDHI_SD_SWITCH: /* SD_SWITCH */
case SDHI_MMC_SEND_EXT_CSD:
ret = sh_sdhi_single_read(host, data);
break;
default:
printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
ret = -EINVAL;
break;
if (host->app_cmd) {
host->app_cmd = 0;
switch (opc) {
case SD_CMD_APP_SEND_SCR:
case SD_CMD_APP_SD_STATUS:
return sh_sdhi_single_read(host, data);
default:
printf(DRIVER_NAME": SD: NOT SUPPORT APP CMD = d'%04d\n",
opc);
return -EINVAL;
}
} else {
switch (opc) {
case MMC_CMD_WRITE_MULTIPLE_BLOCK:
return sh_sdhi_multi_write(host, data);
case MMC_CMD_READ_MULTIPLE_BLOCK:
return sh_sdhi_multi_read(host, data);
case MMC_CMD_WRITE_SINGLE_BLOCK:
return sh_sdhi_single_write(host, data);
case MMC_CMD_READ_SINGLE_BLOCK:
case MMC_CMD_SWITCH:
case MMC_CMD_SEND_EXT_CSD:;
return sh_sdhi_single_read(host, data);
default:
printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
return -EINVAL;
}
}
return ret;
}
static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
struct mmc_data *data, struct mmc_cmd *cmd)
{
long time;
unsigned short opc = cmd->cmdidx;
unsigned short shcmd, opc = cmd->cmdidx;
int ret = 0;
unsigned long timeout;
@@ -563,7 +562,8 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
}
sh_sdhi_writew(host, SDHI_SIZE, data->blocksize);
}
opc = sh_sdhi_set_cmd(host, data, opc);
shcmd = sh_sdhi_set_cmd(host, data, opc);
/*
* U-Boot cannot use interrupt.
@@ -594,11 +594,12 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
INFO2M_RESP_TIMEOUT | INFO2M_ILA) &
sh_sdhi_readw(host, SDHI_INFO2_MASK));
sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(opc & CMD_MASK));
sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(shcmd & CMD_MASK));
time = sh_sdhi_wait_interrupt_flag(host);
if (!time)
if (!time) {
host->app_cmd = 0;
return sh_sdhi_error_manage(host);
}
if (host->sd_error) {
switch (cmd->cmdidx) {
@@ -616,15 +617,20 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
}
host->sd_error = 0;
host->wait_int = 0;
host->app_cmd = 0;
return ret;
}
if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END)
if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END) {
host->app_cmd = 0;
return -EINVAL;
}
if (host->wait_int) {
sh_sdhi_get_response(host, cmd);
host->wait_int = 0;
}
if (data)
ret = sh_sdhi_data_trans(host, data, opc);
@@ -634,23 +640,17 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
return ret;
}
static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
struct mmc_cmd *cmd, struct mmc_data *data)
{
struct sh_sdhi_host *host = mmc_priv(mmc);
int ret;
host->sd_error = 0;
ret = sh_sdhi_start_cmd(host, data, cmd);
return ret;
return sh_sdhi_start_cmd(host, data, cmd);
}
static int sh_sdhi_set_ios(struct mmc *mmc)
static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc)
{
int ret;
struct sh_sdhi_host *host = mmc_priv(mmc);
ret = sh_sdhi_clock_control(host, mmc->clock);
if (ret)
@@ -674,9 +674,8 @@ static int sh_sdhi_set_ios(struct mmc *mmc)
return 0;
}
static int sh_sdhi_initialize(struct mmc *mmc)
static int sh_sdhi_initialize_common(struct sh_sdhi_host *host)
{
struct sh_sdhi_host *host = mmc_priv(mmc);
int ret = sh_sdhi_sync_reset(host);
sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
@@ -692,6 +691,34 @@ static int sh_sdhi_initialize(struct mmc *mmc)
return ret;
}
#ifndef CONFIG_DM_MMC
static void *mmc_priv(struct mmc *mmc)
{
return (void *)mmc->priv;
}
static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct sh_sdhi_host *host = mmc_priv(mmc);
return sh_sdhi_send_cmd_common(host, cmd, data);
}
static int sh_sdhi_set_ios(struct mmc *mmc)
{
struct sh_sdhi_host *host = mmc_priv(mmc);
return sh_sdhi_set_ios_common(host, mmc);
}
static int sh_sdhi_initialize(struct mmc *mmc)
{
struct sh_sdhi_host *host = mmc_priv(mmc);
return sh_sdhi_initialize_common(host);
}
static const struct mmc_ops sh_sdhi_ops = {
.send_cmd = sh_sdhi_send_cmd,
.set_ios = sh_sdhi_set_ios,
@@ -743,7 +770,7 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
}
host->ch = ch;
host->addr = addr;
host->addr = (void __iomem *)addr;
host->quirks = quirks;
if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
@@ -757,3 +784,123 @@ error:
free(host);
return ret;
}
#else
struct sh_sdhi_plat {
struct mmc_config cfg;
struct mmc mmc;
};
int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct sh_sdhi_host *host = dev_get_priv(dev);
return sh_sdhi_send_cmd_common(host, cmd, data);
}
int sh_sdhi_dm_set_ios(struct udevice *dev)
{
struct sh_sdhi_host *host = dev_get_priv(dev);
struct mmc *mmc = mmc_get_mmc_dev(dev);
return sh_sdhi_set_ios_common(host, mmc);
}
static const struct dm_mmc_ops sh_sdhi_dm_ops = {
.send_cmd = sh_sdhi_dm_send_cmd,
.set_ios = sh_sdhi_dm_set_ios,
};
static int sh_sdhi_dm_bind(struct udevice *dev)
{
struct sh_sdhi_plat *plat = dev_get_platdata(dev);
return mmc_bind(dev, &plat->mmc, &plat->cfg);
}
static int sh_sdhi_dm_probe(struct udevice *dev)
{
struct sh_sdhi_plat *plat = dev_get_platdata(dev);
struct sh_sdhi_host *host = dev_get_priv(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct clk sh_sdhi_clk;
const u32 quirks = dev_get_driver_data(dev);
fdt_addr_t base;
int ret;
base = devfdt_get_addr(dev);
if (base == FDT_ADDR_T_NONE)
return -EINVAL;
host->addr = devm_ioremap(dev, base, SZ_2K);
if (!host->addr)
return -ENOMEM;
ret = clk_get_by_index(dev, 0, &sh_sdhi_clk);
if (ret) {
debug("failed to get clock, ret=%d\n", ret);
return ret;
}
ret = clk_enable(&sh_sdhi_clk);
if (ret) {
debug("failed to enable clock, ret=%d\n", ret);
return ret;
}
host->quirks = quirks;
if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
host->bus_shift = 2;
else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
host->bus_shift = 1;
plat->cfg.name = dev->name;
plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
1)) {
case 8:
plat->cfg.host_caps |= MMC_MODE_8BIT;
break;
case 4:
plat->cfg.host_caps |= MMC_MODE_4BIT;
break;
case 1:
break;
default:
dev_err(dev, "Invalid \"bus-width\" value\n");
return -EINVAL;
}
sh_sdhi_initialize_common(host);
plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
plat->cfg.f_min = CLKDEV_INIT;
plat->cfg.f_max = CLKDEV_HS_DATA;
plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
upriv->mmc = &plat->mmc;
return 0;
}
static const struct udevice_id sh_sdhi_sd_match[] = {
{ .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
{ .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
{ /* sentinel */ }
};
U_BOOT_DRIVER(sh_sdhi_mmc) = {
.name = "sh-sdhi-mmc",
.id = UCLASS_MMC,
.of_match = sh_sdhi_sd_match,
.bind = sh_sdhi_dm_bind,
.probe = sh_sdhi_dm_probe,
.priv_auto_alloc_size = sizeof(struct sh_sdhi_host),
.platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat),
.ops = &sh_sdhi_dm_ops,
};
#endif

View File

@@ -470,13 +470,13 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32);
u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10);
cmd->response[0] = (rsp_127_104 & 0xffffff) << 8 |
(rsp_103_72 & 0xff);
cmd->response[1] = (rsp_103_72 & 0xffffff) << 8 |
(rsp_71_40 & 0xff);
cmd->response[2] = (rsp_71_40 & 0xffffff) << 8 |
(rsp_39_8 & 0xff);
cmd->response[3] = (rsp_39_8 & 0xffffff) << 8;
cmd->response[0] = ((rsp_127_104 & 0x00ffffff) << 8) |
((rsp_103_72 & 0xff000000) >> 24);
cmd->response[1] = ((rsp_103_72 & 0x00ffffff) << 8) |
((rsp_71_40 & 0xff000000) >> 24);
cmd->response[2] = ((rsp_71_40 & 0x00ffffff) << 8) |
((rsp_39_8 & 0xff000000) >> 24);
cmd->response[3] = (rsp_39_8 & 0xffffff) << 8;
} else {
/* bit 39-8 */
cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10);