mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-06-29 18:11:43 +00:00
Merge tag 'mmc-2021-2-19' of https://gitlab.denx.de/u-boot/custodians/u-boot-mmc
- mmc_spi improvement - added mmc-pwrseq to remove duplicated code - fix response timeout after switch command - sdhci: skip cache invalidation if DMA is not used
This commit is contained in:
commit
a1a652e801
16 changed files with 153 additions and 107 deletions
|
@ -9,6 +9,7 @@ config MESON64_COMMON
|
||||||
select SYSCON
|
select SYSCON
|
||||||
select REGMAP
|
select REGMAP
|
||||||
select PWRSEQ
|
select PWRSEQ
|
||||||
|
select MMC_PWRSEQ
|
||||||
select BOARD_LATE_INIT
|
select BOARD_LATE_INIT
|
||||||
imply CMD_DM
|
imply CMD_DM
|
||||||
|
|
||||||
|
|
|
@ -1017,13 +1017,13 @@ U_BOOT_CMD(
|
||||||
" Power cycling is required to initialize partitions after set to complete.\n"
|
" Power cycling is required to initialize partitions after set to complete.\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SUPPORT_EMMC_BOOT
|
#ifdef CONFIG_SUPPORT_EMMC_BOOT
|
||||||
"mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n"
|
"mmc bootbus <dev> <boot_bus_width> <reset_boot_bus_width> <boot_mode>\n"
|
||||||
" - Set the BOOT_BUS_WIDTH field of the specified device\n"
|
" - Set the BOOT_BUS_WIDTH field of the specified device\n"
|
||||||
"mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
|
"mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
|
||||||
" - Change sizes of boot and RPMB partitions of specified device\n"
|
" - Change sizes of boot and RPMB partitions of specified device\n"
|
||||||
"mmc partconf dev [boot_ack boot_partition partition_access]\n"
|
"mmc partconf <dev> [boot_ack boot_partition partition_access]\n"
|
||||||
" - Show or change the bits of the PARTITION_CONFIG field of the specified device\n"
|
" - Show or change the bits of the PARTITION_CONFIG field of the specified device\n"
|
||||||
"mmc rst-function dev value\n"
|
"mmc rst-function <dev> <value>\n"
|
||||||
" - Change the RST_n_FUNCTION field of the specified device\n"
|
" - Change the RST_n_FUNCTION field of the specified device\n"
|
||||||
" WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
|
" WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -63,6 +63,7 @@ CONFIG_CROS_EC_KEYB=y
|
||||||
CONFIG_CROS_EC=y
|
CONFIG_CROS_EC=y
|
||||||
CONFIG_CROS_EC_SPI=y
|
CONFIG_CROS_EC_SPI=y
|
||||||
CONFIG_PWRSEQ=y
|
CONFIG_PWRSEQ=y
|
||||||
|
CONFIG_MMC_PWRSEQ=y
|
||||||
# CONFIG_SPL_DM_MMC is not set
|
# CONFIG_SPL_DM_MMC is not set
|
||||||
CONFIG_MMC_DW=y
|
CONFIG_MMC_DW=y
|
||||||
CONFIG_MMC_DW_ROCKCHIP=y
|
CONFIG_MMC_DW_ROCKCHIP=y
|
||||||
|
|
|
@ -55,6 +55,7 @@ CONFIG_CROS_EC_KEYB=y
|
||||||
CONFIG_CROS_EC=y
|
CONFIG_CROS_EC=y
|
||||||
CONFIG_CROS_EC_SPI=y
|
CONFIG_CROS_EC_SPI=y
|
||||||
CONFIG_PWRSEQ=y
|
CONFIG_PWRSEQ=y
|
||||||
|
CONFIG_MMC_PWRSEQ=y
|
||||||
CONFIG_MMC_DW=y
|
CONFIG_MMC_DW=y
|
||||||
CONFIG_MMC_DW_ROCKCHIP=y
|
CONFIG_MMC_DW_ROCKCHIP=y
|
||||||
CONFIG_MMC_SDHCI=y
|
CONFIG_MMC_SDHCI=y
|
||||||
|
|
|
@ -65,6 +65,7 @@ CONFIG_CROS_EC_KEYB=y
|
||||||
CONFIG_CROS_EC=y
|
CONFIG_CROS_EC=y
|
||||||
CONFIG_CROS_EC_SPI=y
|
CONFIG_CROS_EC_SPI=y
|
||||||
CONFIG_PWRSEQ=y
|
CONFIG_PWRSEQ=y
|
||||||
|
CONFIG_MMC_PWRSEQ=y
|
||||||
# CONFIG_SPL_DM_MMC is not set
|
# CONFIG_SPL_DM_MMC is not set
|
||||||
CONFIG_MMC_DW=y
|
CONFIG_MMC_DW=y
|
||||||
CONFIG_MMC_DW_ROCKCHIP=y
|
CONFIG_MMC_DW_ROCKCHIP=y
|
||||||
|
|
|
@ -65,6 +65,7 @@ CONFIG_CROS_EC_KEYB=y
|
||||||
CONFIG_CROS_EC=y
|
CONFIG_CROS_EC=y
|
||||||
CONFIG_CROS_EC_SPI=y
|
CONFIG_CROS_EC_SPI=y
|
||||||
CONFIG_PWRSEQ=y
|
CONFIG_PWRSEQ=y
|
||||||
|
CONFIG_MMC_PWRSEQ=y
|
||||||
# CONFIG_SPL_DM_MMC is not set
|
# CONFIG_SPL_DM_MMC is not set
|
||||||
CONFIG_MMC_DW=y
|
CONFIG_MMC_DW=y
|
||||||
CONFIG_MMC_DW_ROCKCHIP=y
|
CONFIG_MMC_DW_ROCKCHIP=y
|
||||||
|
|
|
@ -64,6 +64,7 @@ CONFIG_CROS_EC_KEYB=y
|
||||||
CONFIG_CROS_EC=y
|
CONFIG_CROS_EC=y
|
||||||
CONFIG_CROS_EC_SPI=y
|
CONFIG_CROS_EC_SPI=y
|
||||||
CONFIG_PWRSEQ=y
|
CONFIG_PWRSEQ=y
|
||||||
|
CONFIG_MMC_PWRSEQ=y
|
||||||
# CONFIG_SPL_DM_MMC is not set
|
# CONFIG_SPL_DM_MMC is not set
|
||||||
CONFIG_MMC_DW=y
|
CONFIG_MMC_DW=y
|
||||||
CONFIG_MMC_DW_ROCKCHIP=y
|
CONFIG_MMC_DW_ROCKCHIP=y
|
||||||
|
|
|
@ -18,6 +18,13 @@ config MMC_WRITE
|
||||||
help
|
help
|
||||||
Enable write access to MMC and SD Cards
|
Enable write access to MMC and SD Cards
|
||||||
|
|
||||||
|
config MMC_PWRSEQ
|
||||||
|
bool "HW reset support for eMMC"
|
||||||
|
depends on PWRSEQ
|
||||||
|
help
|
||||||
|
Ths select Hardware reset support aka pwrseq-emmc for eMMC
|
||||||
|
devices.
|
||||||
|
|
||||||
config MMC_BROKEN_CD
|
config MMC_BROKEN_CD
|
||||||
bool "Poll for broken card detection case"
|
bool "Poll for broken card detection case"
|
||||||
help
|
help
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
obj-y += mmc.o
|
obj-y += mmc.o
|
||||||
obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o
|
obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o
|
||||||
obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o
|
obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o
|
||||||
|
obj-$(CONFIG_MMC_PWRSEQ) += mmc-pwrseq.o
|
||||||
obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o
|
obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o
|
||||||
|
|
||||||
ifndef CONFIG_$(SPL_)BLK
|
ifndef CONFIG_$(SPL_)BLK
|
||||||
|
|
|
@ -265,10 +265,6 @@ static int meson_mmc_probe(struct udevice *dev)
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#ifdef CONFIG_PWRSEQ
|
|
||||||
struct udevice *pwr_dev;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Enable the clocks feeding the MMC controller */
|
/* Enable the clocks feeding the MMC controller */
|
||||||
ret = clk_get_bulk(dev, &clocks);
|
ret = clk_get_bulk(dev, &clocks);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -292,12 +288,11 @@ static int meson_mmc_probe(struct udevice *dev)
|
||||||
|
|
||||||
mmc_set_clock(mmc, cfg->f_min, MMC_CLK_ENABLE);
|
mmc_set_clock(mmc, cfg->f_min, MMC_CLK_ENABLE);
|
||||||
|
|
||||||
#ifdef CONFIG_PWRSEQ
|
#ifdef CONFIG_MMC_PWRSEQ
|
||||||
/* Enable power if needed */
|
/* Enable power if needed */
|
||||||
ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
|
ret = mmc_pwrseq_get_power(dev, cfg);
|
||||||
&pwr_dev);
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ret = pwrseq_set_power(pwr_dev, true);
|
ret = pwrseq_set_power(cfg->pwr_dev, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -342,37 +337,3 @@ U_BOOT_DRIVER(meson_mmc) = {
|
||||||
.of_to_plat = meson_mmc_of_to_plat,
|
.of_to_plat = meson_mmc_of_to_plat,
|
||||||
.plat_auto = sizeof(struct meson_mmc_plat),
|
.plat_auto = sizeof(struct meson_mmc_plat),
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_PWRSEQ
|
|
||||||
static int meson_mmc_pwrseq_set_power(struct udevice *dev, bool enable)
|
|
||||||
{
|
|
||||||
struct gpio_desc reset;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = gpio_request_by_name(dev, "reset-gpios", 0, &reset, GPIOD_IS_OUT);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
dm_gpio_set_value(&reset, 1);
|
|
||||||
udelay(1);
|
|
||||||
dm_gpio_set_value(&reset, 0);
|
|
||||||
udelay(200);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct pwrseq_ops meson_mmc_pwrseq_ops = {
|
|
||||||
.set_power = meson_mmc_pwrseq_set_power,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct udevice_id meson_mmc_pwrseq_ids[] = {
|
|
||||||
{ .compatible = "mmc-pwrseq-emmc" },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
U_BOOT_DRIVER(meson_mmc_pwrseq_drv) = {
|
|
||||||
.name = "mmc_pwrseq_emmc",
|
|
||||||
.id = UCLASS_PWRSEQ,
|
|
||||||
.of_match = meson_mmc_pwrseq_ids,
|
|
||||||
.ops = &meson_mmc_pwrseq_ops,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
51
drivers/mmc/mmc-pwrseq.c
Normal file
51
drivers/mmc/mmc-pwrseq.c
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2021 SAMSUNG Electronics
|
||||||
|
* Jaehoon Chung <jh80.chung@samsung.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <mmc.h>
|
||||||
|
#include <pwrseq.h>
|
||||||
|
#include <asm/gpio.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
|
||||||
|
int mmc_pwrseq_get_power(struct udevice *dev, struct mmc_config *cfg)
|
||||||
|
{
|
||||||
|
/* Enable power if needed */
|
||||||
|
return uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
|
||||||
|
&cfg->pwr_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mmc_pwrseq_set_power(struct udevice *dev, bool enable)
|
||||||
|
{
|
||||||
|
struct gpio_desc reset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = gpio_request_by_name(dev, "reset-gpios", 0, &reset, GPIOD_IS_OUT);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
dm_gpio_set_value(&reset, 1);
|
||||||
|
udelay(1);
|
||||||
|
dm_gpio_set_value(&reset, 0);
|
||||||
|
udelay(200);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pwrseq_ops mmc_pwrseq_ops = {
|
||||||
|
.set_power = mmc_pwrseq_set_power,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct udevice_id mmc_pwrseq_ids[] = {
|
||||||
|
{ .compatible = "mmc-pwrseq-emmc" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(mmc_pwrseq_drv) = {
|
||||||
|
.name = "mmc_pwrseq_emmc",
|
||||||
|
.id = UCLASS_PWRSEQ,
|
||||||
|
.of_match = mmc_pwrseq_ids,
|
||||||
|
.ops = &mmc_pwrseq_ops,
|
||||||
|
};
|
|
@ -841,7 +841,8 @@ static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
|
||||||
value);
|
value);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
if (!ret && (status & MMC_STATUS_RDY_FOR_DATA))
|
if (!ret && (status & MMC_STATUS_RDY_FOR_DATA) &&
|
||||||
|
(status & MMC_STATUS_CURR_STATE) == MMC_STATE_TRANS)
|
||||||
return 0;
|
return 0;
|
||||||
udelay(100);
|
udelay(100);
|
||||||
} while (get_timer(start) < timeout_ms);
|
} while (get_timer(start) < timeout_ms);
|
||||||
|
@ -2062,7 +2063,7 @@ static int mmc_select_hs400es(struct mmc *mmc)
|
||||||
|
|
||||||
static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
|
static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
const struct mode_width_tuning *mwt;
|
const struct mode_width_tuning *mwt;
|
||||||
const struct ext_csd_bus_width *ecbw;
|
const struct ext_csd_bus_width *ecbw;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,8 @@
|
||||||
#define SPI_RESPONSE_CRC_ERR ((5 << 1)|1)
|
#define SPI_RESPONSE_CRC_ERR ((5 << 1)|1)
|
||||||
#define SPI_RESPONSE_WRITE_ERR ((6 << 1)|1)
|
#define SPI_RESPONSE_WRITE_ERR ((6 << 1)|1)
|
||||||
|
|
||||||
/* Read and write blocks start with these tokens and end with crc;
|
/*
|
||||||
|
* Read and write blocks start with these tokens and end with crc;
|
||||||
* on error, read tokens act like a subset of R2_SPI_* values.
|
* on error, read tokens act like a subset of R2_SPI_* values.
|
||||||
*/
|
*/
|
||||||
/* single block write multiblock read */
|
/* single block write multiblock read */
|
||||||
|
@ -70,6 +71,20 @@ struct mmc_spi_priv {
|
||||||
struct spi_slave *spi;
|
struct spi_slave *spi;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mmc_spi_sendcmd() - send a command to the SD card
|
||||||
|
*
|
||||||
|
* @dev: mmc_spi device
|
||||||
|
* @cmdidx: command index
|
||||||
|
* @cmdarg: command argument
|
||||||
|
* @resp_type: card response type
|
||||||
|
* @resp: buffer to store the card response
|
||||||
|
* @resp_size: size of the card response
|
||||||
|
* @resp_match: if true, compare each of received bytes with @resp_match_value
|
||||||
|
* @resp_match_value: a value to be compared with each of received bytes
|
||||||
|
* @r1b: if true, receive additional bytes for busy signal token
|
||||||
|
* @return 0 if OK, -ETIMEDOUT if no card response is received, -ve on error
|
||||||
|
*/
|
||||||
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,
|
||||||
|
@ -78,6 +93,9 @@ static int mmc_spi_sendcmd(struct udevice *dev,
|
||||||
int i, rpos = 0, ret = 0;
|
int i, rpos = 0, ret = 0;
|
||||||
u8 cmdo[7], r;
|
u8 cmdo[7], r;
|
||||||
|
|
||||||
|
if (!resp || !resp_size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
debug("%s: cmd%d cmdarg=0x%x resp_type=0x%x "
|
debug("%s: cmd%d cmdarg=0x%x resp_type=0x%x "
|
||||||
"resp_size=%d resp_match=%d resp_match_value=0x%x\n",
|
"resp_size=%d resp_match=%d resp_match_value=0x%x\n",
|
||||||
__func__, cmdidx, cmdarg, resp_type,
|
__func__, cmdidx, cmdarg, resp_type,
|
||||||
|
@ -98,12 +116,9 @@ static int mmc_spi_sendcmd(struct udevice *dev,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!resp || !resp_size)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
debug("%s: cmd%d", __func__, cmdidx);
|
debug("%s: cmd%d", __func__, cmdidx);
|
||||||
|
|
||||||
if (resp_match) {
|
if (resp_match)
|
||||||
r = ~resp_match_value;
|
r = ~resp_match_value;
|
||||||
i = CMD_TIMEOUT;
|
i = CMD_TIMEOUT;
|
||||||
while (i) {
|
while (i) {
|
||||||
|
@ -114,18 +129,20 @@ static int mmc_spi_sendcmd(struct udevice *dev,
|
||||||
rpos++;
|
rpos++;
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
|
if (resp_match) {
|
||||||
if (r == resp_match_value)
|
if (r == resp_match_value)
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
if (!(r & 0x80))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!i && (r != resp_match_value))
|
|
||||||
|
if (!i)
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < resp_size; i++) {
|
resp[0] = r;
|
||||||
if (i == 0 && resp_match) {
|
for (i = 1; i < resp_size; i++) {
|
||||||
resp[i] = resp_match_value;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
|
ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -157,6 +174,15 @@ static int mmc_spi_sendcmd(struct udevice *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mmc_spi_readdata() - read data block(s) from the SD card
|
||||||
|
*
|
||||||
|
* @dev: mmc_spi device
|
||||||
|
* @xbuf: buffer of the actual data (excluding token and crc) to read
|
||||||
|
* @bcnt: number of data blocks to transfer
|
||||||
|
* @bsize: size of the actual data (excluding token and crc) in bytes
|
||||||
|
* @return 0 if OK, -ECOMM if crc error, -ETIMEDOUT on other errors
|
||||||
|
*/
|
||||||
static int mmc_spi_readdata(struct udevice *dev,
|
static int mmc_spi_readdata(struct udevice *dev,
|
||||||
void *xbuf, u32 bcnt, u32 bsize)
|
void *xbuf, u32 bcnt, u32 bsize)
|
||||||
{
|
{
|
||||||
|
@ -181,8 +207,10 @@ static int mmc_spi_readdata(struct udevice *dev,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
#ifdef CONFIG_MMC_SPI_CRC_ON
|
#ifdef CONFIG_MMC_SPI_CRC_ON
|
||||||
if (be16_to_cpu(crc16_ccitt(0, buf, bsize)) != crc) {
|
u16 crc_ok = be16_to_cpu(crc16_ccitt(0, buf, bsize));
|
||||||
debug("%s: data crc error\n", __func__);
|
if (crc_ok != crc) {
|
||||||
|
debug("%s: data crc error, expected %04x got %04x\n",
|
||||||
|
__func__, crc_ok, crc);
|
||||||
r1 = R1_SPI_COM_CRC;
|
r1 = R1_SPI_COM_CRC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -203,6 +231,16 @@ static int mmc_spi_readdata(struct udevice *dev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mmc_spi_writedata() - write data block(s) to the SD card
|
||||||
|
*
|
||||||
|
* @dev: mmc_spi device
|
||||||
|
* @xbuf: buffer of the actual data (excluding token and crc) to write
|
||||||
|
* @bcnt: number of data blocks to transfer
|
||||||
|
* @bsize: size of actual data (excluding token and crc) in bytes
|
||||||
|
* @multi: indicate a transfer by multiple block write command (CMD25)
|
||||||
|
* @return 0 if OK, -ECOMM if crc error, -ETIMEDOUT on other errors
|
||||||
|
*/
|
||||||
static int mmc_spi_writedata(struct udevice *dev, const void *xbuf,
|
static int mmc_spi_writedata(struct udevice *dev, const void *xbuf,
|
||||||
u32 bcnt, u32 bsize, int multi)
|
u32 bcnt, u32 bsize, int multi)
|
||||||
{
|
{
|
||||||
|
|
|
@ -105,7 +105,6 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
|
||||||
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||||
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
|
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
|
||||||
struct dwmci_host *host = &priv->host;
|
struct dwmci_host *host = &priv->host;
|
||||||
struct udevice *pwr_dev __maybe_unused;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
@ -136,12 +135,11 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
|
||||||
|
|
||||||
host->fifo_mode = priv->fifo_mode;
|
host->fifo_mode = priv->fifo_mode;
|
||||||
|
|
||||||
#ifdef CONFIG_PWRSEQ
|
#ifdef CONFIG_MMC_PWRSEQ
|
||||||
/* Enable power if needed */
|
/* Enable power if needed */
|
||||||
ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
|
ret = mmc_pwrseq_get_power(dev, &plat->cfg);
|
||||||
&pwr_dev);
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ret = pwrseq_set_power(pwr_dev, true);
|
ret = pwrseq_set_power(plat->cfg.pwr_dev, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -182,37 +180,3 @@ U_BOOT_DRIVER(rockchip_rk3288_dw_mshc) = {
|
||||||
|
|
||||||
DM_DRIVER_ALIAS(rockchip_rk3288_dw_mshc, rockchip_rk3328_dw_mshc)
|
DM_DRIVER_ALIAS(rockchip_rk3288_dw_mshc, rockchip_rk3328_dw_mshc)
|
||||||
DM_DRIVER_ALIAS(rockchip_rk3288_dw_mshc, rockchip_rk3368_dw_mshc)
|
DM_DRIVER_ALIAS(rockchip_rk3288_dw_mshc, rockchip_rk3368_dw_mshc)
|
||||||
|
|
||||||
#ifdef CONFIG_PWRSEQ
|
|
||||||
static int rockchip_dwmmc_pwrseq_set_power(struct udevice *dev, bool enable)
|
|
||||||
{
|
|
||||||
struct gpio_desc reset;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = gpio_request_by_name(dev, "reset-gpios", 0, &reset, GPIOD_IS_OUT);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
dm_gpio_set_value(&reset, 1);
|
|
||||||
udelay(1);
|
|
||||||
dm_gpio_set_value(&reset, 0);
|
|
||||||
udelay(200);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct pwrseq_ops rockchip_dwmmc_pwrseq_ops = {
|
|
||||||
.set_power = rockchip_dwmmc_pwrseq_set_power,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct udevice_id rockchip_dwmmc_pwrseq_ids[] = {
|
|
||||||
{ .compatible = "mmc-pwrseq-emmc" },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
U_BOOT_DRIVER(rockchip_dwmmc_pwrseq_drv) = {
|
|
||||||
.name = "mmc_pwrseq_emmc",
|
|
||||||
.id = UCLASS_PWRSEQ,
|
|
||||||
.of_match = rockchip_dwmmc_pwrseq_ids,
|
|
||||||
.ops = &rockchip_dwmmc_pwrseq_ops,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -177,8 +177,10 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data)
|
||||||
}
|
}
|
||||||
} while (!(stat & SDHCI_INT_DATA_END));
|
} while (!(stat & SDHCI_INT_DATA_END));
|
||||||
|
|
||||||
|
#if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
|
||||||
dma_unmap_single(host->start_addr, data->blocks * data->blocksize,
|
dma_unmap_single(host->start_addr, data->blocks * data->blocksize,
|
||||||
mmc_get_dma_dir(data));
|
mmc_get_dma_dir(data));
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,6 +178,7 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
|
||||||
#define MMC_STATUS_ERROR (1 << 19)
|
#define MMC_STATUS_ERROR (1 << 19)
|
||||||
|
|
||||||
#define MMC_STATE_PRG (7 << 9)
|
#define MMC_STATE_PRG (7 << 9)
|
||||||
|
#define MMC_STATE_TRANS (4 << 9)
|
||||||
|
|
||||||
#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
|
#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
|
||||||
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
|
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
|
||||||
|
@ -591,6 +592,9 @@ struct mmc_config {
|
||||||
uint f_max;
|
uint f_max;
|
||||||
uint b_max;
|
uint b_max;
|
||||||
unsigned char part_type;
|
unsigned char part_type;
|
||||||
|
#ifdef CONFIG_MMC_PWRSEQ
|
||||||
|
struct udevice *pwr_dev;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sd_ssr {
|
struct sd_ssr {
|
||||||
|
@ -807,6 +811,17 @@ int mmc_deinit(struct mmc *mmc);
|
||||||
*/
|
*/
|
||||||
int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg);
|
int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg);
|
||||||
|
|
||||||
|
#ifdef CONFIG_MMC_PWRSEQ
|
||||||
|
/**
|
||||||
|
* mmc_pwrseq_get_power() - get a power device from device tree
|
||||||
|
*
|
||||||
|
* @dev: MMC device
|
||||||
|
* @cfg: MMC configuration
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int mmc_pwrseq_get_power(struct udevice *dev, struct mmc_config *cfg);
|
||||||
|
#endif
|
||||||
|
|
||||||
int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
|
int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue