mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
mmc: add thunder boot support
Remove unnecessary initialization process from core as possible, such as remove some idle process, shorten delay, remove parsing ext_csd, remove post-delay for power and so on. All these stuffs are enabled by CONFIG_ROCKCHIP_THUNDER_BOOT. Change-Id: I0e2326dd79d938eb82c8cfac9db09e34d6c08987 Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
This commit is contained in:
@@ -2055,6 +2055,21 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_set_blocklen);
|
EXPORT_SYMBOL(mmc_set_blocklen);
|
||||||
|
|
||||||
|
int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
|
||||||
|
bool is_rel_write)
|
||||||
|
{
|
||||||
|
struct mmc_command cmd = {};
|
||||||
|
|
||||||
|
cmd.opcode = MMC_SET_BLOCK_COUNT;
|
||||||
|
cmd.arg = blockcount & 0x0000FFFF;
|
||||||
|
if (is_rel_write)
|
||||||
|
cmd.arg |= 1 << 31;
|
||||||
|
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
|
||||||
|
return mmc_wait_for_cmd(card->host, &cmd, 5);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mmc_set_blockcount);
|
||||||
|
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
static void mmc_hw_reset_for_init(struct mmc_host *host)
|
static void mmc_hw_reset_for_init(struct mmc_host *host)
|
||||||
{
|
{
|
||||||
mmc_pwrseq_reset(host);
|
mmc_pwrseq_reset(host);
|
||||||
@@ -2063,6 +2078,7 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
|
|||||||
return;
|
return;
|
||||||
host->ops->hw_reset(host);
|
host->ops->hw_reset(host);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mmc_hw_reset - reset the card in hardware
|
* mmc_hw_reset - reset the card in hardware
|
||||||
@@ -2135,7 +2151,9 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
|
|||||||
* Some eMMCs (with VCCQ always on) may not be reset after power up, so
|
* Some eMMCs (with VCCQ always on) may not be reset after power up, so
|
||||||
* do a hardware reset if possible.
|
* do a hardware reset if possible.
|
||||||
*/
|
*/
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
mmc_hw_reset_for_init(host);
|
mmc_hw_reset_for_init(host);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sdio_reset sends CMD52 to reset card. Since we do not know
|
* sdio_reset sends CMD52 to reset card. Since we do not know
|
||||||
|
|||||||
@@ -9,13 +9,15 @@
|
|||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
#include <linux/mmc/host.h>
|
#include <linux/mmc/host.h>
|
||||||
#include <linux/mmc/card.h>
|
#include <linux/mmc/card.h>
|
||||||
#include <linux/mmc/mmc.h>
|
#include <linux/mmc/mmc.h>
|
||||||
|
#include <linux/resource.h>
|
||||||
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
@@ -65,6 +67,7 @@ static const unsigned int taac_mant[] = {
|
|||||||
/*
|
/*
|
||||||
* Given the decoded CSD structure, decode the raw CID to our CID structure.
|
* Given the decoded CSD structure, decode the raw CID to our CID structure.
|
||||||
*/
|
*/
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
static int mmc_decode_cid(struct mmc_card *card)
|
static int mmc_decode_cid(struct mmc_card *card)
|
||||||
{
|
{
|
||||||
u32 *resp = card->raw_cid;
|
u32 *resp = card->raw_cid;
|
||||||
@@ -116,6 +119,7 @@ static int mmc_decode_cid(struct mmc_card *card)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void mmc_set_erase_size(struct mmc_card *card)
|
static void mmc_set_erase_size(struct mmc_card *card)
|
||||||
{
|
{
|
||||||
@@ -655,14 +659,72 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
|
static void *mmc_tb_map_ecsd(phys_addr_t start, size_t len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
void *vaddr;
|
||||||
|
pgprot_t pgprot = PAGE_KERNEL;
|
||||||
|
phys_addr_t phys;
|
||||||
|
int npages = PAGE_ALIGN(len) / PAGE_SIZE;
|
||||||
|
struct page **p = vmalloc(sizeof(struct page *) * npages);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
phys = start;
|
||||||
|
for (i = 0; i < npages; i++) {
|
||||||
|
p[i] = phys_to_page(phys);
|
||||||
|
phys += PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vaddr = vmap(p, npages, VM_MAP, pgprot);
|
||||||
|
vfree(p);
|
||||||
|
|
||||||
|
return vaddr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int mmc_read_ext_csd(struct mmc_card *card)
|
static int mmc_read_ext_csd(struct mmc_card *card)
|
||||||
{
|
{
|
||||||
u8 *ext_csd;
|
u8 *ext_csd;
|
||||||
int err;
|
int err;
|
||||||
|
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
|
void *ecsd;
|
||||||
|
bool valid_ecsd = false;
|
||||||
|
struct device_node *mem;
|
||||||
|
struct resource reg;
|
||||||
|
struct device *dev = card->host->parent;
|
||||||
|
#endif
|
||||||
if (!mmc_can_ext_csd(card))
|
if (!mmc_can_ext_csd(card))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
|
mem = of_parse_phandle(dev->of_node, "memory-region-ecsd", 0);
|
||||||
|
if (mem) {
|
||||||
|
err = of_address_to_resource(mem, 0, ®);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dev, "fail to get resource\n");
|
||||||
|
goto get_ecsd;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecsd = mmc_tb_map_ecsd(reg.start, resource_size(®));
|
||||||
|
if (!ecsd)
|
||||||
|
goto get_ecsd;
|
||||||
|
|
||||||
|
if (readl(ecsd + SZ_512) == 0x55aa55aa) {
|
||||||
|
ext_csd = ecsd;
|
||||||
|
valid_ecsd = true;
|
||||||
|
goto decode;
|
||||||
|
} else {
|
||||||
|
dev_dbg(dev, "invalid ecsd tag!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dev_info(dev, "not find \"memory-region\" property\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
get_ecsd:
|
||||||
|
#endif
|
||||||
err = mmc_get_ext_csd(card, &ext_csd);
|
err = mmc_get_ext_csd(card, &ext_csd);
|
||||||
if (err) {
|
if (err) {
|
||||||
/* If the host or the card can't do the switch,
|
/* If the host or the card can't do the switch,
|
||||||
@@ -687,12 +749,22 @@ static int mmc_read_ext_csd(struct mmc_card *card)
|
|||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
|
decode:
|
||||||
|
#endif
|
||||||
err = mmc_decode_ext_csd(card, ext_csd);
|
err = mmc_decode_ext_csd(card, ext_csd);
|
||||||
|
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
|
if (!valid_ecsd)
|
||||||
|
kfree(ext_csd);
|
||||||
|
else
|
||||||
|
vunmap(ecsd);
|
||||||
|
#else
|
||||||
kfree(ext_csd);
|
kfree(ext_csd);
|
||||||
|
#endif
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
|
static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
|
||||||
{
|
{
|
||||||
u8 *bw_ext_csd;
|
u8 *bw_ext_csd;
|
||||||
@@ -765,6 +837,7 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
|
|||||||
kfree(bw_ext_csd);
|
kfree(bw_ext_csd);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
|
MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
|
||||||
card->raw_cid[2], card->raw_cid[3]);
|
card->raw_cid[2], card->raw_cid[3]);
|
||||||
@@ -1034,11 +1107,12 @@ static int mmc_select_bus_width(struct mmc_card *card)
|
|||||||
* compare ext_csd previously read in 1 bit mode
|
* compare ext_csd previously read in 1 bit mode
|
||||||
* against ext_csd at new bus width
|
* against ext_csd at new bus width
|
||||||
*/
|
*/
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
|
if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
|
||||||
err = mmc_compare_ext_csds(card, bus_width);
|
err = mmc_compare_ext_csds(card, bus_width);
|
||||||
else
|
else
|
||||||
err = mmc_bus_test(card, bus_width);
|
err = mmc_bus_test(card, bus_width);
|
||||||
|
#endif
|
||||||
if (!err) {
|
if (!err) {
|
||||||
err = bus_width;
|
err = bus_width;
|
||||||
break;
|
break;
|
||||||
@@ -1572,7 +1646,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||||||
* respond.
|
* respond.
|
||||||
* mmc_go_idle is needed for eMMC that are asleep
|
* mmc_go_idle is needed for eMMC that are asleep
|
||||||
*/
|
*/
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
mmc_go_idle(host);
|
mmc_go_idle(host);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The extra bit indicates that we support high capacity */
|
/* The extra bit indicates that we support high capacity */
|
||||||
err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
|
err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
|
||||||
@@ -1617,7 +1693,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||||||
card->ocr = ocr;
|
card->ocr = ocr;
|
||||||
card->type = MMC_TYPE_MMC;
|
card->type = MMC_TYPE_MMC;
|
||||||
card->rca = 1;
|
card->rca = 1;
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
|
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1648,9 +1726,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||||||
err = mmc_decode_csd(card);
|
err = mmc_decode_csd(card);
|
||||||
if (err)
|
if (err)
|
||||||
goto free_card;
|
goto free_card;
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
err = mmc_decode_cid(card);
|
err = mmc_decode_cid(card);
|
||||||
if (err)
|
if (err)
|
||||||
goto free_card;
|
goto free_card;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1793,6 +1873,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||||||
/*
|
/*
|
||||||
* Enable HPI feature (if supported)
|
* Enable HPI feature (if supported)
|
||||||
*/
|
*/
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
if (card->ext_csd.hpi) {
|
if (card->ext_csd.hpi) {
|
||||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||||
EXT_CSD_HPI_MGMT, 1,
|
EXT_CSD_HPI_MGMT, 1,
|
||||||
@@ -1808,7 +1889,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||||||
card->ext_csd.hpi_en = 1;
|
card->ext_csd.hpi_en = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* If cache size is higher than 0, this indicates the existence of cache
|
* If cache size is higher than 0, this indicates the existence of cache
|
||||||
* and it can be turned on. Note that some eMMCs from Micron has been
|
* and it can be turned on. Note that some eMMCs from Micron has been
|
||||||
|
|||||||
@@ -145,24 +145,26 @@ int mmc_go_idle(struct mmc_host *host)
|
|||||||
* rules that must accommodate non-MMC slaves which this layer
|
* rules that must accommodate non-MMC slaves which this layer
|
||||||
* won't even know about.
|
* won't even know about.
|
||||||
*/
|
*/
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
if (!mmc_host_is_spi(host)) {
|
if (!mmc_host_is_spi(host)) {
|
||||||
mmc_set_chip_select(host, MMC_CS_HIGH);
|
mmc_set_chip_select(host, MMC_CS_HIGH);
|
||||||
mmc_delay(1);
|
mmc_delay(1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
cmd.opcode = MMC_GO_IDLE_STATE;
|
cmd.opcode = MMC_GO_IDLE_STATE;
|
||||||
cmd.arg = 0;
|
cmd.arg = 0;
|
||||||
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;
|
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;
|
||||||
|
|
||||||
err = mmc_wait_for_cmd(host, &cmd, 0);
|
err = mmc_wait_for_cmd(host, &cmd, 0);
|
||||||
|
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
mmc_delay(1);
|
mmc_delay(1);
|
||||||
|
|
||||||
if (!mmc_host_is_spi(host)) {
|
if (!mmc_host_is_spi(host)) {
|
||||||
mmc_set_chip_select(host, MMC_CS_DONTCARE);
|
mmc_set_chip_select(host, MMC_CS_DONTCARE);
|
||||||
mmc_delay(1);
|
mmc_delay(1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
host->use_spi_crc = 0;
|
host->use_spi_crc = 0;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@@ -193,8 +195,6 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
|
|||||||
|
|
||||||
err = -ETIMEDOUT;
|
err = -ETIMEDOUT;
|
||||||
|
|
||||||
mmc_delay(10);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* According to eMMC specification v5.1 section 6.4.3, we
|
* According to eMMC specification v5.1 section 6.4.3, we
|
||||||
* should issue CMD1 repeatedly in the idle state until
|
* should issue CMD1 repeatedly in the idle state until
|
||||||
@@ -204,6 +204,11 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
|
|||||||
*/
|
*/
|
||||||
if (!ocr && !mmc_host_is_spi(host))
|
if (!ocr && !mmc_host_is_spi(host))
|
||||||
cmd.arg = cmd.resp[0] | BIT(30);
|
cmd.arg = cmd.resp[0] | BIT(30);
|
||||||
|
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
|
mmc_delay(1);
|
||||||
|
#else
|
||||||
|
udelay(1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rocr && !mmc_host_is_spi(host))
|
if (rocr && !mmc_host_is_spi(host))
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/mmc/slot-gpio.h>
|
#include <linux/mmc/slot-gpio.h>
|
||||||
|
#include <linux/soc/rockchip/rockchip_decompress.h>
|
||||||
|
|
||||||
#include "dw_mmc.h"
|
#include "dw_mmc.h"
|
||||||
|
|
||||||
@@ -208,6 +210,7 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
|
|||||||
static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags)
|
static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags)
|
||||||
{
|
{
|
||||||
u32 status;
|
u32 status;
|
||||||
|
u32 delay = 10;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Databook says that before issuing a new data transfer command
|
* Databook says that before issuing a new data transfer command
|
||||||
@@ -217,12 +220,16 @@ static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags)
|
|||||||
* ...also allow sending for SDMMC_CMD_VOLT_SWITCH where busy is
|
* ...also allow sending for SDMMC_CMD_VOLT_SWITCH where busy is
|
||||||
* expected.
|
* expected.
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||||
|
if (host->slot->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC)
|
||||||
|
delay = 0;
|
||||||
|
#endif
|
||||||
if ((cmd_flags & SDMMC_CMD_PRV_DAT_WAIT) &&
|
if ((cmd_flags & SDMMC_CMD_PRV_DAT_WAIT) &&
|
||||||
!(cmd_flags & SDMMC_CMD_VOLT_SWITCH)) {
|
!(cmd_flags & SDMMC_CMD_VOLT_SWITCH)) {
|
||||||
if (readl_poll_timeout_atomic(host->regs + SDMMC_STATUS,
|
if (readl_poll_timeout_atomic(host->regs + SDMMC_STATUS,
|
||||||
status,
|
status,
|
||||||
!(status & SDMMC_STATUS_BUSY),
|
!(status & SDMMC_STATUS_BUSY),
|
||||||
10, 500 * USEC_PER_MSEC))
|
delay, 500 * USEC_PER_MSEC))
|
||||||
dev_err(host->dev, "Busy; trying anyway\n");
|
dev_err(host->dev, "Busy; trying anyway\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3226,6 +3233,59 @@ int dw_mci_probe(struct dw_mci *host)
|
|||||||
int width, i, ret = 0;
|
int width, i, ret = 0;
|
||||||
u32 fifo_size;
|
u32 fifo_size;
|
||||||
|
|
||||||
|
#if defined(CONFIG_ROCKCHIP_THUNDER_BOOT) && defined(CONFIG_ROCKCHIP_HW_DECOMPRESS)
|
||||||
|
struct resource idmac, ramdisk_src, ramdisk_dst;
|
||||||
|
struct device_node *dma, *rds, *rdd;
|
||||||
|
struct device *dev = host->dev;
|
||||||
|
u32 intr;
|
||||||
|
|
||||||
|
if (device_property_read_bool(host->dev, "supports-emmc")) {
|
||||||
|
if (readl_poll_timeout(host->regs + SDMMC_STATUS,
|
||||||
|
fifo_size,
|
||||||
|
!(fifo_size & (BIT(10) | GENMASK(7, 4))),
|
||||||
|
0, 500 * USEC_PER_MSEC))
|
||||||
|
dev_err(dev, "Controller is occupied!\n");
|
||||||
|
|
||||||
|
if (readl_poll_timeout(host->regs + SDMMC_IDSTS,
|
||||||
|
fifo_size, !(fifo_size & GENMASK(16, 13)),
|
||||||
|
0, 500 * USEC_PER_MSEC))
|
||||||
|
dev_err(dev, "DMA is still running!\n");
|
||||||
|
|
||||||
|
intr = mci_readl(host, RINTSTS);
|
||||||
|
if (intr & DW_MCI_CMD_ERROR_FLAGS || intr & DW_MCI_DATA_ERROR_FLAGS) {
|
||||||
|
WARN_ON(1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release idmac descriptor */
|
||||||
|
dma = of_parse_phandle(dev->of_node, "memory-region-idamc", 0);
|
||||||
|
if (dma) {
|
||||||
|
ret = of_address_to_resource(dma, 0, &idmac);
|
||||||
|
if (ret >= 0)
|
||||||
|
free_reserved_area(phys_to_virt(idmac.start),
|
||||||
|
phys_to_virt(idmac.start) + resource_size(&idmac),
|
||||||
|
-1, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse ramdisk addr and help start decompressing */
|
||||||
|
rds = of_parse_phandle(dev->of_node, "memory-region-src", 0);
|
||||||
|
rdd = of_parse_phandle(dev->of_node, "memory-region-dst", 0);
|
||||||
|
if (rds && rdd) {
|
||||||
|
if (of_address_to_resource(rds, 0, &ramdisk_src) >= 0 &&
|
||||||
|
of_address_to_resource(rdd, 0, &ramdisk_dst) >= 0)
|
||||||
|
/*
|
||||||
|
* Decompress HW driver will free reserved area of
|
||||||
|
* memory-region-src.
|
||||||
|
*/
|
||||||
|
ret = rk_decom_start(GZIP_MOD, ramdisk_src.start,
|
||||||
|
ramdisk_dst.start,
|
||||||
|
resource_size(&ramdisk_dst));
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(dev, "fail to start decom\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!host->pdata) {
|
if (!host->pdata) {
|
||||||
host->pdata = dw_mci_parse_dt(host);
|
host->pdata = dw_mci_parse_dt(host);
|
||||||
if (IS_ERR(host->pdata))
|
if (IS_ERR(host->pdata))
|
||||||
|
|||||||
Reference in New Issue
Block a user