mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
emmc: add emmc HS400 function
PD#142470: emmc: support hs400 busmode 1. refix source clock 400MHZ 2. add hs400 timming function Change-Id: I9cc767262379ba2be5ab5d3e68aae87c1f18c242 Signed-off-by: Long Yu <long.yu@amlogic.com>
This commit is contained in:
@@ -462,8 +462,9 @@
|
||||
pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>;
|
||||
clocks = <&clkc CLKID_SD_EMMC_C>,
|
||||
<&clkc CLKID_SD_EMMC_C_P0_COMP>,
|
||||
<&clkc CLKID_FCLK_DIV2>;
|
||||
clock-names = "core", "clkin0", "clkin1";
|
||||
<&clkc CLKID_FCLK_DIV2>,
|
||||
<&clkc CLKID_FCLK_DIV5>;
|
||||
clock-names = "core", "clkin0", "clkin1", "clkin2";
|
||||
|
||||
bus-width = <8>;
|
||||
cap-sd-highspeed;
|
||||
@@ -486,9 +487,9 @@
|
||||
"MMC_CAP_HW_RESET",
|
||||
"MMC_CAP_ERASE",
|
||||
"MMC_CAP_CMD23";
|
||||
/*caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400";*/
|
||||
caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400";
|
||||
f_min = <300000>;
|
||||
f_max = <100000000>;
|
||||
f_max = <200000000>;
|
||||
max_req_size = <0x20000>; /**128KB*/
|
||||
gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>;
|
||||
hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>;
|
||||
@@ -510,8 +511,9 @@
|
||||
pinctrl-1 = <&sdio_all_pins>;
|
||||
clocks = <&clkc CLKID_SD_EMMC_B>,
|
||||
<&clkc CLKID_SD_EMMC_B_P0_COMP>,
|
||||
<&clkc CLKID_FCLK_DIV2>;
|
||||
clock-names = "core", "clkin0", "clkin1";
|
||||
<&clkc CLKID_FCLK_DIV2>,
|
||||
<&clkc CLKID_FCLK_DIV5>;
|
||||
clock-names = "core", "clkin0", "clkin1", "clkin2";
|
||||
|
||||
bus-width = <4>;
|
||||
cap-sd-highspeed;
|
||||
|
||||
@@ -388,8 +388,9 @@
|
||||
pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>;
|
||||
clocks = <&clkc CLKID_SD_EMMC_C>,
|
||||
<&clkc CLKID_SD_EMMC_C_P0_COMP>,
|
||||
<&clkc CLKID_FCLK_DIV2>;
|
||||
clock-names = "core", "clkin0", "clkin1";
|
||||
<&clkc CLKID_FCLK_DIV2>,
|
||||
<&clkc CLKID_FCLK_DIV5>;
|
||||
clock-names = "core", "clkin0", "clkin1", "clkin2";
|
||||
|
||||
bus-width = <8>;
|
||||
cap-sd-highspeed;
|
||||
|
||||
@@ -1240,6 +1240,8 @@ int aml_emmc_clktree_init(struct amlsd_host *host)
|
||||
ret = PTR_ERR(host->core_clk);
|
||||
return ret;
|
||||
}
|
||||
pr_info("core->rate: %lu\n", clk_get_rate(host->core_clk));
|
||||
pr_info("core->name: %s\n", __clk_get_name(host->core_clk));
|
||||
ret = clk_prepare_enable(host->core_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1257,6 +1259,8 @@ int aml_emmc_clktree_init(struct amlsd_host *host)
|
||||
}
|
||||
host->mux_parent_rate[i] = clk_get_rate(host->mux_parent[i]);
|
||||
mux_parent_names[i] = __clk_get_name(host->mux_parent[i]);
|
||||
pr_info("rate: %lu, name: %s\n",
|
||||
host->mux_parent_rate[i], mux_parent_names[i]);
|
||||
mux_parent_count++;
|
||||
if (host->mux_parent_rate[i] < f_min)
|
||||
f_min = host->mux_parent_rate[i];
|
||||
@@ -1272,6 +1276,7 @@ int aml_emmc_clktree_init(struct amlsd_host *host)
|
||||
|
||||
/* create the mux */
|
||||
snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev));
|
||||
pr_info("clk_name: %s\n", clk_name);
|
||||
init.name = clk_name;
|
||||
init.ops = &clk_mux_ops;
|
||||
init.flags = 0;
|
||||
@@ -1306,7 +1311,8 @@ int aml_emmc_clktree_init(struct amlsd_host *host)
|
||||
return PTR_ERR(host->cfg_div_clk);
|
||||
|
||||
ret = clk_prepare_enable(host->cfg_div_clk);
|
||||
|
||||
pr_info("[%s] clock: 0x%x\n",
|
||||
__func__, readl(host->base + SD_EMMC_CLOCK_V3));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1324,6 +1330,7 @@ static int meson_mmc_clk_init(struct amlsd_host *host)
|
||||
struct sd_emmc_config *pconf = (struct sd_emmc_config *)&vconf;
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
|
||||
writel(0, host->base + SD_EMMC_CLOCK);
|
||||
ret = aml_emmc_clktree_init(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1662,7 +1669,7 @@ err_exit:
|
||||
*a linear buffer and an SG list for amlogic,
|
||||
* We don't disable irq in this function
|
||||
**/
|
||||
static int aml_sd_emmc_post_dma(struct amlsd_host *host,
|
||||
int aml_sd_emmc_post_dma(struct amlsd_host *host,
|
||||
struct mmc_request *mrq)
|
||||
{
|
||||
struct mmc_data *data = NULL;
|
||||
@@ -1718,7 +1725,7 @@ static void aml_sd_emmc_check_sdio_irq(struct amlsd_host *host)
|
||||
}
|
||||
}
|
||||
}
|
||||
static int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||
int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
@@ -2023,7 +2030,7 @@ static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||
spin_unlock_irqrestore(&host->mrq_lock, flags);
|
||||
}
|
||||
|
||||
static int meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
|
||||
int meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
struct sd_emmc_desc_info *desc_info =
|
||||
@@ -2694,6 +2701,7 @@ static const struct mmc_host_ops meson_mmc_ops_v3 = {
|
||||
.card_busy = aml_sd_emmc_card_busy,
|
||||
.execute_tuning = aml_mmc_execute_tuning_v3,
|
||||
.hw_reset = aml_emmc_hw_reset,
|
||||
.post_hs400_timming = aml_post_hs400_timming,
|
||||
};
|
||||
|
||||
static void aml_reg_print(struct amlsd_host *host)
|
||||
@@ -2746,8 +2754,12 @@ static int meson_mmc_probe(struct platform_device *pdev)
|
||||
ret = -EINVAL;
|
||||
goto free_host;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, host->irq,
|
||||
if (host->ctrl_ver >= 3)
|
||||
ret = devm_request_threaded_irq(&pdev->dev, host->irq,
|
||||
meson_mmc_irq, meson_mmc_irq_thread_v3,
|
||||
IRQF_SHARED, "meson-aml-mmc", host);
|
||||
else
|
||||
ret = devm_request_threaded_irq(&pdev->dev, host->irq,
|
||||
meson_mmc_irq, meson_mmc_irq_thread,
|
||||
IRQF_SHARED, "meson-aml-mmc", host);
|
||||
if (ret)
|
||||
|
||||
@@ -51,6 +51,7 @@ int meson_mmc_clk_init_v3(struct amlsd_host *host)
|
||||
struct sd_emmc_config *pconf = (struct sd_emmc_config *)&vconf;
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
|
||||
writel(0, host->base + SD_EMMC_CLOCK);
|
||||
ret = aml_emmc_clktree_init(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -89,7 +90,10 @@ static int meson_mmc_clk_set_rate_v3(struct amlsd_host *host,
|
||||
unsigned long clk_ios)
|
||||
{
|
||||
struct mmc_host *mmc = host->mmc;
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
int ret = 0;
|
||||
struct clk *fdiv5_clk = NULL;
|
||||
void __iomem *source_base = NULL;
|
||||
#ifdef SD_EMMC_CLK_CTRL
|
||||
u32 clk_rate, clk_div, clk_src_sel;
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
@@ -141,7 +145,8 @@ static int meson_mmc_clk_set_rate_v3(struct amlsd_host *host,
|
||||
#else
|
||||
if (clk_ios == mmc->actual_clock)
|
||||
return 0;
|
||||
|
||||
pr_info("[%s] before clock: 0x%x\n",
|
||||
__func__, readl(host->base + SD_EMMC_CLOCK_V3));
|
||||
/* stop clock */
|
||||
vcfg = readl(host->base + SD_EMMC_CFG);
|
||||
if (!conf->stop_clk) {
|
||||
@@ -149,6 +154,16 @@ static int meson_mmc_clk_set_rate_v3(struct amlsd_host *host,
|
||||
writel(vcfg, host->base + SD_EMMC_CFG);
|
||||
}
|
||||
|
||||
if ((clk_ios >= 200000000) && aml_card_type_mmc(pdata)) {
|
||||
ret = clk_set_parent(host->cfg_div_clk, host->mux_clk);
|
||||
if (ret)
|
||||
pr_warn("set mux_clk as parent error\n");
|
||||
fdiv5_clk = devm_clk_get(host->dev, "clkin2");
|
||||
ret = clk_set_parent(host->mux_parent[0], fdiv5_clk);
|
||||
if (ret)
|
||||
pr_warn("set fdiv5_clk as parent error\n");
|
||||
}
|
||||
|
||||
dev_dbg(host->dev, "change clock rate %u -> %lu\n",
|
||||
mmc->actual_clock, clk_ios);
|
||||
ret = clk_set_rate(host->cfg_div_clk, clk_ios);
|
||||
@@ -165,7 +180,16 @@ static int meson_mmc_clk_set_rate_v3(struct amlsd_host *host,
|
||||
writel(vcfg, host->base + SD_EMMC_CFG);
|
||||
}
|
||||
#endif
|
||||
|
||||
source_base =
|
||||
ioremap_nocache(P_HHI_NAND_CLK_CNTL,
|
||||
sizeof(u32));
|
||||
/* pr_info("actual_clock :%u, HHI_nand: 0x%x\n",
|
||||
* mmc->actual_clock, readl(source_base));
|
||||
*/
|
||||
/* pr_info("[%s] after clock: 0x%x\n",
|
||||
* __func__, readl(host->base + SD_EMMC_CLOCK_V3));
|
||||
*/
|
||||
iounmap(source_base);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -192,6 +216,7 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_host *host,
|
||||
adjust = readl(host->base + SD_EMMC_ADJUST_V3);
|
||||
gadjust->ds_enable = 1;
|
||||
writel(adjust, host->base + SD_EMMC_ADJUST_V3);
|
||||
clk_rate = 400000000;
|
||||
/*host->tuning_mode = AUTO_TUNING_MODE;*/
|
||||
}
|
||||
}
|
||||
@@ -273,8 +298,7 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
struct aml_tuning_data tuning_data;
|
||||
int err;
|
||||
u32 adj_win_start = 100;
|
||||
int err = 0;
|
||||
u32 intf3;
|
||||
|
||||
if (opcode == MMC_SEND_TUNING_BLOCK_HS200) {
|
||||
@@ -298,8 +322,6 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode)
|
||||
intf3 = readl(host->base + SD_EMMC_INTF3);
|
||||
intf3 |= (1 << 22);
|
||||
writel(intf3, host->base + SD_EMMC_INTF3);
|
||||
err = aml_sd_emmc_execute_tuning_(mmc, opcode,
|
||||
&tuning_data, adj_win_start);
|
||||
|
||||
pr_info("%s: gclock=0x%x, gdelay1=0x%x, gdelay2=0x%x,intf3=0x%x\n",
|
||||
mmc_hostname(mmc), readl(host->base + SD_EMMC_CLOCK_V3),
|
||||
@@ -309,39 +331,553 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*static int aml_sd_emmc_cali_v3(struct mmc_host *mmc,
|
||||
* u8 opcode, u8 *blk_test, u32 blksz, u32 blocks)
|
||||
*{
|
||||
* struct amlsd_host *host = mmc_priv(mmc);
|
||||
* struct mmc_request mrq = {NULL};
|
||||
* struct mmc_command cmd = {0};
|
||||
* struct mmc_command stop = {0};
|
||||
* struct mmc_data data = {0};
|
||||
* struct scatterlist sg;
|
||||
*
|
||||
* cmd.opcode = opcode;
|
||||
* cmd.arg = ((SZ_1M * (36 + 3)) / 512);
|
||||
* cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
|
||||
*
|
||||
* stop.opcode = MMC_STOP_TRANSMISSION;
|
||||
* stop.arg = 0;
|
||||
* stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||
*
|
||||
* data.blksz = blksz;
|
||||
* data.blocks = blocks;
|
||||
* data.flags = MMC_DATA_READ;
|
||||
* data.sg = &sg;
|
||||
* data.sg_len = 1;
|
||||
*
|
||||
* memset(blk_test, 0, blksz * data.blocks);
|
||||
* sg_init_one(&sg, blk_test, blksz * data.blocks);
|
||||
*
|
||||
* mrq.cmd = &cmd;
|
||||
* mrq.stop = &stop;
|
||||
* mrq.data = &data;
|
||||
* host->mrq = &mrq;
|
||||
* mmc_wait_for_req(mmc, &mrq);
|
||||
* return data.error | cmd.error;
|
||||
*}
|
||||
*/
|
||||
irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id)
|
||||
{
|
||||
struct amlsd_host *host = dev_id;
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
struct mmc_request *mrq;
|
||||
unsigned long flags;
|
||||
enum aml_mmc_waitfor xfer_step;
|
||||
u32 status, xfer_bytes = 0;
|
||||
|
||||
spin_lock_irqsave(&host->mrq_lock, flags);
|
||||
mrq = host->mrq;
|
||||
xfer_step = host->xfer_step;
|
||||
status = host->status;
|
||||
|
||||
if ((xfer_step == XFER_FINISHED) || (xfer_step == XFER_TIMER_TIMEOUT)) {
|
||||
sd_emmc_err("Warning: %s xfer_step=%d, host->status=%d\n",
|
||||
mmc_hostname(host->mmc), xfer_step, status);
|
||||
spin_unlock_irqrestore(&host->mrq_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
WARN_ON((host->xfer_step != XFER_IRQ_OCCUR)
|
||||
&& (host->xfer_step != XFER_IRQ_TASKLET_BUSY));
|
||||
|
||||
if (!mrq) {
|
||||
sd_emmc_err("%s: !mrq xfer_step %d\n",
|
||||
mmc_hostname(host->mmc), xfer_step);
|
||||
if (xfer_step == XFER_FINISHED ||
|
||||
xfer_step == XFER_TIMER_TIMEOUT){
|
||||
spin_unlock_irqrestore(&host->mrq_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
/* aml_sd_emmc_print_err(host); */
|
||||
}
|
||||
/* process stop cmd we sent on porpos */
|
||||
if (host->cmd_is_stop) {
|
||||
/* --new irq enter, */
|
||||
host->cmd_is_stop = 0;
|
||||
mrq->cmd->error = host->error_bak;
|
||||
spin_unlock_irqrestore(&host->mrq_lock, flags);
|
||||
meson_mmc_request_done(host->mmc, host->mrq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
spin_unlock_irqrestore(&host->mrq_lock, flags);
|
||||
|
||||
WARN_ON(!host->mrq->cmd);
|
||||
|
||||
switch (status) {
|
||||
case HOST_TASKLET_DATA:
|
||||
case HOST_TASKLET_CMD:
|
||||
/* WARN_ON(aml_sd_emmc_desc_check(host)); */
|
||||
sd_emmc_dbg(AMLSD_DBG_REQ, "%s %d cmd:%d\n",
|
||||
__func__, __LINE__, mrq->cmd->opcode);
|
||||
host->error_flag = 0;
|
||||
if (mrq->cmd->data && mrq->cmd->opcode) {
|
||||
xfer_bytes = mrq->data->blksz*mrq->data->blocks;
|
||||
/* copy buffer from dma to data->sg in read cmd*/
|
||||
#ifdef SD_EMMC_REQ_DMA_SGMAP
|
||||
WARN_ON(aml_sd_emmc_post_dma(host, mrq));
|
||||
#else
|
||||
if (host->mrq->data->flags & MMC_DATA_READ) {
|
||||
aml_sg_copy_buffer(mrq->data->sg,
|
||||
mrq->data->sg_len, host->bn_buf,
|
||||
xfer_bytes, 0);
|
||||
}
|
||||
#endif
|
||||
mrq->data->bytes_xfered = xfer_bytes;
|
||||
host->xfer_step = XFER_TASKLET_DATA;
|
||||
} else {
|
||||
host->xfer_step = XFER_TASKLET_CMD;
|
||||
}
|
||||
spin_lock_irqsave(&host->mrq_lock, flags);
|
||||
mrq->cmd->error = 0;
|
||||
spin_unlock_irqrestore(&host->mrq_lock, flags);
|
||||
|
||||
meson_mmc_read_resp(host->mmc, mrq->cmd);
|
||||
meson_mmc_request_done(host->mmc, mrq);
|
||||
|
||||
break;
|
||||
|
||||
case HOST_RSP_TIMEOUT_ERR:
|
||||
case HOST_DAT_TIMEOUT_ERR:
|
||||
case HOST_RSP_CRC_ERR:
|
||||
case HOST_DAT_CRC_ERR:
|
||||
if (host->is_tunning == 0)
|
||||
pr_info("%s %d %s: cmd:%d\n", __func__, __LINE__,
|
||||
mmc_hostname(host->mmc), mrq->cmd->opcode);
|
||||
if (mrq->cmd->data) {
|
||||
dma_unmap_sg(mmc_dev(host->mmc), mrq->cmd->data->sg,
|
||||
mrq->cmd->data->sg_len,
|
||||
(mrq->cmd->data->flags & MMC_DATA_READ) ?
|
||||
DMA_FROM_DEVICE : DMA_TO_DEVICE);
|
||||
}
|
||||
meson_mmc_read_resp(host->mmc, host->mrq->cmd);
|
||||
|
||||
/* set retry @ 1st error happens! */
|
||||
if ((host->error_flag == 0)
|
||||
&& (aml_card_type_mmc(pdata)
|
||||
|| aml_card_type_non_sdio(pdata))
|
||||
&& (host->is_tunning == 0)) {
|
||||
|
||||
sd_emmc_err("%s() %d: set 1st retry!\n",
|
||||
__func__, __LINE__);
|
||||
host->error_flag |= (1<<0);
|
||||
spin_lock_irqsave(&host->mrq_lock, flags);
|
||||
mrq->cmd->retries = 3;
|
||||
spin_unlock_irqrestore(&host->mrq_lock, flags);
|
||||
}
|
||||
|
||||
if (aml_card_type_mmc(pdata) &&
|
||||
(host->error_flag & (1<<0)) && mrq->cmd->retries) {
|
||||
sd_emmc_err("retry cmd %d the %d-th time(s)\n",
|
||||
mrq->cmd->opcode, mrq->cmd->retries);
|
||||
/* chage configs on current host */
|
||||
}
|
||||
/* last retry effort! */
|
||||
if ((aml_card_type_mmc(pdata) || aml_card_type_non_sdio(pdata))
|
||||
&& host->error_flag && (mrq->cmd->retries == 0)) {
|
||||
host->error_flag |= (1<<30);
|
||||
sd_emmc_err("Command retried failed line:%d, cmd:%d\n",
|
||||
__LINE__, mrq->cmd->opcode);
|
||||
}
|
||||
/* retry need send a stop 2 emmc... */
|
||||
/* do not send stop for sdio wifi case */
|
||||
if (host->mrq->stop
|
||||
&& (aml_card_type_mmc(pdata)
|
||||
|| aml_card_type_non_sdio(pdata))
|
||||
&& pdata->is_in
|
||||
&& (host->mrq->cmd->opcode != MMC_SEND_TUNING_BLOCK)
|
||||
&& (host->mrq->cmd->opcode !=
|
||||
MMC_SEND_TUNING_BLOCK_HS200))
|
||||
aml_sd_emmc_send_stop(host);
|
||||
else
|
||||
meson_mmc_request_done(host->mmc, mrq);
|
||||
break;
|
||||
|
||||
default:
|
||||
sd_emmc_err("BUG %s: xfer_step=%d, host->status=%d\n",
|
||||
mmc_hostname(host->mmc), xfer_step, status);
|
||||
/* aml_sd_emmc_print_err(host); */
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int aml_sd_emmc_cali_v3(struct mmc_host *mmc,
|
||||
u8 opcode, u8 *blk_test, u32 blksz, u32 blocks)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
struct mmc_request mrq = {NULL};
|
||||
struct mmc_command cmd = {0};
|
||||
struct mmc_command stop = {0};
|
||||
struct mmc_data data = {0};
|
||||
struct scatterlist sg;
|
||||
|
||||
cmd.opcode = opcode;
|
||||
cmd.arg = ((SZ_1M * (36 + 3)) / 512);
|
||||
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
|
||||
|
||||
stop.opcode = MMC_STOP_TRANSMISSION;
|
||||
stop.arg = 0;
|
||||
stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||
|
||||
data.blksz = blksz;
|
||||
data.blocks = blocks;
|
||||
data.flags = MMC_DATA_READ;
|
||||
data.sg = &sg;
|
||||
data.sg_len = 1;
|
||||
|
||||
memset(blk_test, 0, blksz * data.blocks);
|
||||
sg_init_one(&sg, blk_test, blksz * data.blocks);
|
||||
|
||||
mrq.cmd = &cmd;
|
||||
mrq.stop = &stop;
|
||||
mrq.data = &data;
|
||||
host->mrq = &mrq;
|
||||
mmc_wait_for_req(mmc, &mrq);
|
||||
return data.error | cmd.error;
|
||||
}
|
||||
|
||||
#define EMMC_TIMMING_DBG 1
|
||||
|
||||
static int emmc_eyetest_log(struct mmc_host *mmc, u32 line_x)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
u32 adjust = readl(host->base + SD_EMMC_ADJUST_V3);
|
||||
struct sd_emmc_adjust_v3 *gadjust =
|
||||
(struct sd_emmc_adjust_v3 *)&adjust;
|
||||
/*u32 delay1 = sd_emmc_regs->reg.v3.gdelay1;
|
||||
*struct sd_emmc_delay1 *gdelay1 = (struct sd_emmc_delay1 *)&delay1;
|
||||
*u32 delay2 = sd_emmc_regs->reg.v3.gdelay2;
|
||||
*struct sd_emmc_delay2 *gdelay2 = (struct sd_emmc_delay2 *)&delay2;
|
||||
*u32 clktest_log = 0;
|
||||
*struct clktest_log gclktest_log =
|
||||
* (struct clktest_log *)&(clktest_log);
|
||||
*u32 clktest_out = 0;
|
||||
*/
|
||||
u32 eyetest_log = 0;
|
||||
struct eyetest_log *geyetest_log = (struct eyetest_log *)&(eyetest_log);
|
||||
u32 eyetest_out0 = 0, eyetest_out1 = 0;
|
||||
u32 intf3 = readl(host->base + SD_EMMC_INTF3);
|
||||
struct intf3 *gintf3 = (struct intf3 *)&(intf3);
|
||||
u32 vcfg = readl(host->base + SD_EMMC_CFG);
|
||||
int j = 0;
|
||||
u64 tmp = 0;
|
||||
u32 blksz = 512;
|
||||
u8 *blk_test;
|
||||
blk_test = kmalloc(blksz * CALI_BLK_CNT, GFP_KERNEL);
|
||||
if (!blk_test)
|
||||
return -ENOMEM;
|
||||
host->is_tunning = 1;
|
||||
emmc_dbg(EMMC_TIMMING_DBG,
|
||||
"line_x: %d\n", line_x);
|
||||
/*sd_emmc_regs->reg.v3.gdelay1 = delay1;
|
||||
*sd_emmc_regs->reg.v3.gdelay2 = delay2;
|
||||
*/
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "delay1: 0x%x , delay2: 0x%x\n",
|
||||
readl(host->base + SD_EMMC_DELAY1_V3),
|
||||
readl(host->base + SD_EMMC_DELAY2_V3));
|
||||
gadjust->cali_enable = 1;
|
||||
gadjust->cali_sel = line_x;
|
||||
writel(adjust, host->base + SD_EMMC_ADJUST_V3);
|
||||
if (line_x < 9)
|
||||
gintf3->eyetest_exp = 7;
|
||||
else
|
||||
gintf3->eyetest_exp = 3;
|
||||
gintf3->eyetest_on = 1;
|
||||
writel(intf3, host->base + SD_EMMC_INTF3);
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "intf3: 0x%x,adjust: 0x%x\n",
|
||||
readl(host->base + SD_EMMC_INTF3),
|
||||
readl(host->base + SD_EMMC_ADJUST_V3));
|
||||
|
||||
/*****test start*************/
|
||||
if (line_x < 9)
|
||||
aml_sd_emmc_cali_v3(mmc,
|
||||
MMC_READ_MULTIPLE_BLOCK,
|
||||
blk_test, blksz, 40);
|
||||
else
|
||||
aml_sd_emmc_cali_v3(mmc,
|
||||
MMC_READ_MULTIPLE_BLOCK,
|
||||
blk_test, blksz, 80);
|
||||
|
||||
eyetest_log = readl(host->base + SD_EMMC_EYETEST_LOG);
|
||||
eyetest_out0 = readl(host->base + SD_EMMC_EYETEST_OUT0);
|
||||
eyetest_out1 = readl(host->base + SD_EMMC_EYETEST_OUT1);
|
||||
|
||||
while ((!(geyetest_log->eyetest_done & 0x1))) {
|
||||
eyetest_out0 = readl(host->base + SD_EMMC_EYETEST_OUT0);
|
||||
eyetest_out1 = readl(host->base + SD_EMMC_EYETEST_OUT1);
|
||||
eyetest_log = readl(host->base + SD_EMMC_EYETEST_LOG);
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "testing eyetest times: 0x%x, out: 0x%x, 0x%x\n",
|
||||
readl(host->base + SD_EMMC_EYETEST_LOG),
|
||||
eyetest_out0, eyetest_out1);
|
||||
if (j == 10)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "test done! eyetest times: 0x%x, out: 0x%x, 0x%x\n",
|
||||
readl(host->base + SD_EMMC_EYETEST_LOG),
|
||||
eyetest_out0, eyetest_out1);
|
||||
gintf3->eyetest_on = 0;
|
||||
writel(intf3, host->base + SD_EMMC_INTF3);
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "intf3: 0x%x,adjust: 0x%x\n",
|
||||
readl(host->base + SD_EMMC_INTF3),
|
||||
readl(host->base + SD_EMMC_ADJUST_V3));
|
||||
if (vcfg & 0x4) {
|
||||
if (pdata->count > 32) {
|
||||
eyetest_out1 <<= (32 - (pdata->count - 32));
|
||||
eyetest_out1 >>= (32 - (pdata->count - 32));
|
||||
} else
|
||||
eyetest_out1 = 0x0;
|
||||
}
|
||||
pdata->align[line_x] = ((tmp | eyetest_out1) << 32) | eyetest_out0;
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "u64 eyetestout 0x%llx\n",
|
||||
pdata->align[line_x]);
|
||||
host->is_tunning = 0;
|
||||
kfree(blk_test);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fbinary(u64 x)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
if ((x >> i) & 0x1)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int emmc_detect_base_line(u64 *arr)
|
||||
{
|
||||
u32 i = 0, first[10] = {0};
|
||||
u32 max = 0, l_max = 0xff;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
first[i] = fbinary(arr[i]);
|
||||
if (first[i] > max) {
|
||||
l_max = i;
|
||||
max = first[i];
|
||||
}
|
||||
}
|
||||
pr_warn("%s [%d] detect line:%d, max: %u\n",
|
||||
__func__, __LINE__, l_max, max);
|
||||
return max;
|
||||
}
|
||||
|
||||
/**************** start all data align ********************/
|
||||
static int emmc_all_data_line_alignment(struct mmc_host *mmc)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
u32 delay1 = 0, delay2 = 0;
|
||||
int result;
|
||||
int temp = 0, base_line = 0, line_x = 0;
|
||||
|
||||
pdata->base_line = emmc_detect_base_line(pdata->align);
|
||||
base_line = pdata->base_line;
|
||||
for (line_x = 0; line_x < 9; line_x++) {
|
||||
if (line_x == 8)
|
||||
continue;
|
||||
temp = fbinary(pdata->align[line_x]);
|
||||
if (temp <= 4)
|
||||
continue;
|
||||
result = base_line - temp;
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "line_x: %d, result: %d\n",
|
||||
line_x, result);
|
||||
if (line_x < 5)
|
||||
delay1 |= result << (6 * line_x);
|
||||
else
|
||||
delay2 |= result << (6 * (line_x - 5));
|
||||
}
|
||||
delay1 |= readl(host->base + SD_EMMC_DELAY1_V3);
|
||||
delay2 |= readl(host->base + SD_EMMC_DELAY2_V3);
|
||||
writel(delay1, host->base + SD_EMMC_DELAY1_V3);
|
||||
writel(delay2, host->base + SD_EMMC_DELAY2_V3);
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "delay1: 0x%x, delay2: 0x%x\n",
|
||||
delay1, delay2);
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "gdelay1: 0x%x, gdelay2: 0x%x\n",
|
||||
readl(host->base + SD_EMMC_DELAY1_V3),
|
||||
readl(host->base + SD_EMMC_DELAY2_V3));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emmc_ds_data_alignment(struct mmc_host *mmc)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
u32 delay1 = readl(host->base + SD_EMMC_DELAY1_V3);
|
||||
u32 delay2 = readl(host->base + SD_EMMC_DELAY2_V3);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
pr_info("i = %d, delay1: 0x%x, delay2: 0x%x\n",
|
||||
i, readl(host->base + SD_EMMC_DELAY1_V3),
|
||||
readl(host->base + SD_EMMC_DELAY2_V3));
|
||||
delay1 += (1<<0)|(1<<6)|(1<<12)|(1<<18)|(1<<24);
|
||||
delay2 += (1<<0)|(1<<6)|(1<<12)|(1<<24);
|
||||
writel(delay1, host->base + SD_EMMC_DELAY1_V3);
|
||||
writel(delay2, host->base + SD_EMMC_DELAY2_V3);
|
||||
emmc_eyetest_log(mmc, 3);
|
||||
emmc_eyetest_log(mmc, 8);
|
||||
if (pdata->align[3] & 0xf)
|
||||
break;
|
||||
}
|
||||
if (i == 64) {
|
||||
pr_warn("%s [%d] Don't find line delay which aligned with DS\n",
|
||||
__func__, __LINE__);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void print_all_line_eyetest(struct mmc_host *mmc)
|
||||
{
|
||||
int line_x;
|
||||
|
||||
for (line_x = 0; line_x < 10; line_x++)
|
||||
emmc_eyetest_log(mmc, line_x);
|
||||
}
|
||||
/* first step*/
|
||||
static int emmc_ds_core_align(struct mmc_host *mmc)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
u32 delay1 = readl(host->base + SD_EMMC_DELAY1_V3);
|
||||
u32 delay2 = readl(host->base + SD_EMMC_DELAY2_V3);
|
||||
u32 delay2_bak = delay2;
|
||||
u32 count = 0;
|
||||
u32 ds_count = 0;
|
||||
|
||||
if (pdata->align[8] & 0xf)
|
||||
return 0;
|
||||
ds_count = fbinary(pdata->align[8]);
|
||||
//BUG_ON(ds_count >= 4 && ds_count <= 8);
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "ds_count:%d,delay1:0x%x,delay2:0x%x\n",
|
||||
ds_count, readl(host->base + SD_EMMC_DELAY1_V3),
|
||||
readl(host->base + SD_EMMC_DELAY2_V3));
|
||||
if (ds_count < 20) {
|
||||
delay2 += ((20 - ds_count) << 18);
|
||||
writel(delay2, host->base + SD_EMMC_DELAY2_V3);
|
||||
} else {
|
||||
delay2 += (1<<18);
|
||||
writel(delay2, host->base + SD_EMMC_DELAY2_V3);
|
||||
}
|
||||
emmc_eyetest_log(mmc, 8);
|
||||
while (!(pdata->align[8] & 0xf)) {
|
||||
delay2 += (1<<18);
|
||||
writel(delay2, host->base + SD_EMMC_DELAY2_V3);
|
||||
emmc_eyetest_log(mmc, 8);
|
||||
}
|
||||
delay1 = readl(host->base + SD_EMMC_DELAY1_V3);
|
||||
delay2 = readl(host->base + SD_EMMC_DELAY2_V3);
|
||||
ds_count = fbinary(pdata->align[8]);
|
||||
count = ((delay2>>18) & 0x3f) - ((delay2_bak>>18) & 0x3f);
|
||||
pdata->ds_core = count;
|
||||
delay1 += (count<<0)|(count<<6)|(count<<12)|(count<<18)|(count<<24);
|
||||
delay2 += (count<<0)|(count<<6)|(count<<12)|(count<<24);
|
||||
writel(delay1, host->base + SD_EMMC_DELAY1_V3);
|
||||
writel(delay2, host->base + SD_EMMC_DELAY2_V3);
|
||||
emmc_dbg(EMMC_TIMMING_DBG,
|
||||
"ds_count:%d,delay1:0x%x,delay2:0x%x,count: %u\n",
|
||||
ds_count, readl(host->base + SD_EMMC_DELAY1_V3),
|
||||
readl(host->base + SD_EMMC_DELAY2_V3), count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 1
|
||||
static int emmc_ds_manual_sht(struct mmc_host *mmc)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
/* struct amlsd_platform *pdata = host->pdata; */
|
||||
u32 intf3 = readl(host->base + SD_EMMC_INTF3);
|
||||
struct intf3 *gintf3 = (struct intf3 *)&(intf3);
|
||||
u8 *blk_test = NULL;
|
||||
u32 blksz = 512;
|
||||
int i, err = 0;
|
||||
u32 sta = 0, end = 0, flag = 0;
|
||||
|
||||
blk_test = kmalloc(blksz * CALI_BLK_CNT, GFP_KERNEL);
|
||||
if (!blk_test)
|
||||
return -ENOMEM;
|
||||
|
||||
print_all_line_eyetest(mmc);
|
||||
emmc_ds_core_align(mmc);
|
||||
print_all_line_eyetest(mmc);
|
||||
emmc_all_data_line_alignment(mmc);
|
||||
print_all_line_eyetest(mmc);
|
||||
emmc_ds_data_alignment(mmc);
|
||||
print_all_line_eyetest(mmc);
|
||||
host->is_tunning = 1;
|
||||
for (i = 0; i < 64; i++) {
|
||||
gintf3->ds_sht_m += 1;
|
||||
writel(intf3, host->base + SD_EMMC_INTF3);
|
||||
err = aml_sd_emmc_cali_v3(mmc,
|
||||
MMC_READ_MULTIPLE_BLOCK,
|
||||
blk_test, blksz, 20);
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "intf3: 0x%x, err: %d\n",
|
||||
readl(host->base + SD_EMMC_INTF3), err);
|
||||
if (!err && !flag) {
|
||||
sta = i;
|
||||
flag = 1;
|
||||
} else if (err && flag) {
|
||||
end = i-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
gintf3->ds_sht_m = (sta + end) / 2;
|
||||
writel(intf3, host->base + SD_EMMC_INTF3);
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "sta:%u, end:%u,ds_sht:%u, intf3:0x%x",
|
||||
sta, end, gintf3->ds_sht_m,
|
||||
readl(host->base + SD_EMMC_INTF3));
|
||||
host->is_tunning = 0;
|
||||
kfree(blk_test);
|
||||
blk_test = NULL;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* test clock, return delay cells for one cycle
|
||||
*/
|
||||
static unsigned int emmc_clktest(struct mmc_host *mmc)
|
||||
{
|
||||
struct amlsd_host *host = mmc_priv(mmc);
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
u32 intf3 = readl(host->base + SD_EMMC_INTF3);
|
||||
struct intf3 *gintf3 = (struct intf3 *)&(intf3);
|
||||
u32 clktest = 0, delay_cell = 0, clktest_log = 0, count = 0;
|
||||
u32 vcfg = readl(host->base + SD_EMMC_CFG);
|
||||
int i = 0;
|
||||
|
||||
vcfg &= ~(1 << 23);
|
||||
writel(vcfg, host->base + SD_EMMC_CFG);
|
||||
writel(0, host->base + SD_EMMC_DELAY1_V3);
|
||||
writel(0, host->base + SD_EMMC_DELAY2_V3);
|
||||
gintf3->clktest_exp = 8;
|
||||
gintf3->clktest_on_m = 1;
|
||||
writel(intf3, host->base + SD_EMMC_INTF3);
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "CFG: 0x%x\n",
|
||||
readl(host->base + SD_EMMC_CFG));
|
||||
|
||||
clktest_log = readl(host->base + SD_EMMC_CLKTEST_LOG);
|
||||
clktest = readl(host->base + SD_EMMC_CLKTEST_OUT);
|
||||
while (!(clktest_log & 0x80000000)) {
|
||||
mdelay(1);
|
||||
i++;
|
||||
clktest_log = readl(host->base + SD_EMMC_CLKTEST_LOG);
|
||||
clktest = readl(host->base + SD_EMMC_CLKTEST_OUT);
|
||||
if (i > 4) {
|
||||
pr_warn("[%s] [%d] emmc clktest error\n",
|
||||
__func__, __LINE__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (clktest_log & 0x80000000) {
|
||||
clktest = readl(host->base + SD_EMMC_CLKTEST_OUT);
|
||||
count = clktest / (1 << 8);
|
||||
if (vcfg & 0x4)
|
||||
delay_cell = (2500 / count);
|
||||
else
|
||||
delay_cell = (5000 / count);
|
||||
}
|
||||
pr_info("%s [%d] clktest : %u, delay_cell: %d, count: %u\n",
|
||||
__func__, __LINE__, clktest, delay_cell, count);
|
||||
gintf3->clktest_on_m = 0;
|
||||
writel(intf3, host->base + SD_EMMC_INTF3);
|
||||
vcfg |= (1 << 23);
|
||||
writel(vcfg, host->base + SD_EMMC_CFG);
|
||||
|
||||
emmc_dbg(EMMC_TIMMING_DBG, "CFG: 0x%x\n",
|
||||
readl(host->base + SD_EMMC_CFG));
|
||||
pdata->count = count;
|
||||
pdata->delay_cell = delay_cell;
|
||||
return count;
|
||||
}
|
||||
|
||||
int aml_post_hs400_timming(struct mmc_host *mmc)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
emmc_clktest(mmc);
|
||||
ret = emmc_ds_manual_sht(mmc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "sd_ops.h"
|
||||
|
||||
#define DEFAULT_CMD6_TIMEOUT_MS 500
|
||||
#define AMLOGIC_HS400_TIMING 1
|
||||
|
||||
static const unsigned int tran_exp[] = {
|
||||
10000, 100000, 1000000, 10000000,
|
||||
@@ -1500,7 +1501,23 @@ static int mmc_hs200_tuning(struct mmc_card *card)
|
||||
|
||||
return mmc_execute_tuning(card);
|
||||
}
|
||||
#ifdef AMLOGIC_HS400_TIMING
|
||||
static int mmc_hs400_timming(struct mmc_card *card)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
int err = 0;
|
||||
|
||||
if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400)
|
||||
&& (host->ops->post_hs400_timming)) {
|
||||
err = host->ops->post_hs400_timming(host);
|
||||
if (err)
|
||||
pr_warn("%s: refix HS400 timming failed\n",
|
||||
mmc_hostname(host));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Handle the detection and initialisation of a card.
|
||||
*
|
||||
@@ -1742,6 +1759,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
err = mmc_select_hs400(card);
|
||||
if (err)
|
||||
goto free_card;
|
||||
#ifdef AMLOGIC_HS400_TIMING
|
||||
err = mmc_hs400_timming(card);
|
||||
if (err)
|
||||
goto err;
|
||||
#endif
|
||||
} else {
|
||||
/* Select the desired bus width optionally */
|
||||
err = mmc_select_bus_width(card);
|
||||
|
||||
@@ -24,9 +24,21 @@ extern int meson_mmc_clk_init_v3(struct amlsd_host *host);
|
||||
|
||||
extern void meson_mmc_set_ios_v3(struct mmc_host *mmc, struct mmc_ios *ios);
|
||||
|
||||
extern int aml_sd_emmc_execute_tuning_(struct mmc_host *mmc, u32 opcode,
|
||||
struct aml_tuning_data *tuning_data, u32 adj_win_start);
|
||||
/*extern int aml_sd_emmc_execute_tuning_(struct mmc_host *mmc, u32 opcode,
|
||||
* struct aml_tuning_data *tuning_data, u32 adj_win_start);
|
||||
*/
|
||||
|
||||
extern void aml_sd_emmc_set_buswidth(struct amlsd_host *host, u32 busw_ios);
|
||||
|
||||
extern int meson_mmc_request_done(struct mmc_host *mmc,
|
||||
struct mmc_request *mrq);
|
||||
|
||||
extern int meson_mmc_read_resp(struct mmc_host *mmc,
|
||||
struct mmc_command *cmd);
|
||||
|
||||
extern void aml_sd_emmc_send_stop(struct amlsd_host *host);
|
||||
|
||||
extern int aml_sd_emmc_post_dma(struct amlsd_host *host,
|
||||
struct mmc_request *mrq);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,10 +25,9 @@ void meson_mmc_set_ios_v3(struct mmc_host *mmc, struct mmc_ios *ios);
|
||||
|
||||
int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode);
|
||||
|
||||
/* irqreturn_t meson_mmc_irq_v3(int irq, void *dev_id);*/
|
||||
irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id);
|
||||
|
||||
/*irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id);*/
|
||||
/* int aml_post_hs400_timming(struct mmc_host *mmc); */
|
||||
int aml_post_hs400_timming(struct mmc_host *mmc);
|
||||
|
||||
/* extern ssize_t emmc_eyetest_show(struct device *dev,
|
||||
* struct device_attribute *attr, char *buf);
|
||||
|
||||
@@ -109,6 +109,11 @@ extern const u8 tuning_blk_pattern_8bit[128];
|
||||
#define sd_emmc_err(fmt, args...) \
|
||||
pr_warn("[%s] " fmt, __func__, ##args)
|
||||
|
||||
#define emmc_dbg(emmc_timming_dbg, fmt, args...) do {\
|
||||
if (emmc_timming_dbg) \
|
||||
pr_warn("[%s]" fmt, __func__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define SD_PARSE_U32_PROP_HEX(node, prop_name, prop, value) do { \
|
||||
if (!of_property_read_u32(node, prop_name, &prop)) {\
|
||||
value = prop;\
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#ifdef AML_CALIBRATION
|
||||
#define MAX_CALI_RETRY 3
|
||||
#define MAX_DELAY_CNT 16
|
||||
#define CALI_BLK_CNT 10
|
||||
#define CALI_BLK_CNT 80
|
||||
#endif
|
||||
|
||||
#define SD_EMMC_CLOCK 0x0
|
||||
@@ -58,7 +58,7 @@
|
||||
#define SD_EMMC_CLOCK_V3 0x0
|
||||
#define SD_EMMC_DELAY1_V3 0x4
|
||||
#define SD_EMMC_DELAY2_V3 0x8
|
||||
#define SD_EMMC_ADJUST_V3 0X10
|
||||
#define SD_EMMC_ADJUST_V3 0xc
|
||||
#define SD_EMMC_ADJ_IDX_LOG 0x20
|
||||
#define SD_EMMC_CLKTEST_LOG 0x24
|
||||
#define SD_EMMC_CLKTEST_OUT 0x28
|
||||
@@ -224,6 +224,13 @@ struct amlsd_platform {
|
||||
unsigned char caling;
|
||||
unsigned char calout[20][20];
|
||||
#endif
|
||||
u64 align[10];
|
||||
int base_line;
|
||||
unsigned int count;
|
||||
unsigned int delay_cell;
|
||||
unsigned int ds_core;
|
||||
/* int order; */
|
||||
unsigned int rx_err;
|
||||
/* 0:unknown, 1:mmc card(include eMMC), 2:sd card(include tSD),
|
||||
* 3:sdio device(ie:sdio-wifi), 4:SD combo (IO+mem) card,
|
||||
* 5:NON sdio device(means sd/mmc card), other:reserved
|
||||
@@ -327,6 +334,7 @@ struct amlsd_host {
|
||||
dma_addr_t dma_gping; /* 0x400 */
|
||||
dma_addr_t dma_gpong; /* 0x800 */
|
||||
char is_tunning;
|
||||
char is_timming;
|
||||
char tuning_mode;
|
||||
unsigned int irq;
|
||||
unsigned int irq_in;
|
||||
|
||||
@@ -155,6 +155,7 @@ struct mmc_host_ops {
|
||||
int card_drv, int *drv_type);
|
||||
void (*hw_reset)(struct mmc_host *host);
|
||||
void (*card_event)(struct mmc_host *host);
|
||||
int (*post_hs400_timming)(struct mmc_host *host);
|
||||
|
||||
/*
|
||||
* Optional callback to support controllers with HW issues for multiple
|
||||
|
||||
Reference in New Issue
Block a user