* [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support
@ 2015-01-14 10:30 ` Alim Akhtar
0 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-14 10:30 UTC (permalink / raw)
To: linux-mmc
Cc: chris, ulf.hansson, jh80.chung, tgih.jun, dianders, alim.akhtar,
kgene, linux-arm-kernel, devicetree, linux-samsung-soc,
a.kesavan
This adds HS400 mode support for exynos dw_mmc host controller.
Currently tested on Exynos5800-peach-pi platform for HS400 mode.
Tested HS200 mode with this series applied, HS200 still works.
Appreciate testing on other exynos5/7 platform which supports emmc5.0
Changes in V4:
* drop the idea of changing existing binding for ciu_div as per [1]
* addressed comments from Jaehoon Chung [2]
[1] http://www.spinics.net/lists/linux-samsung-soc/msg40923.html
[2] http://www.spinics.net/lists/devicetree/msg64373.html
Changes in V3:
rebased on ulf's next (commit: 607b448 mmc: core: Make tuning block patterns static)
Seungwon Jeon (2):
mmc: dw_mmc: exynos: Support eMMC's HS400 mode
ARM: dts: Add HS400 support for exynos5420 and exynos5800
.../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +-
arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +
arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +-
arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +-
drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
drivers/mmc/host/dw_mmc-exynos.h | 19 +-
drivers/mmc/host/dw_mmc.c | 16 +-
drivers/mmc/host/dw_mmc.h | 2 +
9 files changed, 212 insertions(+), 38 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support
@ 2015-01-14 10:30 ` Alim Akhtar
0 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-14 10:30 UTC (permalink / raw)
To: linux-arm-kernel
This adds HS400 mode support for exynos dw_mmc host controller.
Currently tested on Exynos5800-peach-pi platform for HS400 mode.
Tested HS200 mode with this series applied, HS200 still works.
Appreciate testing on other exynos5/7 platform which supports emmc5.0
Changes in V4:
* drop the idea of changing existing binding for ciu_div as per [1]
* addressed comments from Jaehoon Chung [2]
[1] http://www.spinics.net/lists/linux-samsung-soc/msg40923.html
[2] http://www.spinics.net/lists/devicetree/msg64373.html
Changes in V3:
rebased on ulf's next (commit: 607b448 mmc: core: Make tuning block patterns static)
Seungwon Jeon (2):
mmc: dw_mmc: exynos: Support eMMC's HS400 mode
ARM: dts: Add HS400 support for exynos5420 and exynos5800
.../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +-
arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +
arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +-
arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +-
drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
drivers/mmc/host/dw_mmc-exynos.h | 19 +-
drivers/mmc/host/dw_mmc.c | 16 +-
drivers/mmc/host/dw_mmc.h | 2 +
9 files changed, 212 insertions(+), 38 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 1/2] mmc: dw_mmc: exynos: Support eMMC's HS400 mode
2015-01-14 10:30 ` Alim Akhtar
@ 2015-01-14 10:30 ` Alim Akhtar
-1 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-14 10:30 UTC (permalink / raw)
To: linux-mmc
Cc: chris, ulf.hansson, jh80.chung, tgih.jun, dianders, alim.akhtar,
kgene, linux-arm-kernel, devicetree, linux-samsung-soc,
a.kesavan
From: Seungwon Jeon <tgih.jun@samsung.com>
Implements HS400 mode support for exynos host driver.
This also include some updates as new mode is added.
Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
[Alim: addressed review comments]
---
.../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
drivers/mmc/host/dw_mmc-exynos.h | 19 +-
drivers/mmc/host/dw_mmc.c | 16 +-
drivers/mmc/host/dw_mmc.h | 2 +
5 files changed, 196 insertions(+), 35 deletions(-)
diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
index ee4fc05..dcab52c 100644
--- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
@@ -36,6 +36,8 @@ Required Properties:
in transmit mode and CIU clock phase shift value in receive mode for double
data rate mode operation. Refer notes below for the order of the cells and the
valid values.
+* samsung,dw-mshc-hs400-timing: Specifies the value of CIU TX and RX clock phase
+ shift value for hs400 mode operation.
Notes for the sdr-timing and ddr-timing values:
@@ -50,6 +52,9 @@ Required Properties:
- if CIU clock divider value is 0 (that is divide by 1), both tx and rx
phase shift clocks should be 0.
+* read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode
+ (Latency value for delay line in Read path)
+
Required properties for a slot (Deprecated - Recommend to use one slot per host):
* gpios: specifies a list of gpios used for command, clock and data bus. The
@@ -82,5 +87,7 @@ Example:
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <2 3>;
samsung,dw-mshc-ddr-timing = <1 2>;
+ samsung,dw-mshc-hs400-timing = <0 2>;
+ read-strobe-delay = <90>;
bus-width = <8>;
};
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 12a5eaa..172a2a8 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -40,7 +40,12 @@ struct dw_mci_exynos_priv_data {
u8 ciu_div;
u32 sdr_timing;
u32 ddr_timing;
+ u32 hs400_timing;
+ u32 tuned_sample;
u32 cur_speed;
+ u32 dqs_delay;
+ u32 saved_dqs_en;
+ u32 saved_strobe_ctrl;
};
static struct dw_mci_exynos_compatible {
@@ -71,6 +76,21 @@ static struct dw_mci_exynos_compatible {
},
};
+static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
+ return EXYNOS4412_FIXED_CIU_CLK_DIV;
+ else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
+ return EXYNOS4210_FIXED_CIU_CLK_DIV;
+ else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+ return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
+ else
+ return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1;
+}
+
static int dw_mci_exynos_priv_init(struct dw_mci *host)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
@@ -85,6 +105,16 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT);
}
+ if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) {
+ priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL);
+ priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN);
+ priv->saved_dqs_en |= AXI_NON_BLOCKING_WR;
+ mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en);
+ if (!priv->dqs_delay)
+ priv->dqs_delay =
+ DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
+ }
+
return 0;
}
@@ -92,11 +122,31 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
- host->bus_hz /= (priv->ciu_div + 1);
+ host->bus_hz /= priv->ciu_div;
return 0;
}
+static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+ u32 clksel;
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+ clksel = mci_readl(host, CLKSEL64);
+ else
+ clksel = mci_readl(host, CLKSEL);
+
+ clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing;
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+ mci_writel(host, CLKSEL64, clksel);
+ else
+ mci_writel(host, CLKSEL, clksel);
+}
+
#ifdef CONFIG_PM_SLEEP
static int dw_mci_exynos_suspend(struct device *dev)
{
@@ -172,30 +222,38 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
}
}
-static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
- unsigned int wanted = ios->clock;
- unsigned long actual;
- u8 div = priv->ciu_div + 1;
+ u32 dqs, strobe;
- if (ios->timing == MMC_TIMING_MMC_DDR52) {
- if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
- priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
- mci_writel(host, CLKSEL64, priv->ddr_timing);
- else
- mci_writel(host, CLKSEL, priv->ddr_timing);
- /* Should be double rate for DDR mode */
- if (ios->bus_width == MMC_BUS_WIDTH_8)
- wanted <<= 1;
+ /*
+ * Not suppported to configure register
+ * related to HS400
+ */
+ if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420)
+ return;
+
+ dqs = priv->saved_dqs_en;
+ strobe = priv->saved_strobe_ctrl;
+
+ if (timing == MMC_TIMING_MMC_HS400) {
+ dqs |= DATA_STROBE_EN;
+ strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay);
} else {
- if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
- priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
- mci_writel(host, CLKSEL64, priv->sdr_timing);
- else
- mci_writel(host, CLKSEL, priv->sdr_timing);
+ dqs &= ~DATA_STROBE_EN;
}
+ mci_writel(host, HS400_DQS_EN, dqs);
+ mci_writel(host, HS400_DLINE_CTRL, strobe);
+}
+
+static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+ unsigned long actual;
+ u8 div;
+ int ret;
/*
* Don't care if wanted clock is zero or
* ciu clock is unavailable
@@ -207,17 +265,52 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
if (wanted < EXYNOS_CCLKIN_MIN)
wanted = EXYNOS_CCLKIN_MIN;
- if (wanted != priv->cur_speed) {
- int ret = clk_set_rate(host->ciu_clk, wanted * div);
- if (ret)
- dev_warn(host->dev,
- "failed to set clk-rate %u error: %d\n",
- wanted * div, ret);
- actual = clk_get_rate(host->ciu_clk);
- host->bus_hz = actual / div;
- priv->cur_speed = wanted;
- host->current_speed = 0;
+ if (wanted == priv->cur_speed)
+ return;
+
+ div = dw_mci_exynos_get_ciu_div(host);
+ ret = clk_set_rate(host->ciu_clk, wanted * div);
+ if (ret)
+ dev_warn(host->dev,
+ "failed to set clk-rate %u error: %d\n",
+ wanted * div, ret);
+ actual = clk_get_rate(host->ciu_clk);
+ host->bus_hz = actual / div;
+ priv->cur_speed = wanted;
+ host->current_speed = 0;
+}
+
+static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+ unsigned int wanted = ios->clock;
+ u32 timing = ios->timing, clksel;
+
+ switch (timing) {
+ case MMC_TIMING_MMC_HS400:
+ /* Update tuned sample timing */
+ clksel = SDMMC_CLKSEL_UP_SAMPLE(
+ priv->hs400_timing, priv->tuned_sample);
+ wanted <<= 1;
+ break;
+ case MMC_TIMING_MMC_DDR52:
+ clksel = priv->ddr_timing;
+ /* Should be double rate for DDR mode */
+ if (ios->bus_width == MMC_BUS_WIDTH_8)
+ wanted <<= 1;
+ break;
+ default:
+ clksel = priv->sdr_timing;
}
+
+ /* Set clock timing for the requested speed mode*/
+ dw_mci_exynos_set_clksel_timing(host, clksel);
+
+ /* Configure setting for HS400 */
+ dw_mci_exynos_config_hs400(host, timing);
+
+ /* Configure clock rate */
+ dw_mci_exynos_adjust_clock(host, wanted);
}
static int dw_mci_exynos_parse_dt(struct dw_mci *host)
@@ -260,6 +353,16 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host)
return ret;
priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
+
+ ret = of_property_read_u32_array(np,
+ "samsung,dw-mshc-hs400-timing", timing, 2);
+ if (!ret && of_property_read_u32(np,
+ "read-strobe-delay", &priv->dqs_delay))
+ dev_info(host->dev,
+ "read-strobe-delay is not found, assuming usage of default value\n");
+
+ priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1],
+ HS400_FIXED_CIU_CLK_DIV);
host->priv = priv;
return 0;
}
@@ -285,7 +388,7 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
clksel = mci_readl(host, CLKSEL64);
else
clksel = mci_readl(host, CLKSEL);
- clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample);
+ clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
mci_writel(host, CLKSEL64, clksel);
@@ -304,13 +407,16 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
clksel = mci_readl(host, CLKSEL64);
else
clksel = mci_readl(host, CLKSEL);
+
sample = (clksel + 1) & 0x7;
- clksel = (clksel & ~0x7) | sample;
+ clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
+
if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
mci_writel(host, CLKSEL64, clksel);
else
mci_writel(host, CLKSEL, clksel);
+
return sample;
}
@@ -343,6 +449,7 @@ out:
static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
{
struct dw_mci *host = slot->host;
+ struct dw_mci_exynos_priv_data *priv = host->priv;
struct mmc_host *mmc = slot->mmc;
u8 start_smpl, smpl, candiates = 0;
s8 found = -1;
@@ -360,14 +467,27 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
} while (start_smpl != smpl);
found = dw_mci_exynos_get_best_clksmpl(candiates);
- if (found >= 0)
+ if (found >= 0) {
dw_mci_exynos_set_clksmpl(host, found);
- else
+ priv->tuned_sample = found;
+ } else {
ret = -EIO;
+ }
return ret;
}
+int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
+ struct mmc_ios *ios)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+
+ dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing);
+ dw_mci_exynos_adjust_clock(host, (ios->clock) << 1);
+
+ return 0;
+}
+
/* Common capabilities of Exynos4/Exynos5 SoC */
static unsigned long exynos_dwmmc_caps[4] = {
MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
@@ -384,6 +504,7 @@ static const struct dw_mci_drv_data exynos_drv_data = {
.set_ios = dw_mci_exynos_set_ios,
.parse_dt = dw_mci_exynos_parse_dt,
.execute_tuning = dw_mci_exynos_execute_tuning,
+ .prepare_hs400_tuning = dw_mci_exynos_prepare_hs400_tuning,
};
static const struct of_device_id dw_mci_exynos_match[] = {
diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h
index 7872ce5..595c934 100644
--- a/drivers/mmc/host/dw_mmc-exynos.h
+++ b/drivers/mmc/host/dw_mmc-exynos.h
@@ -12,20 +12,36 @@
#ifndef _DW_MMC_EXYNOS_H_
#define _DW_MMC_EXYNOS_H_
-/* Extended Register's Offset */
#define SDMMC_CLKSEL 0x09C
#define SDMMC_CLKSEL64 0x0A8
+/* Extended Register's Offset */
+#define SDMMC_HS400_DQS_EN 0x180
+#define SDMMC_HS400_ASYNC_FIFO_CTRL 0x184
+#define SDMMC_HS400_DLINE_CTRL 0x188
+
/* CLKSEL register defines */
#define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0)
#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16)
#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24)
#define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7)
+#define SDMMC_CLKSEL_GET_DIV(x) (((x) >> 24) & 0x7)
+#define SDMMC_CLKSEL_UP_SAMPLE(x, y) (((x) & ~SDMMC_CLKSEL_CCLK_SAMPLE(7)) |\
+ SDMMC_CLKSEL_CCLK_SAMPLE(y))
#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \
SDMMC_CLKSEL_CCLK_DRIVE(y) | \
SDMMC_CLKSEL_CCLK_DIVIDER(z))
+#define SDMMC_CLKSEL_TIMING_MASK SDMMC_CLKSEL_TIMING(0x7, 0x7, 0x7)
#define SDMMC_CLKSEL_WAKEUP_INT BIT(11)
+/* RCLK_EN register defines */
+#define DATA_STROBE_EN BIT(0)
+#define AXI_NON_BLOCKING_WR BIT(7)
+
+/* DLINE_CTRL register defines */
+#define DQS_CTRL_RD_DELAY(x, y) (((x) & ~0x3FF) | ((y) & 0x3FF))
+#define DQS_CTRL_GET_RD_DELAY(x) ((x) & 0x3FF)
+
/* Protector Register */
#define SDMMC_EMMCP_BASE 0x1000
#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010)
@@ -49,6 +65,7 @@
/* Fixed clock divider */
#define EXYNOS4210_FIXED_CIU_CLK_DIV 2
#define EXYNOS4412_FIXED_CIU_CLK_DIV 4
+#define HS400_FIXED_CIU_CLK_DIV 1
/* Minimal required clock frequency for cclkin, unit: HZ */
#define EXYNOS_CCLKIN_MIN 50000000
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 2e8abc8..43a3a5b 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1084,7 +1084,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
regs = mci_readl(slot->host, UHS_REG);
/* DDR mode set */
- if (ios->timing == MMC_TIMING_MMC_DDR52)
+ if (ios->timing == MMC_TIMING_MMC_DDR52 ||
+ ios->timing == MMC_TIMING_MMC_HS400)
regs |= ((0x1 << slot->id) << 16);
else
regs &= ~((0x1 << slot->id) << 16);
@@ -1321,6 +1322,18 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
return err;
}
+int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct dw_mci_slot *slot = mmc_priv(mmc);
+ struct dw_mci *host = slot->host;
+ const struct dw_mci_drv_data *drv_data = host->drv_data;
+
+ if (drv_data && drv_data->prepare_hs400_tuning)
+ return drv_data->prepare_hs400_tuning(host, ios);
+
+ return 0;
+}
+
static const struct mmc_host_ops dw_mci_ops = {
.request = dw_mci_request,
.pre_req = dw_mci_pre_req,
@@ -1333,6 +1346,7 @@ static const struct mmc_host_ops dw_mci_ops = {
.card_busy = dw_mci_card_busy,
.start_signal_voltage_switch = dw_mci_switch_voltage,
.init_card = dw_mci_init_card,
+ .prepare_hs400_tuning = dw_mci_prepare_hs400_tuning,
};
static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 18c4afe..d239867 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -271,5 +271,7 @@ struct dw_mci_drv_data {
void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
int (*parse_dt)(struct dw_mci *host);
int (*execute_tuning)(struct dw_mci_slot *slot);
+ int (*prepare_hs400_tuning)(struct dw_mci *host,
+ struct mmc_ios *ios);
};
#endif /* _DW_MMC_H_ */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 1/2] mmc: dw_mmc: exynos: Support eMMC's HS400 mode
@ 2015-01-14 10:30 ` Alim Akhtar
0 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-14 10:30 UTC (permalink / raw)
To: linux-arm-kernel
From: Seungwon Jeon <tgih.jun@samsung.com>
Implements HS400 mode support for exynos host driver.
This also include some updates as new mode is added.
Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
[Alim: addressed review comments]
---
.../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
drivers/mmc/host/dw_mmc-exynos.h | 19 +-
drivers/mmc/host/dw_mmc.c | 16 +-
drivers/mmc/host/dw_mmc.h | 2 +
5 files changed, 196 insertions(+), 35 deletions(-)
diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
index ee4fc05..dcab52c 100644
--- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
@@ -36,6 +36,8 @@ Required Properties:
in transmit mode and CIU clock phase shift value in receive mode for double
data rate mode operation. Refer notes below for the order of the cells and the
valid values.
+* samsung,dw-mshc-hs400-timing: Specifies the value of CIU TX and RX clock phase
+ shift value for hs400 mode operation.
Notes for the sdr-timing and ddr-timing values:
@@ -50,6 +52,9 @@ Required Properties:
- if CIU clock divider value is 0 (that is divide by 1), both tx and rx
phase shift clocks should be 0.
+* read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode
+ (Latency value for delay line in Read path)
+
Required properties for a slot (Deprecated - Recommend to use one slot per host):
* gpios: specifies a list of gpios used for command, clock and data bus. The
@@ -82,5 +87,7 @@ Example:
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <2 3>;
samsung,dw-mshc-ddr-timing = <1 2>;
+ samsung,dw-mshc-hs400-timing = <0 2>;
+ read-strobe-delay = <90>;
bus-width = <8>;
};
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 12a5eaa..172a2a8 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -40,7 +40,12 @@ struct dw_mci_exynos_priv_data {
u8 ciu_div;
u32 sdr_timing;
u32 ddr_timing;
+ u32 hs400_timing;
+ u32 tuned_sample;
u32 cur_speed;
+ u32 dqs_delay;
+ u32 saved_dqs_en;
+ u32 saved_strobe_ctrl;
};
static struct dw_mci_exynos_compatible {
@@ -71,6 +76,21 @@ static struct dw_mci_exynos_compatible {
},
};
+static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
+ return EXYNOS4412_FIXED_CIU_CLK_DIV;
+ else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
+ return EXYNOS4210_FIXED_CIU_CLK_DIV;
+ else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+ return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
+ else
+ return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1;
+}
+
static int dw_mci_exynos_priv_init(struct dw_mci *host)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
@@ -85,6 +105,16 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT);
}
+ if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) {
+ priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL);
+ priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN);
+ priv->saved_dqs_en |= AXI_NON_BLOCKING_WR;
+ mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en);
+ if (!priv->dqs_delay)
+ priv->dqs_delay =
+ DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
+ }
+
return 0;
}
@@ -92,11 +122,31 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
- host->bus_hz /= (priv->ciu_div + 1);
+ host->bus_hz /= priv->ciu_div;
return 0;
}
+static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+ u32 clksel;
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+ clksel = mci_readl(host, CLKSEL64);
+ else
+ clksel = mci_readl(host, CLKSEL);
+
+ clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing;
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+ mci_writel(host, CLKSEL64, clksel);
+ else
+ mci_writel(host, CLKSEL, clksel);
+}
+
#ifdef CONFIG_PM_SLEEP
static int dw_mci_exynos_suspend(struct device *dev)
{
@@ -172,30 +222,38 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
}
}
-static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
- unsigned int wanted = ios->clock;
- unsigned long actual;
- u8 div = priv->ciu_div + 1;
+ u32 dqs, strobe;
- if (ios->timing == MMC_TIMING_MMC_DDR52) {
- if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
- priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
- mci_writel(host, CLKSEL64, priv->ddr_timing);
- else
- mci_writel(host, CLKSEL, priv->ddr_timing);
- /* Should be double rate for DDR mode */
- if (ios->bus_width == MMC_BUS_WIDTH_8)
- wanted <<= 1;
+ /*
+ * Not suppported to configure register
+ * related to HS400
+ */
+ if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420)
+ return;
+
+ dqs = priv->saved_dqs_en;
+ strobe = priv->saved_strobe_ctrl;
+
+ if (timing == MMC_TIMING_MMC_HS400) {
+ dqs |= DATA_STROBE_EN;
+ strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay);
} else {
- if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
- priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
- mci_writel(host, CLKSEL64, priv->sdr_timing);
- else
- mci_writel(host, CLKSEL, priv->sdr_timing);
+ dqs &= ~DATA_STROBE_EN;
}
+ mci_writel(host, HS400_DQS_EN, dqs);
+ mci_writel(host, HS400_DLINE_CTRL, strobe);
+}
+
+static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+ unsigned long actual;
+ u8 div;
+ int ret;
/*
* Don't care if wanted clock is zero or
* ciu clock is unavailable
@@ -207,17 +265,52 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
if (wanted < EXYNOS_CCLKIN_MIN)
wanted = EXYNOS_CCLKIN_MIN;
- if (wanted != priv->cur_speed) {
- int ret = clk_set_rate(host->ciu_clk, wanted * div);
- if (ret)
- dev_warn(host->dev,
- "failed to set clk-rate %u error: %d\n",
- wanted * div, ret);
- actual = clk_get_rate(host->ciu_clk);
- host->bus_hz = actual / div;
- priv->cur_speed = wanted;
- host->current_speed = 0;
+ if (wanted == priv->cur_speed)
+ return;
+
+ div = dw_mci_exynos_get_ciu_div(host);
+ ret = clk_set_rate(host->ciu_clk, wanted * div);
+ if (ret)
+ dev_warn(host->dev,
+ "failed to set clk-rate %u error: %d\n",
+ wanted * div, ret);
+ actual = clk_get_rate(host->ciu_clk);
+ host->bus_hz = actual / div;
+ priv->cur_speed = wanted;
+ host->current_speed = 0;
+}
+
+static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+ unsigned int wanted = ios->clock;
+ u32 timing = ios->timing, clksel;
+
+ switch (timing) {
+ case MMC_TIMING_MMC_HS400:
+ /* Update tuned sample timing */
+ clksel = SDMMC_CLKSEL_UP_SAMPLE(
+ priv->hs400_timing, priv->tuned_sample);
+ wanted <<= 1;
+ break;
+ case MMC_TIMING_MMC_DDR52:
+ clksel = priv->ddr_timing;
+ /* Should be double rate for DDR mode */
+ if (ios->bus_width == MMC_BUS_WIDTH_8)
+ wanted <<= 1;
+ break;
+ default:
+ clksel = priv->sdr_timing;
}
+
+ /* Set clock timing for the requested speed mode*/
+ dw_mci_exynos_set_clksel_timing(host, clksel);
+
+ /* Configure setting for HS400 */
+ dw_mci_exynos_config_hs400(host, timing);
+
+ /* Configure clock rate */
+ dw_mci_exynos_adjust_clock(host, wanted);
}
static int dw_mci_exynos_parse_dt(struct dw_mci *host)
@@ -260,6 +353,16 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host)
return ret;
priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
+
+ ret = of_property_read_u32_array(np,
+ "samsung,dw-mshc-hs400-timing", timing, 2);
+ if (!ret && of_property_read_u32(np,
+ "read-strobe-delay", &priv->dqs_delay))
+ dev_info(host->dev,
+ "read-strobe-delay is not found, assuming usage of default value\n");
+
+ priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1],
+ HS400_FIXED_CIU_CLK_DIV);
host->priv = priv;
return 0;
}
@@ -285,7 +388,7 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
clksel = mci_readl(host, CLKSEL64);
else
clksel = mci_readl(host, CLKSEL);
- clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample);
+ clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
mci_writel(host, CLKSEL64, clksel);
@@ -304,13 +407,16 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
clksel = mci_readl(host, CLKSEL64);
else
clksel = mci_readl(host, CLKSEL);
+
sample = (clksel + 1) & 0x7;
- clksel = (clksel & ~0x7) | sample;
+ clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
+
if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
mci_writel(host, CLKSEL64, clksel);
else
mci_writel(host, CLKSEL, clksel);
+
return sample;
}
@@ -343,6 +449,7 @@ out:
static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
{
struct dw_mci *host = slot->host;
+ struct dw_mci_exynos_priv_data *priv = host->priv;
struct mmc_host *mmc = slot->mmc;
u8 start_smpl, smpl, candiates = 0;
s8 found = -1;
@@ -360,14 +467,27 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
} while (start_smpl != smpl);
found = dw_mci_exynos_get_best_clksmpl(candiates);
- if (found >= 0)
+ if (found >= 0) {
dw_mci_exynos_set_clksmpl(host, found);
- else
+ priv->tuned_sample = found;
+ } else {
ret = -EIO;
+ }
return ret;
}
+int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
+ struct mmc_ios *ios)
+{
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+
+ dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing);
+ dw_mci_exynos_adjust_clock(host, (ios->clock) << 1);
+
+ return 0;
+}
+
/* Common capabilities of Exynos4/Exynos5 SoC */
static unsigned long exynos_dwmmc_caps[4] = {
MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
@@ -384,6 +504,7 @@ static const struct dw_mci_drv_data exynos_drv_data = {
.set_ios = dw_mci_exynos_set_ios,
.parse_dt = dw_mci_exynos_parse_dt,
.execute_tuning = dw_mci_exynos_execute_tuning,
+ .prepare_hs400_tuning = dw_mci_exynos_prepare_hs400_tuning,
};
static const struct of_device_id dw_mci_exynos_match[] = {
diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h
index 7872ce5..595c934 100644
--- a/drivers/mmc/host/dw_mmc-exynos.h
+++ b/drivers/mmc/host/dw_mmc-exynos.h
@@ -12,20 +12,36 @@
#ifndef _DW_MMC_EXYNOS_H_
#define _DW_MMC_EXYNOS_H_
-/* Extended Register's Offset */
#define SDMMC_CLKSEL 0x09C
#define SDMMC_CLKSEL64 0x0A8
+/* Extended Register's Offset */
+#define SDMMC_HS400_DQS_EN 0x180
+#define SDMMC_HS400_ASYNC_FIFO_CTRL 0x184
+#define SDMMC_HS400_DLINE_CTRL 0x188
+
/* CLKSEL register defines */
#define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0)
#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16)
#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24)
#define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7)
+#define SDMMC_CLKSEL_GET_DIV(x) (((x) >> 24) & 0x7)
+#define SDMMC_CLKSEL_UP_SAMPLE(x, y) (((x) & ~SDMMC_CLKSEL_CCLK_SAMPLE(7)) |\
+ SDMMC_CLKSEL_CCLK_SAMPLE(y))
#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \
SDMMC_CLKSEL_CCLK_DRIVE(y) | \
SDMMC_CLKSEL_CCLK_DIVIDER(z))
+#define SDMMC_CLKSEL_TIMING_MASK SDMMC_CLKSEL_TIMING(0x7, 0x7, 0x7)
#define SDMMC_CLKSEL_WAKEUP_INT BIT(11)
+/* RCLK_EN register defines */
+#define DATA_STROBE_EN BIT(0)
+#define AXI_NON_BLOCKING_WR BIT(7)
+
+/* DLINE_CTRL register defines */
+#define DQS_CTRL_RD_DELAY(x, y) (((x) & ~0x3FF) | ((y) & 0x3FF))
+#define DQS_CTRL_GET_RD_DELAY(x) ((x) & 0x3FF)
+
/* Protector Register */
#define SDMMC_EMMCP_BASE 0x1000
#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010)
@@ -49,6 +65,7 @@
/* Fixed clock divider */
#define EXYNOS4210_FIXED_CIU_CLK_DIV 2
#define EXYNOS4412_FIXED_CIU_CLK_DIV 4
+#define HS400_FIXED_CIU_CLK_DIV 1
/* Minimal required clock frequency for cclkin, unit: HZ */
#define EXYNOS_CCLKIN_MIN 50000000
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 2e8abc8..43a3a5b 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1084,7 +1084,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
regs = mci_readl(slot->host, UHS_REG);
/* DDR mode set */
- if (ios->timing == MMC_TIMING_MMC_DDR52)
+ if (ios->timing == MMC_TIMING_MMC_DDR52 ||
+ ios->timing == MMC_TIMING_MMC_HS400)
regs |= ((0x1 << slot->id) << 16);
else
regs &= ~((0x1 << slot->id) << 16);
@@ -1321,6 +1322,18 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
return err;
}
+int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct dw_mci_slot *slot = mmc_priv(mmc);
+ struct dw_mci *host = slot->host;
+ const struct dw_mci_drv_data *drv_data = host->drv_data;
+
+ if (drv_data && drv_data->prepare_hs400_tuning)
+ return drv_data->prepare_hs400_tuning(host, ios);
+
+ return 0;
+}
+
static const struct mmc_host_ops dw_mci_ops = {
.request = dw_mci_request,
.pre_req = dw_mci_pre_req,
@@ -1333,6 +1346,7 @@ static const struct mmc_host_ops dw_mci_ops = {
.card_busy = dw_mci_card_busy,
.start_signal_voltage_switch = dw_mci_switch_voltage,
.init_card = dw_mci_init_card,
+ .prepare_hs400_tuning = dw_mci_prepare_hs400_tuning,
};
static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 18c4afe..d239867 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -271,5 +271,7 @@ struct dw_mci_drv_data {
void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
int (*parse_dt)(struct dw_mci *host);
int (*execute_tuning)(struct dw_mci_slot *slot);
+ int (*prepare_hs400_tuning)(struct dw_mci *host,
+ struct mmc_ios *ios);
};
#endif /* _DW_MMC_H_ */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
2015-01-14 10:30 ` Alim Akhtar
@ 2015-01-14 10:30 ` Alim Akhtar
-1 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-14 10:30 UTC (permalink / raw)
To: linux-mmc
Cc: chris, ulf.hansson, jh80.chung, tgih.jun, dianders, alim.akhtar,
kgene, linux-arm-kernel, devicetree, linux-samsung-soc,
a.kesavan
From: Seungwon Jeon <tgih.jun@samsung.com>
HS400 timing values are added for SMDK5420, exynos5420-peach-pit
and exynos5800-peach-pi boards.
This also adds RCLK GPIO line, this gpio should be in pull-down
state.
Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
[Alim: addressed review comments]
---
arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
4 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index 9a050e1..7ffaba8 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -569,8 +569,10 @@
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <0 4>;
samsung,dw-mshc-ddr-timing = <0 2>;
+ samsung,dw-mshc-hs400-timing = <0 2>;
+ read-strobe-delay = <90>;
pinctrl-names = "default";
- pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
bus-width = <8>;
};
diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
index ba686e4..8b15316 100644
--- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
@@ -201,6 +201,13 @@
samsung,pin-drv = <3>;
};
+ sd0_rclk: sd0-rclk {
+ samsung,pins = "gpc0-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <1>;
+ samsung,pin-drv = <3>;
+ };
+
sd1_cmd: sd1-cmd {
samsung,pins = "gpc1-1";
samsung,pin-function = <2>;
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
index 8be3d7b..5290e79 100644
--- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
+++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
@@ -80,8 +80,10 @@
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <0 4>;
samsung,dw-mshc-ddr-timing = <0 2>;
+ samsung,dw-mshc-hs400-timing = <0 2>;
+ read-strobe-delay = <90>;
pinctrl-names = "default";
- pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
bus-width = <8>;
cap-mmc-highspeed;
};
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index e8fdda8..fa1c858 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -557,8 +557,10 @@
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <0 4>;
samsung,dw-mshc-ddr-timing = <0 2>;
+ samsung,dw-mshc-hs400-timing = <0 2>;
+ read-strobe-delay = <90>;
pinctrl-names = "default";
- pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
bus-width = <8>;
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
@ 2015-01-14 10:30 ` Alim Akhtar
0 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-14 10:30 UTC (permalink / raw)
To: linux-arm-kernel
From: Seungwon Jeon <tgih.jun@samsung.com>
HS400 timing values are added for SMDK5420, exynos5420-peach-pit
and exynos5800-peach-pi boards.
This also adds RCLK GPIO line, this gpio should be in pull-down
state.
Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
[Alim: addressed review comments]
---
arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
4 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index 9a050e1..7ffaba8 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -569,8 +569,10 @@
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <0 4>;
samsung,dw-mshc-ddr-timing = <0 2>;
+ samsung,dw-mshc-hs400-timing = <0 2>;
+ read-strobe-delay = <90>;
pinctrl-names = "default";
- pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
bus-width = <8>;
};
diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
index ba686e4..8b15316 100644
--- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
@@ -201,6 +201,13 @@
samsung,pin-drv = <3>;
};
+ sd0_rclk: sd0-rclk {
+ samsung,pins = "gpc0-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <1>;
+ samsung,pin-drv = <3>;
+ };
+
sd1_cmd: sd1-cmd {
samsung,pins = "gpc1-1";
samsung,pin-function = <2>;
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
index 8be3d7b..5290e79 100644
--- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
+++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
@@ -80,8 +80,10 @@
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <0 4>;
samsung,dw-mshc-ddr-timing = <0 2>;
+ samsung,dw-mshc-hs400-timing = <0 2>;
+ read-strobe-delay = <90>;
pinctrl-names = "default";
- pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
bus-width = <8>;
cap-mmc-highspeed;
};
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index e8fdda8..fa1c858 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -557,8 +557,10 @@
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <0 4>;
samsung,dw-mshc-ddr-timing = <0 2>;
+ samsung,dw-mshc-hs400-timing = <0 2>;
+ read-strobe-delay = <90>;
pinctrl-names = "default";
- pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
bus-width = <8>;
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support
2015-01-14 10:30 ` Alim Akhtar
@ 2015-01-14 13:32 ` Jaehoon Chung
-1 siblings, 0 replies; 24+ messages in thread
From: Jaehoon Chung @ 2015-01-14 13:32 UTC (permalink / raw)
To: Alim Akhtar, linux-mmc
Cc: devicetree, ulf.hansson, linux-samsung-soc, tgih.jun, chris,
dianders, jh80.chung, kgene, a.kesavan, alim.akhtar,
linux-arm-kernel
Hi, Alim.
On 01/14/2015 07:30 PM, Alim Akhtar wrote:
> This adds HS400 mode support for exynos dw_mmc host controller.
>
> Currently tested on Exynos5800-peach-pi platform for HS400 mode.
> Tested HS200 mode with this series applied, HS200 still works.
>
> Appreciate testing on other exynos5/7 platform which supports emmc5.0
I will test this patch on exynos5/7 board.
Best Regards,
Jaehoon Chung
>
> Changes in V4:
> * drop the idea of changing existing binding for ciu_div as per [1]
> * addressed comments from Jaehoon Chung [2]
>
> [1] http://www.spinics.net/lists/linux-samsung-soc/msg40923.html
> [2] http://www.spinics.net/lists/devicetree/msg64373.html
>
> Changes in V3:
> rebased on ulf's next (commit: 607b448 mmc: core: Make tuning block patterns static)
>
> Seungwon Jeon (2):
> mmc: dw_mmc: exynos: Support eMMC's HS400 mode
> ARM: dts: Add HS400 support for exynos5420 and exynos5800
>
> .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +-
> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +
> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +-
> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +-
> drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
> drivers/mmc/host/dw_mmc-exynos.h | 19 +-
> drivers/mmc/host/dw_mmc.c | 16 +-
> drivers/mmc/host/dw_mmc.h | 2 +
> 9 files changed, 212 insertions(+), 38 deletions(-)
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support
@ 2015-01-14 13:32 ` Jaehoon Chung
0 siblings, 0 replies; 24+ messages in thread
From: Jaehoon Chung @ 2015-01-14 13:32 UTC (permalink / raw)
To: linux-arm-kernel
Hi, Alim.
On 01/14/2015 07:30 PM, Alim Akhtar wrote:
> This adds HS400 mode support for exynos dw_mmc host controller.
>
> Currently tested on Exynos5800-peach-pi platform for HS400 mode.
> Tested HS200 mode with this series applied, HS200 still works.
>
> Appreciate testing on other exynos5/7 platform which supports emmc5.0
I will test this patch on exynos5/7 board.
Best Regards,
Jaehoon Chung
>
> Changes in V4:
> * drop the idea of changing existing binding for ciu_div as per [1]
> * addressed comments from Jaehoon Chung [2]
>
> [1] http://www.spinics.net/lists/linux-samsung-soc/msg40923.html
> [2] http://www.spinics.net/lists/devicetree/msg64373.html
>
> Changes in V3:
> rebased on ulf's next (commit: 607b448 mmc: core: Make tuning block patterns static)
>
> Seungwon Jeon (2):
> mmc: dw_mmc: exynos: Support eMMC's HS400 mode
> ARM: dts: Add HS400 support for exynos5420 and exynos5800
>
> .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +-
> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +
> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +-
> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +-
> drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
> drivers/mmc/host/dw_mmc-exynos.h | 19 +-
> drivers/mmc/host/dw_mmc.c | 16 +-
> drivers/mmc/host/dw_mmc.h | 2 +
> 9 files changed, 212 insertions(+), 38 deletions(-)
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support
2015-01-14 13:32 ` Jaehoon Chung
@ 2015-01-14 15:35 ` Kukjin Kim
-1 siblings, 0 replies; 24+ messages in thread
From: Kukjin Kim @ 2015-01-14 15:35 UTC (permalink / raw)
To: Jaehoon Chung
Cc: Alim Akhtar, linux-mmc, devicetree, ulf.hansson,
linux-samsung-soc, tgih.jun, chris, dianders, kgene, a.kesavan,
alim.akhtar, linux-arm-kernel
On 01/14/15 22:32, Jaehoon Chung wrote:
> Hi, Alim.
>
> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>> This adds HS400 mode support for exynos dw_mmc host controller.
>>
>> Currently tested on Exynos5800-peach-pi platform for HS400 mode.
>> Tested HS200 mode with this series applied, HS200 still works.
>>
>> Appreciate testing on other exynos5/7 platform which supports emmc5.0
>
> I will test this patch on exynos5/7 board.
>
What's the result? :-) If it's OK, I'll take DT changes for exynos
stuff, I'm not sure about the driver changes though...
Thanks,
Kukjin
> Best Regards,
> Jaehoon Chung
>>
>> Changes in V4:
>> * drop the idea of changing existing binding for ciu_div as per [1]
>> * addressed comments from Jaehoon Chung [2]
>>
>> [1] http://www.spinics.net/lists/linux-samsung-soc/msg40923.html
>> [2] http://www.spinics.net/lists/devicetree/msg64373.html
>>
>> Changes in V3:
>> rebased on ulf's next (commit: 607b448 mmc: core: Make tuning block patterns static)
>>
>> Seungwon Jeon (2):
>> mmc: dw_mmc: exynos: Support eMMC's HS400 mode
>> ARM: dts: Add HS400 support for exynos5420 and exynos5800
>>
>> .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
>> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +-
>> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +
>> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +-
>> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +-
>> drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
>> drivers/mmc/host/dw_mmc-exynos.h | 19 +-
>> drivers/mmc/host/dw_mmc.c | 16 +-
>> drivers/mmc/host/dw_mmc.h | 2 +
>> 9 files changed, 212 insertions(+), 38 deletions(-)
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support
@ 2015-01-14 15:35 ` Kukjin Kim
0 siblings, 0 replies; 24+ messages in thread
From: Kukjin Kim @ 2015-01-14 15:35 UTC (permalink / raw)
To: linux-arm-kernel
On 01/14/15 22:32, Jaehoon Chung wrote:
> Hi, Alim.
>
> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>> This adds HS400 mode support for exynos dw_mmc host controller.
>>
>> Currently tested on Exynos5800-peach-pi platform for HS400 mode.
>> Tested HS200 mode with this series applied, HS200 still works.
>>
>> Appreciate testing on other exynos5/7 platform which supports emmc5.0
>
> I will test this patch on exynos5/7 board.
>
What's the result? :-) If it's OK, I'll take DT changes for exynos
stuff, I'm not sure about the driver changes though...
Thanks,
Kukjin
> Best Regards,
> Jaehoon Chung
>>
>> Changes in V4:
>> * drop the idea of changing existing binding for ciu_div as per [1]
>> * addressed comments from Jaehoon Chung [2]
>>
>> [1] http://www.spinics.net/lists/linux-samsung-soc/msg40923.html
>> [2] http://www.spinics.net/lists/devicetree/msg64373.html
>>
>> Changes in V3:
>> rebased on ulf's next (commit: 607b448 mmc: core: Make tuning block patterns static)
>>
>> Seungwon Jeon (2):
>> mmc: dw_mmc: exynos: Support eMMC's HS400 mode
>> ARM: dts: Add HS400 support for exynos5420 and exynos5800
>>
>> .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
>> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +-
>> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +
>> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +-
>> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +-
>> drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
>> drivers/mmc/host/dw_mmc-exynos.h | 19 +-
>> drivers/mmc/host/dw_mmc.c | 16 +-
>> drivers/mmc/host/dw_mmc.h | 2 +
>> 9 files changed, 212 insertions(+), 38 deletions(-)
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support
2015-01-14 15:35 ` Kukjin Kim
@ 2015-01-14 15:56 ` Ulf Hansson
-1 siblings, 0 replies; 24+ messages in thread
From: Ulf Hansson @ 2015-01-14 15:56 UTC (permalink / raw)
To: Kukjin Kim
Cc: Jaehoon Chung, Alim Akhtar, linux-mmc, devicetree,
linux-samsung-soc, tgih.jun, Chris Ball, Doug Anderson,
ABHILASH KESAVAN, Alim Akhtar, linux-arm-kernel
On 14 January 2015 at 16:35, Kukjin Kim <kgene@kernel.org> wrote:
> On 01/14/15 22:32, Jaehoon Chung wrote:
>> Hi, Alim.
>>
>> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>>> This adds HS400 mode support for exynos dw_mmc host controller.
>>>
>>> Currently tested on Exynos5800-peach-pi platform for HS400 mode.
>>> Tested HS200 mode with this series applied, HS200 still works.
>>>
>>> Appreciate testing on other exynos5/7 platform which supports emmc5.0
>>
>> I will test this patch on exynos5/7 board.
>>
>
> What's the result? :-) If it's OK, I'll take DT changes for exynos
> stuff, I'm not sure about the driver changes though...
Kukjin,
As I understand it, there is a dependency between the patches, since
driver adds supports for new DT bindings.
So, unless I am mistaken I think it would be best to take this
complete patchset through my mmc tree. With your ack of course.
Kind regards
Uffe
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support
@ 2015-01-14 15:56 ` Ulf Hansson
0 siblings, 0 replies; 24+ messages in thread
From: Ulf Hansson @ 2015-01-14 15:56 UTC (permalink / raw)
To: linux-arm-kernel
On 14 January 2015 at 16:35, Kukjin Kim <kgene@kernel.org> wrote:
> On 01/14/15 22:32, Jaehoon Chung wrote:
>> Hi, Alim.
>>
>> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>>> This adds HS400 mode support for exynos dw_mmc host controller.
>>>
>>> Currently tested on Exynos5800-peach-pi platform for HS400 mode.
>>> Tested HS200 mode with this series applied, HS200 still works.
>>>
>>> Appreciate testing on other exynos5/7 platform which supports emmc5.0
>>
>> I will test this patch on exynos5/7 board.
>>
>
> What's the result? :-) If it's OK, I'll take DT changes for exynos
> stuff, I'm not sure about the driver changes though...
Kukjin,
As I understand it, there is a dependency between the patches, since
driver adds supports for new DT bindings.
So, unless I am mistaken I think it would be best to take this
complete patchset through my mmc tree. With your ack of course.
Kind regards
Uffe
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 1/2] mmc: dw_mmc: exynos: Support eMMC's HS400 mode
2015-01-14 10:30 ` Alim Akhtar
@ 2015-01-20 23:02 ` Jaehoon Chung
-1 siblings, 0 replies; 24+ messages in thread
From: Jaehoon Chung @ 2015-01-20 23:02 UTC (permalink / raw)
To: Alim Akhtar, linux-mmc
Cc: chris, ulf.hansson, tgih.jun, dianders, alim.akhtar, kgene,
linux-arm-kernel, devicetree, linux-samsung-soc, a.kesavan
Hi,
This patch can be separated.
When i tested on my board, it's not working fine.
I think it depends on my timing, so i will check after change the timing.
On 01/14/2015 07:30 PM, Alim Akhtar wrote:
> From: Seungwon Jeon <tgih.jun@samsung.com>
>
> Implements HS400 mode support for exynos host driver.
> This also include some updates as new mode is added.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
> [Alim: addressed review comments]
> ---
> .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
> drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
> drivers/mmc/host/dw_mmc-exynos.h | 19 +-
> drivers/mmc/host/dw_mmc.c | 16 +-
> drivers/mmc/host/dw_mmc.h | 2 +
> 5 files changed, 196 insertions(+), 35 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
> index ee4fc05..dcab52c 100644
> --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
> +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
> @@ -36,6 +36,8 @@ Required Properties:
> in transmit mode and CIU clock phase shift value in receive mode for double
> data rate mode operation. Refer notes below for the order of the cells and the
> valid values.
> +* samsung,dw-mshc-hs400-timing: Specifies the value of CIU TX and RX clock phase
> + shift value for hs400 mode operation.
>
> Notes for the sdr-timing and ddr-timing values:
>
> @@ -50,6 +52,9 @@ Required Properties:
> - if CIU clock divider value is 0 (that is divide by 1), both tx and rx
> phase shift clocks should be 0.
>
> +* read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode
> + (Latency value for delay line in Read path)
> +
> Required properties for a slot (Deprecated - Recommend to use one slot per host):
>
> * gpios: specifies a list of gpios used for command, clock and data bus. The
> @@ -82,5 +87,7 @@ Example:
> samsung,dw-mshc-ciu-div = <3>;
> samsung,dw-mshc-sdr-timing = <2 3>;
> samsung,dw-mshc-ddr-timing = <1 2>;
> + samsung,dw-mshc-hs400-timing = <0 2>;
> + read-strobe-delay = <90>;
read-strobe-delay is exynos specific, isn't?
read-strobe-delay -> samsung.read-strobe-delay.
> bus-width = <8>;
> };
> diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
> index 12a5eaa..172a2a8 100644
> --- a/drivers/mmc/host/dw_mmc-exynos.c
> +++ b/drivers/mmc/host/dw_mmc-exynos.c
> @@ -40,7 +40,12 @@ struct dw_mci_exynos_priv_data {
> u8 ciu_div;
> u32 sdr_timing;
> u32 ddr_timing;
> + u32 hs400_timing;
> + u32 tuned_sample;
> u32 cur_speed;
> + u32 dqs_delay;
> + u32 saved_dqs_en;
> + u32 saved_strobe_ctrl;
> };
>
> static struct dw_mci_exynos_compatible {
> @@ -71,6 +76,21 @@ static struct dw_mci_exynos_compatible {
> },
> };
>
> +static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> +
> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
> + return EXYNOS4412_FIXED_CIU_CLK_DIV;
> + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
> + return EXYNOS4210_FIXED_CIU_CLK_DIV;
> + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
> + else
> + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1;
> +}
> +
> static int dw_mci_exynos_priv_init(struct dw_mci *host)
> {
> struct dw_mci_exynos_priv_data *priv = host->priv;
> @@ -85,6 +105,16 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
> SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT);
> }
>
> + if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) {
> + priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL);
> + priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN);
> + priv->saved_dqs_en |= AXI_NON_BLOCKING_WR;
> + mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en);
> + if (!priv->dqs_delay)
> + priv->dqs_delay =
> + DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
> + }
> +
> return 0;
> }
>
> @@ -92,11 +122,31 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
> {
> struct dw_mci_exynos_priv_data *priv = host->priv;
>
> - host->bus_hz /= (priv->ciu_div + 1);
> + host->bus_hz /= priv->ciu_div;
Don't need to consider the case that priv->ciu_div set to 0?
>
> return 0;
> }
>
> +static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> + u32 clksel;
> +
> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> + clksel = mci_readl(host, CLKSEL64);
> + else
> + clksel = mci_readl(host, CLKSEL);
> +
> + clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing;
> +
> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> + mci_writel(host, CLKSEL64, clksel);
> + else
> + mci_writel(host, CLKSEL, clksel);
> +}
> +
> #ifdef CONFIG_PM_SLEEP
> static int dw_mci_exynos_suspend(struct device *dev)
> {
> @@ -172,30 +222,38 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
> }
> }
>
> -static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
> {
> struct dw_mci_exynos_priv_data *priv = host->priv;
> - unsigned int wanted = ios->clock;
> - unsigned long actual;
> - u8 div = priv->ciu_div + 1;
> + u32 dqs, strobe;
>
> - if (ios->timing == MMC_TIMING_MMC_DDR52) {
> - if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> - priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> - mci_writel(host, CLKSEL64, priv->ddr_timing);
> - else
> - mci_writel(host, CLKSEL, priv->ddr_timing);
> - /* Should be double rate for DDR mode */
> - if (ios->bus_width == MMC_BUS_WIDTH_8)
> - wanted <<= 1;
> + /*
> + * Not suppported to configure register
Typo..supported
> + * related to HS400
> + */
> + if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420)
> + return;
> +
> + dqs = priv->saved_dqs_en;
> + strobe = priv->saved_strobe_ctrl;
priv->saved_dqs_en is set at init-time.
And you read the RDDQS_EN and HS400_DLINE_CTRL register at that time.
Doesn't it need to consider the changed value at those register?
priv->saved_xxx is reset value?
> +
> + if (timing == MMC_TIMING_MMC_HS400) {
> + dqs |= DATA_STROBE_EN;
> + strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay);
> } else {
> - if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> - priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> - mci_writel(host, CLKSEL64, priv->sdr_timing);
> - else
> - mci_writel(host, CLKSEL, priv->sdr_timing);
> + dqs &= ~DATA_STROBE_EN;
> }
>
> + mci_writel(host, HS400_DQS_EN, dqs);
> + mci_writel(host, HS400_DLINE_CTRL, strobe);
> +}
> +
> +static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> + unsigned long actual;
> + u8 div;
> + int ret;
> /*
> * Don't care if wanted clock is zero or
> * ciu clock is unavailable
> @@ -207,17 +265,52 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> if (wanted < EXYNOS_CCLKIN_MIN)
> wanted = EXYNOS_CCLKIN_MIN;
>
> - if (wanted != priv->cur_speed) {
> - int ret = clk_set_rate(host->ciu_clk, wanted * div);
> - if (ret)
> - dev_warn(host->dev,
> - "failed to set clk-rate %u error: %d\n",
> - wanted * div, ret);
> - actual = clk_get_rate(host->ciu_clk);
> - host->bus_hz = actual / div;
> - priv->cur_speed = wanted;
> - host->current_speed = 0;
> + if (wanted == priv->cur_speed)
> + return;
> +
> + div = dw_mci_exynos_get_ciu_div(host);
> + ret = clk_set_rate(host->ciu_clk, wanted * div);
> + if (ret)
> + dev_warn(host->dev,
> + "failed to set clk-rate %u error: %d\n",
> + wanted * div, ret);
> + actual = clk_get_rate(host->ciu_clk);
> + host->bus_hz = actual / div;
> + priv->cur_speed = wanted;
> + host->current_speed = 0;
> +}
> +
> +static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> + unsigned int wanted = ios->clock;
> + u32 timing = ios->timing, clksel;
> +
> + switch (timing) {
> + case MMC_TIMING_MMC_HS400:
> + /* Update tuned sample timing */
> + clksel = SDMMC_CLKSEL_UP_SAMPLE(
> + priv->hs400_timing, priv->tuned_sample);
> + wanted <<= 1;
> + break;
> + case MMC_TIMING_MMC_DDR52:
> + clksel = priv->ddr_timing;
> + /* Should be double rate for DDR mode */
> + if (ios->bus_width == MMC_BUS_WIDTH_8)
> + wanted <<= 1;
> + break;
> + default:
> + clksel = priv->sdr_timing;
> }
> +
> + /* Set clock timing for the requested speed mode*/
> + dw_mci_exynos_set_clksel_timing(host, clksel);
> +
> + /* Configure setting for HS400 */
> + dw_mci_exynos_config_hs400(host, timing);
> +
> + /* Configure clock rate */
> + dw_mci_exynos_adjust_clock(host, wanted);
> }
>
> static int dw_mci_exynos_parse_dt(struct dw_mci *host)
> @@ -260,6 +353,16 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host)
> return ret;
>
> priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
> +
> + ret = of_property_read_u32_array(np,
> + "samsung,dw-mshc-hs400-timing", timing, 2);
> + if (!ret && of_property_read_u32(np,
> + "read-strobe-delay", &priv->dqs_delay))
> + dev_info(host->dev,
> + "read-strobe-delay is not found, assuming usage of default value\n");
Need the message?
> +
> + priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1],
> + HS400_FIXED_CIU_CLK_DIV);
Why useed the HS400_FIXED_CIU_CLK_DIV? always set to 1?
Best Regards,
Jaehoon Chung
> host->priv = priv;
> return 0;
> }
> @@ -285,7 +388,7 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
> clksel = mci_readl(host, CLKSEL64);
> else
> clksel = mci_readl(host, CLKSEL);
> - clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample);
> + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
> if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> mci_writel(host, CLKSEL64, clksel);
> @@ -304,13 +407,16 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
> clksel = mci_readl(host, CLKSEL64);
> else
> clksel = mci_readl(host, CLKSEL);
> +
> sample = (clksel + 1) & 0x7;
> - clksel = (clksel & ~0x7) | sample;
> + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
> +
> if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> mci_writel(host, CLKSEL64, clksel);
> else
> mci_writel(host, CLKSEL, clksel);
> +
> return sample;
> }
>
> @@ -343,6 +449,7 @@ out:
> static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
> {
> struct dw_mci *host = slot->host;
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> struct mmc_host *mmc = slot->mmc;
> u8 start_smpl, smpl, candiates = 0;
> s8 found = -1;
> @@ -360,14 +467,27 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
> } while (start_smpl != smpl);
>
> found = dw_mci_exynos_get_best_clksmpl(candiates);
> - if (found >= 0)
> + if (found >= 0) {
> dw_mci_exynos_set_clksmpl(host, found);
> - else
> + priv->tuned_sample = found;
> + } else {
> ret = -EIO;
> + }
>
> return ret;
> }
>
> +int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
> + struct mmc_ios *ios)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> +
> + dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing);
> + dw_mci_exynos_adjust_clock(host, (ios->clock) << 1);
> +
> + return 0;
> +}
> +
> /* Common capabilities of Exynos4/Exynos5 SoC */
> static unsigned long exynos_dwmmc_caps[4] = {
> MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
> @@ -384,6 +504,7 @@ static const struct dw_mci_drv_data exynos_drv_data = {
> .set_ios = dw_mci_exynos_set_ios,
> .parse_dt = dw_mci_exynos_parse_dt,
> .execute_tuning = dw_mci_exynos_execute_tuning,
> + .prepare_hs400_tuning = dw_mci_exynos_prepare_hs400_tuning,
> };
>
> static const struct of_device_id dw_mci_exynos_match[] = {
> diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h
> index 7872ce5..595c934 100644
> --- a/drivers/mmc/host/dw_mmc-exynos.h
> +++ b/drivers/mmc/host/dw_mmc-exynos.h
> @@ -12,20 +12,36 @@
> #ifndef _DW_MMC_EXYNOS_H_
> #define _DW_MMC_EXYNOS_H_
>
> -/* Extended Register's Offset */
> #define SDMMC_CLKSEL 0x09C
> #define SDMMC_CLKSEL64 0x0A8
>
> +/* Extended Register's Offset */
> +#define SDMMC_HS400_DQS_EN 0x180
> +#define SDMMC_HS400_ASYNC_FIFO_CTRL 0x184
> +#define SDMMC_HS400_DLINE_CTRL 0x188
> +
> /* CLKSEL register defines */
> #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0)
> #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16)
> #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24)
> #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7)
> +#define SDMMC_CLKSEL_GET_DIV(x) (((x) >> 24) & 0x7)
> +#define SDMMC_CLKSEL_UP_SAMPLE(x, y) (((x) & ~SDMMC_CLKSEL_CCLK_SAMPLE(7)) |\
> + SDMMC_CLKSEL_CCLK_SAMPLE(y))
> #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \
> SDMMC_CLKSEL_CCLK_DRIVE(y) | \
> SDMMC_CLKSEL_CCLK_DIVIDER(z))
> +#define SDMMC_CLKSEL_TIMING_MASK SDMMC_CLKSEL_TIMING(0x7, 0x7, 0x7)
> #define SDMMC_CLKSEL_WAKEUP_INT BIT(11)
>
> +/* RCLK_EN register defines */
> +#define DATA_STROBE_EN BIT(0)
> +#define AXI_NON_BLOCKING_WR BIT(7)
> +
> +/* DLINE_CTRL register defines */
> +#define DQS_CTRL_RD_DELAY(x, y) (((x) & ~0x3FF) | ((y) & 0x3FF))
> +#define DQS_CTRL_GET_RD_DELAY(x) ((x) & 0x3FF)
> +
> /* Protector Register */
> #define SDMMC_EMMCP_BASE 0x1000
> #define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010)
> @@ -49,6 +65,7 @@
> /* Fixed clock divider */
> #define EXYNOS4210_FIXED_CIU_CLK_DIV 2
> #define EXYNOS4412_FIXED_CIU_CLK_DIV 4
> +#define HS400_FIXED_CIU_CLK_DIV 1
>
> /* Minimal required clock frequency for cclkin, unit: HZ */
> #define EXYNOS_CCLKIN_MIN 50000000
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 2e8abc8..43a3a5b 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1084,7 +1084,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> regs = mci_readl(slot->host, UHS_REG);
>
> /* DDR mode set */
> - if (ios->timing == MMC_TIMING_MMC_DDR52)
> + if (ios->timing == MMC_TIMING_MMC_DDR52 ||
> + ios->timing == MMC_TIMING_MMC_HS400)
> regs |= ((0x1 << slot->id) << 16);
> else
> regs &= ~((0x1 << slot->id) << 16);
> @@ -1321,6 +1322,18 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
> return err;
> }
>
> +int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> + struct dw_mci_slot *slot = mmc_priv(mmc);
> + struct dw_mci *host = slot->host;
> + const struct dw_mci_drv_data *drv_data = host->drv_data;
> +
> + if (drv_data && drv_data->prepare_hs400_tuning)
> + return drv_data->prepare_hs400_tuning(host, ios);
> +
> + return 0;
> +}
> +
> static const struct mmc_host_ops dw_mci_ops = {
> .request = dw_mci_request,
> .pre_req = dw_mci_pre_req,
> @@ -1333,6 +1346,7 @@ static const struct mmc_host_ops dw_mci_ops = {
> .card_busy = dw_mci_card_busy,
> .start_signal_voltage_switch = dw_mci_switch_voltage,
> .init_card = dw_mci_init_card,
> + .prepare_hs400_tuning = dw_mci_prepare_hs400_tuning,
> };
>
> static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index 18c4afe..d239867 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -271,5 +271,7 @@ struct dw_mci_drv_data {
> void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
> int (*parse_dt)(struct dw_mci *host);
> int (*execute_tuning)(struct dw_mci_slot *slot);
> + int (*prepare_hs400_tuning)(struct dw_mci *host,
> + struct mmc_ios *ios);
> };
> #endif /* _DW_MMC_H_ */
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 1/2] mmc: dw_mmc: exynos: Support eMMC's HS400 mode
@ 2015-01-20 23:02 ` Jaehoon Chung
0 siblings, 0 replies; 24+ messages in thread
From: Jaehoon Chung @ 2015-01-20 23:02 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This patch can be separated.
When i tested on my board, it's not working fine.
I think it depends on my timing, so i will check after change the timing.
On 01/14/2015 07:30 PM, Alim Akhtar wrote:
> From: Seungwon Jeon <tgih.jun@samsung.com>
>
> Implements HS400 mode support for exynos host driver.
> This also include some updates as new mode is added.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
> [Alim: addressed review comments]
> ---
> .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
> drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
> drivers/mmc/host/dw_mmc-exynos.h | 19 +-
> drivers/mmc/host/dw_mmc.c | 16 +-
> drivers/mmc/host/dw_mmc.h | 2 +
> 5 files changed, 196 insertions(+), 35 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
> index ee4fc05..dcab52c 100644
> --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
> +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
> @@ -36,6 +36,8 @@ Required Properties:
> in transmit mode and CIU clock phase shift value in receive mode for double
> data rate mode operation. Refer notes below for the order of the cells and the
> valid values.
> +* samsung,dw-mshc-hs400-timing: Specifies the value of CIU TX and RX clock phase
> + shift value for hs400 mode operation.
>
> Notes for the sdr-timing and ddr-timing values:
>
> @@ -50,6 +52,9 @@ Required Properties:
> - if CIU clock divider value is 0 (that is divide by 1), both tx and rx
> phase shift clocks should be 0.
>
> +* read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode
> + (Latency value for delay line in Read path)
> +
> Required properties for a slot (Deprecated - Recommend to use one slot per host):
>
> * gpios: specifies a list of gpios used for command, clock and data bus. The
> @@ -82,5 +87,7 @@ Example:
> samsung,dw-mshc-ciu-div = <3>;
> samsung,dw-mshc-sdr-timing = <2 3>;
> samsung,dw-mshc-ddr-timing = <1 2>;
> + samsung,dw-mshc-hs400-timing = <0 2>;
> + read-strobe-delay = <90>;
read-strobe-delay is exynos specific, isn't?
read-strobe-delay -> samsung.read-strobe-delay.
> bus-width = <8>;
> };
> diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
> index 12a5eaa..172a2a8 100644
> --- a/drivers/mmc/host/dw_mmc-exynos.c
> +++ b/drivers/mmc/host/dw_mmc-exynos.c
> @@ -40,7 +40,12 @@ struct dw_mci_exynos_priv_data {
> u8 ciu_div;
> u32 sdr_timing;
> u32 ddr_timing;
> + u32 hs400_timing;
> + u32 tuned_sample;
> u32 cur_speed;
> + u32 dqs_delay;
> + u32 saved_dqs_en;
> + u32 saved_strobe_ctrl;
> };
>
> static struct dw_mci_exynos_compatible {
> @@ -71,6 +76,21 @@ static struct dw_mci_exynos_compatible {
> },
> };
>
> +static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> +
> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
> + return EXYNOS4412_FIXED_CIU_CLK_DIV;
> + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
> + return EXYNOS4210_FIXED_CIU_CLK_DIV;
> + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
> + else
> + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1;
> +}
> +
> static int dw_mci_exynos_priv_init(struct dw_mci *host)
> {
> struct dw_mci_exynos_priv_data *priv = host->priv;
> @@ -85,6 +105,16 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
> SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT);
> }
>
> + if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) {
> + priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL);
> + priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN);
> + priv->saved_dqs_en |= AXI_NON_BLOCKING_WR;
> + mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en);
> + if (!priv->dqs_delay)
> + priv->dqs_delay =
> + DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
> + }
> +
> return 0;
> }
>
> @@ -92,11 +122,31 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
> {
> struct dw_mci_exynos_priv_data *priv = host->priv;
>
> - host->bus_hz /= (priv->ciu_div + 1);
> + host->bus_hz /= priv->ciu_div;
Don't need to consider the case that priv->ciu_div set to 0?
>
> return 0;
> }
>
> +static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> + u32 clksel;
> +
> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> + clksel = mci_readl(host, CLKSEL64);
> + else
> + clksel = mci_readl(host, CLKSEL);
> +
> + clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing;
> +
> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> + mci_writel(host, CLKSEL64, clksel);
> + else
> + mci_writel(host, CLKSEL, clksel);
> +}
> +
> #ifdef CONFIG_PM_SLEEP
> static int dw_mci_exynos_suspend(struct device *dev)
> {
> @@ -172,30 +222,38 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
> }
> }
>
> -static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
> {
> struct dw_mci_exynos_priv_data *priv = host->priv;
> - unsigned int wanted = ios->clock;
> - unsigned long actual;
> - u8 div = priv->ciu_div + 1;
> + u32 dqs, strobe;
>
> - if (ios->timing == MMC_TIMING_MMC_DDR52) {
> - if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> - priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> - mci_writel(host, CLKSEL64, priv->ddr_timing);
> - else
> - mci_writel(host, CLKSEL, priv->ddr_timing);
> - /* Should be double rate for DDR mode */
> - if (ios->bus_width == MMC_BUS_WIDTH_8)
> - wanted <<= 1;
> + /*
> + * Not suppported to configure register
Typo..supported
> + * related to HS400
> + */
> + if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420)
> + return;
> +
> + dqs = priv->saved_dqs_en;
> + strobe = priv->saved_strobe_ctrl;
priv->saved_dqs_en is set at init-time.
And you read the RDDQS_EN and HS400_DLINE_CTRL register at that time.
Doesn't it need to consider the changed value at those register?
priv->saved_xxx is reset value?
> +
> + if (timing == MMC_TIMING_MMC_HS400) {
> + dqs |= DATA_STROBE_EN;
> + strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay);
> } else {
> - if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> - priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> - mci_writel(host, CLKSEL64, priv->sdr_timing);
> - else
> - mci_writel(host, CLKSEL, priv->sdr_timing);
> + dqs &= ~DATA_STROBE_EN;
> }
>
> + mci_writel(host, HS400_DQS_EN, dqs);
> + mci_writel(host, HS400_DLINE_CTRL, strobe);
> +}
> +
> +static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> + unsigned long actual;
> + u8 div;
> + int ret;
> /*
> * Don't care if wanted clock is zero or
> * ciu clock is unavailable
> @@ -207,17 +265,52 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> if (wanted < EXYNOS_CCLKIN_MIN)
> wanted = EXYNOS_CCLKIN_MIN;
>
> - if (wanted != priv->cur_speed) {
> - int ret = clk_set_rate(host->ciu_clk, wanted * div);
> - if (ret)
> - dev_warn(host->dev,
> - "failed to set clk-rate %u error: %d\n",
> - wanted * div, ret);
> - actual = clk_get_rate(host->ciu_clk);
> - host->bus_hz = actual / div;
> - priv->cur_speed = wanted;
> - host->current_speed = 0;
> + if (wanted == priv->cur_speed)
> + return;
> +
> + div = dw_mci_exynos_get_ciu_div(host);
> + ret = clk_set_rate(host->ciu_clk, wanted * div);
> + if (ret)
> + dev_warn(host->dev,
> + "failed to set clk-rate %u error: %d\n",
> + wanted * div, ret);
> + actual = clk_get_rate(host->ciu_clk);
> + host->bus_hz = actual / div;
> + priv->cur_speed = wanted;
> + host->current_speed = 0;
> +}
> +
> +static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> + unsigned int wanted = ios->clock;
> + u32 timing = ios->timing, clksel;
> +
> + switch (timing) {
> + case MMC_TIMING_MMC_HS400:
> + /* Update tuned sample timing */
> + clksel = SDMMC_CLKSEL_UP_SAMPLE(
> + priv->hs400_timing, priv->tuned_sample);
> + wanted <<= 1;
> + break;
> + case MMC_TIMING_MMC_DDR52:
> + clksel = priv->ddr_timing;
> + /* Should be double rate for DDR mode */
> + if (ios->bus_width == MMC_BUS_WIDTH_8)
> + wanted <<= 1;
> + break;
> + default:
> + clksel = priv->sdr_timing;
> }
> +
> + /* Set clock timing for the requested speed mode*/
> + dw_mci_exynos_set_clksel_timing(host, clksel);
> +
> + /* Configure setting for HS400 */
> + dw_mci_exynos_config_hs400(host, timing);
> +
> + /* Configure clock rate */
> + dw_mci_exynos_adjust_clock(host, wanted);
> }
>
> static int dw_mci_exynos_parse_dt(struct dw_mci *host)
> @@ -260,6 +353,16 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host)
> return ret;
>
> priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
> +
> + ret = of_property_read_u32_array(np,
> + "samsung,dw-mshc-hs400-timing", timing, 2);
> + if (!ret && of_property_read_u32(np,
> + "read-strobe-delay", &priv->dqs_delay))
> + dev_info(host->dev,
> + "read-strobe-delay is not found, assuming usage of default value\n");
Need the message?
> +
> + priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1],
> + HS400_FIXED_CIU_CLK_DIV);
Why useed the HS400_FIXED_CIU_CLK_DIV? always set to 1?
Best Regards,
Jaehoon Chung
> host->priv = priv;
> return 0;
> }
> @@ -285,7 +388,7 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
> clksel = mci_readl(host, CLKSEL64);
> else
> clksel = mci_readl(host, CLKSEL);
> - clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample);
> + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
> if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> mci_writel(host, CLKSEL64, clksel);
> @@ -304,13 +407,16 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
> clksel = mci_readl(host, CLKSEL64);
> else
> clksel = mci_readl(host, CLKSEL);
> +
> sample = (clksel + 1) & 0x7;
> - clksel = (clksel & ~0x7) | sample;
> + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
> +
> if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
> priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
> mci_writel(host, CLKSEL64, clksel);
> else
> mci_writel(host, CLKSEL, clksel);
> +
> return sample;
> }
>
> @@ -343,6 +449,7 @@ out:
> static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
> {
> struct dw_mci *host = slot->host;
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> struct mmc_host *mmc = slot->mmc;
> u8 start_smpl, smpl, candiates = 0;
> s8 found = -1;
> @@ -360,14 +467,27 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
> } while (start_smpl != smpl);
>
> found = dw_mci_exynos_get_best_clksmpl(candiates);
> - if (found >= 0)
> + if (found >= 0) {
> dw_mci_exynos_set_clksmpl(host, found);
> - else
> + priv->tuned_sample = found;
> + } else {
> ret = -EIO;
> + }
>
> return ret;
> }
>
> +int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
> + struct mmc_ios *ios)
> +{
> + struct dw_mci_exynos_priv_data *priv = host->priv;
> +
> + dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing);
> + dw_mci_exynos_adjust_clock(host, (ios->clock) << 1);
> +
> + return 0;
> +}
> +
> /* Common capabilities of Exynos4/Exynos5 SoC */
> static unsigned long exynos_dwmmc_caps[4] = {
> MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
> @@ -384,6 +504,7 @@ static const struct dw_mci_drv_data exynos_drv_data = {
> .set_ios = dw_mci_exynos_set_ios,
> .parse_dt = dw_mci_exynos_parse_dt,
> .execute_tuning = dw_mci_exynos_execute_tuning,
> + .prepare_hs400_tuning = dw_mci_exynos_prepare_hs400_tuning,
> };
>
> static const struct of_device_id dw_mci_exynos_match[] = {
> diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h
> index 7872ce5..595c934 100644
> --- a/drivers/mmc/host/dw_mmc-exynos.h
> +++ b/drivers/mmc/host/dw_mmc-exynos.h
> @@ -12,20 +12,36 @@
> #ifndef _DW_MMC_EXYNOS_H_
> #define _DW_MMC_EXYNOS_H_
>
> -/* Extended Register's Offset */
> #define SDMMC_CLKSEL 0x09C
> #define SDMMC_CLKSEL64 0x0A8
>
> +/* Extended Register's Offset */
> +#define SDMMC_HS400_DQS_EN 0x180
> +#define SDMMC_HS400_ASYNC_FIFO_CTRL 0x184
> +#define SDMMC_HS400_DLINE_CTRL 0x188
> +
> /* CLKSEL register defines */
> #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0)
> #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16)
> #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24)
> #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7)
> +#define SDMMC_CLKSEL_GET_DIV(x) (((x) >> 24) & 0x7)
> +#define SDMMC_CLKSEL_UP_SAMPLE(x, y) (((x) & ~SDMMC_CLKSEL_CCLK_SAMPLE(7)) |\
> + SDMMC_CLKSEL_CCLK_SAMPLE(y))
> #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \
> SDMMC_CLKSEL_CCLK_DRIVE(y) | \
> SDMMC_CLKSEL_CCLK_DIVIDER(z))
> +#define SDMMC_CLKSEL_TIMING_MASK SDMMC_CLKSEL_TIMING(0x7, 0x7, 0x7)
> #define SDMMC_CLKSEL_WAKEUP_INT BIT(11)
>
> +/* RCLK_EN register defines */
> +#define DATA_STROBE_EN BIT(0)
> +#define AXI_NON_BLOCKING_WR BIT(7)
> +
> +/* DLINE_CTRL register defines */
> +#define DQS_CTRL_RD_DELAY(x, y) (((x) & ~0x3FF) | ((y) & 0x3FF))
> +#define DQS_CTRL_GET_RD_DELAY(x) ((x) & 0x3FF)
> +
> /* Protector Register */
> #define SDMMC_EMMCP_BASE 0x1000
> #define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010)
> @@ -49,6 +65,7 @@
> /* Fixed clock divider */
> #define EXYNOS4210_FIXED_CIU_CLK_DIV 2
> #define EXYNOS4412_FIXED_CIU_CLK_DIV 4
> +#define HS400_FIXED_CIU_CLK_DIV 1
>
> /* Minimal required clock frequency for cclkin, unit: HZ */
> #define EXYNOS_CCLKIN_MIN 50000000
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 2e8abc8..43a3a5b 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1084,7 +1084,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> regs = mci_readl(slot->host, UHS_REG);
>
> /* DDR mode set */
> - if (ios->timing == MMC_TIMING_MMC_DDR52)
> + if (ios->timing == MMC_TIMING_MMC_DDR52 ||
> + ios->timing == MMC_TIMING_MMC_HS400)
> regs |= ((0x1 << slot->id) << 16);
> else
> regs &= ~((0x1 << slot->id) << 16);
> @@ -1321,6 +1322,18 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
> return err;
> }
>
> +int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> + struct dw_mci_slot *slot = mmc_priv(mmc);
> + struct dw_mci *host = slot->host;
> + const struct dw_mci_drv_data *drv_data = host->drv_data;
> +
> + if (drv_data && drv_data->prepare_hs400_tuning)
> + return drv_data->prepare_hs400_tuning(host, ios);
> +
> + return 0;
> +}
> +
> static const struct mmc_host_ops dw_mci_ops = {
> .request = dw_mci_request,
> .pre_req = dw_mci_pre_req,
> @@ -1333,6 +1346,7 @@ static const struct mmc_host_ops dw_mci_ops = {
> .card_busy = dw_mci_card_busy,
> .start_signal_voltage_switch = dw_mci_switch_voltage,
> .init_card = dw_mci_init_card,
> + .prepare_hs400_tuning = dw_mci_prepare_hs400_tuning,
> };
>
> static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index 18c4afe..d239867 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -271,5 +271,7 @@ struct dw_mci_drv_data {
> void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
> int (*parse_dt)(struct dw_mci *host);
> int (*execute_tuning)(struct dw_mci_slot *slot);
> + int (*prepare_hs400_tuning)(struct dw_mci *host,
> + struct mmc_ios *ios);
> };
> #endif /* _DW_MMC_H_ */
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
2015-01-14 10:30 ` Alim Akhtar
@ 2015-01-20 23:02 ` Jaehoon Chung
-1 siblings, 0 replies; 24+ messages in thread
From: Jaehoon Chung @ 2015-01-20 23:02 UTC (permalink / raw)
To: Alim Akhtar, linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: chris-OsFVWbfNK3isTnJN9+BGXg, ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
tgih.jun-Sze3O3UU22JBDgjK7y7TUQ, dianders-F7+t8E8rja9g9hUCZPvPmw,
alim.akhtar-Re5JQEeQqe8AvxtiuMwx3w, kgene-DgEjT+Ai2ygdnm+yROfE0A,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
a.kesavan-Sze3O3UU22JBDgjK7y7TUQ
Hi,
If you want to enable the hs400 mode, need to add "mmc-hs400-1_8v" or "mmc-hs400-1_2v".
But this patch didn't add them. do you have any other plan?
On 01/14/2015 07:30 PM, Alim Akhtar wrote:
> From: Seungwon Jeon <tgih.jun-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>
> HS400 timing values are added for SMDK5420, exynos5420-peach-pit
> and exynos5800-peach-pi boards.
> This also adds RCLK GPIO line, this gpio should be in pull-down
> state.
>
> Signed-off-by: Seungwon Jeon <tgih.jun-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Signed-off-by: Alim Akhtar <alim.akhtar-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> [Alim: addressed review comments]
> ---
> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
> 4 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
> index 9a050e1..7ffaba8 100644
> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
> @@ -569,8 +569,10 @@
> samsung,dw-mshc-ciu-div = <3>;
> samsung,dw-mshc-sdr-timing = <0 4>;
> samsung,dw-mshc-ddr-timing = <0 2>;
> + samsung,dw-mshc-hs400-timing = <0 2>;
> + read-strobe-delay = <90>;
> pinctrl-names = "default";
> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
> bus-width = <8>;
> };
>
> diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
> index ba686e4..8b15316 100644
> --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
> +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
> @@ -201,6 +201,13 @@
> samsung,pin-drv = <3>;
> };
>
> + sd0_rclk: sd0-rclk {
I know it used to "sd0_rdqs", not "sd0_rclk".
Change name.
Best Regards,
Jaehoon Chung
> + samsung,pins = "gpc0-7";
> + samsung,pin-function = <2>;
> + samsung,pin-pud = <1>;
> + samsung,pin-drv = <3>;
> + };
> +
> sd1_cmd: sd1-cmd {
> samsung,pins = "gpc1-1";
> samsung,pin-function = <2>;
> diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
> index 8be3d7b..5290e79 100644
> --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
> +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
> @@ -80,8 +80,10 @@
> samsung,dw-mshc-ciu-div = <3>;
> samsung,dw-mshc-sdr-timing = <0 4>;
> samsung,dw-mshc-ddr-timing = <0 2>;
> + samsung,dw-mshc-hs400-timing = <0 2>;
> + read-strobe-delay = <90>;
> pinctrl-names = "default";
> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
> bus-width = <8>;
> cap-mmc-highspeed;
> };
> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
> index e8fdda8..fa1c858 100644
> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
> @@ -557,8 +557,10 @@
> samsung,dw-mshc-ciu-div = <3>;
> samsung,dw-mshc-sdr-timing = <0 4>;
> samsung,dw-mshc-ddr-timing = <0 2>;
> + samsung,dw-mshc-hs400-timing = <0 2>;
> + read-strobe-delay = <90>;
> pinctrl-names = "default";
> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
> bus-width = <8>;
> };
>
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
@ 2015-01-20 23:02 ` Jaehoon Chung
0 siblings, 0 replies; 24+ messages in thread
From: Jaehoon Chung @ 2015-01-20 23:02 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
If you want to enable the hs400 mode, need to add "mmc-hs400-1_8v" or "mmc-hs400-1_2v".
But this patch didn't add them. do you have any other plan?
On 01/14/2015 07:30 PM, Alim Akhtar wrote:
> From: Seungwon Jeon <tgih.jun@samsung.com>
>
> HS400 timing values are added for SMDK5420, exynos5420-peach-pit
> and exynos5800-peach-pi boards.
> This also adds RCLK GPIO line, this gpio should be in pull-down
> state.
>
> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
> [Alim: addressed review comments]
> ---
> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
> 4 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
> index 9a050e1..7ffaba8 100644
> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
> @@ -569,8 +569,10 @@
> samsung,dw-mshc-ciu-div = <3>;
> samsung,dw-mshc-sdr-timing = <0 4>;
> samsung,dw-mshc-ddr-timing = <0 2>;
> + samsung,dw-mshc-hs400-timing = <0 2>;
> + read-strobe-delay = <90>;
> pinctrl-names = "default";
> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
> bus-width = <8>;
> };
>
> diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
> index ba686e4..8b15316 100644
> --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
> +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
> @@ -201,6 +201,13 @@
> samsung,pin-drv = <3>;
> };
>
> + sd0_rclk: sd0-rclk {
I know it used to "sd0_rdqs", not "sd0_rclk".
Change name.
Best Regards,
Jaehoon Chung
> + samsung,pins = "gpc0-7";
> + samsung,pin-function = <2>;
> + samsung,pin-pud = <1>;
> + samsung,pin-drv = <3>;
> + };
> +
> sd1_cmd: sd1-cmd {
> samsung,pins = "gpc1-1";
> samsung,pin-function = <2>;
> diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
> index 8be3d7b..5290e79 100644
> --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
> +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
> @@ -80,8 +80,10 @@
> samsung,dw-mshc-ciu-div = <3>;
> samsung,dw-mshc-sdr-timing = <0 4>;
> samsung,dw-mshc-ddr-timing = <0 2>;
> + samsung,dw-mshc-hs400-timing = <0 2>;
> + read-strobe-delay = <90>;
> pinctrl-names = "default";
> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
> bus-width = <8>;
> cap-mmc-highspeed;
> };
> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
> index e8fdda8..fa1c858 100644
> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
> @@ -557,8 +557,10 @@
> samsung,dw-mshc-ciu-div = <3>;
> samsung,dw-mshc-sdr-timing = <0 4>;
> samsung,dw-mshc-ddr-timing = <0 2>;
> + samsung,dw-mshc-hs400-timing = <0 2>;
> + read-strobe-delay = <90>;
> pinctrl-names = "default";
> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
> bus-width = <8>;
> };
>
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
2015-01-20 23:02 ` Jaehoon Chung
@ 2015-01-21 14:12 ` Alim Akhtar
-1 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-21 14:12 UTC (permalink / raw)
To: Jaehoon Chung
Cc: Alim Akhtar, linux-mmc, Chris Ball, Ulf Hansson, Seungwon Jeon,
Douglas Anderson, kgene, linux-arm-kernel, devicetree,
linux-samsung-soc, Abhilash Kesavan
Hi Jaehoon
On Wed, Jan 21, 2015 at 4:32 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> Hi,
>
> If you want to enable the hs400 mode, need to add "mmc-hs400-1_8v" or "mmc-hs400-1_2v".
> But this patch didn't add them. do you have any other plan?
>
Yes, right, plan is to send separate patch to enable hs400, as of now
I am not sure if all the 5800-peach-pi boards are populated with
emmc5.0 device or not. So I will enable HS400 after confirming this
point.
> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>> From: Seungwon Jeon <tgih.jun@samsung.com>
>>
>> HS400 timing values are added for SMDK5420, exynos5420-peach-pit
>> and exynos5800-peach-pi boards.
>> This also adds RCLK GPIO line, this gpio should be in pull-down
>> state.
>>
>> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>> [Alim: addressed review comments]
>> ---
>> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
>> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
>> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
>> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
>> 4 files changed, 16 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>> index 9a050e1..7ffaba8 100644
>> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
>> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>> @@ -569,8 +569,10 @@
>> samsung,dw-mshc-ciu-div = <3>;
>> samsung,dw-mshc-sdr-timing = <0 4>;
>> samsung,dw-mshc-ddr-timing = <0 2>;
>> + samsung,dw-mshc-hs400-timing = <0 2>;
>> + read-strobe-delay = <90>;
>> pinctrl-names = "default";
>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>> bus-width = <8>;
>> };
>>
>> diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>> index ba686e4..8b15316 100644
>> --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>> +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>> @@ -201,6 +201,13 @@
>> samsung,pin-drv = <3>;
>> };
>>
>> + sd0_rclk: sd0-rclk {
>
> I know it used to "sd0_rdqs", not "sd0_rclk".
> Change name.
>
Ok, I will change as per UM of 5800/5420,
> Best Regards,
> Jaehoon Chung
>> + samsung,pins = "gpc0-7";
>> + samsung,pin-function = <2>;
>> + samsung,pin-pud = <1>;
>> + samsung,pin-drv = <3>;
>> + };
>> +
>> sd1_cmd: sd1-cmd {
>> samsung,pins = "gpc1-1";
>> samsung,pin-function = <2>;
>> diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>> index 8be3d7b..5290e79 100644
>> --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
>> +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>> @@ -80,8 +80,10 @@
>> samsung,dw-mshc-ciu-div = <3>;
>> samsung,dw-mshc-sdr-timing = <0 4>;
>> samsung,dw-mshc-ddr-timing = <0 2>;
>> + samsung,dw-mshc-hs400-timing = <0 2>;
>> + read-strobe-delay = <90>;
>> pinctrl-names = "default";
>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>> bus-width = <8>;
>> cap-mmc-highspeed;
>> };
>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> index e8fdda8..fa1c858 100644
>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> @@ -557,8 +557,10 @@
>> samsung,dw-mshc-ciu-div = <3>;
>> samsung,dw-mshc-sdr-timing = <0 4>;
>> samsung,dw-mshc-ddr-timing = <0 2>;
>> + samsung,dw-mshc-hs400-timing = <0 2>;
>> + read-strobe-delay = <90>;
>> pinctrl-names = "default";
>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>> bus-width = <8>;
>> };
>>
>>
>
--
Regards,
Alim
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
@ 2015-01-21 14:12 ` Alim Akhtar
0 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-21 14:12 UTC (permalink / raw)
To: linux-arm-kernel
Hi Jaehoon
On Wed, Jan 21, 2015 at 4:32 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> Hi,
>
> If you want to enable the hs400 mode, need to add "mmc-hs400-1_8v" or "mmc-hs400-1_2v".
> But this patch didn't add them. do you have any other plan?
>
Yes, right, plan is to send separate patch to enable hs400, as of now
I am not sure if all the 5800-peach-pi boards are populated with
emmc5.0 device or not. So I will enable HS400 after confirming this
point.
> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>> From: Seungwon Jeon <tgih.jun@samsung.com>
>>
>> HS400 timing values are added for SMDK5420, exynos5420-peach-pit
>> and exynos5800-peach-pi boards.
>> This also adds RCLK GPIO line, this gpio should be in pull-down
>> state.
>>
>> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>> [Alim: addressed review comments]
>> ---
>> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
>> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
>> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
>> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
>> 4 files changed, 16 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>> index 9a050e1..7ffaba8 100644
>> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
>> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>> @@ -569,8 +569,10 @@
>> samsung,dw-mshc-ciu-div = <3>;
>> samsung,dw-mshc-sdr-timing = <0 4>;
>> samsung,dw-mshc-ddr-timing = <0 2>;
>> + samsung,dw-mshc-hs400-timing = <0 2>;
>> + read-strobe-delay = <90>;
>> pinctrl-names = "default";
>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>> bus-width = <8>;
>> };
>>
>> diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>> index ba686e4..8b15316 100644
>> --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>> +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>> @@ -201,6 +201,13 @@
>> samsung,pin-drv = <3>;
>> };
>>
>> + sd0_rclk: sd0-rclk {
>
> I know it used to "sd0_rdqs", not "sd0_rclk".
> Change name.
>
Ok, I will change as per UM of 5800/5420,
> Best Regards,
> Jaehoon Chung
>> + samsung,pins = "gpc0-7";
>> + samsung,pin-function = <2>;
>> + samsung,pin-pud = <1>;
>> + samsung,pin-drv = <3>;
>> + };
>> +
>> sd1_cmd: sd1-cmd {
>> samsung,pins = "gpc1-1";
>> samsung,pin-function = <2>;
>> diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>> index 8be3d7b..5290e79 100644
>> --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
>> +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>> @@ -80,8 +80,10 @@
>> samsung,dw-mshc-ciu-div = <3>;
>> samsung,dw-mshc-sdr-timing = <0 4>;
>> samsung,dw-mshc-ddr-timing = <0 2>;
>> + samsung,dw-mshc-hs400-timing = <0 2>;
>> + read-strobe-delay = <90>;
>> pinctrl-names = "default";
>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>> bus-width = <8>;
>> cap-mmc-highspeed;
>> };
>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> index e8fdda8..fa1c858 100644
>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> @@ -557,8 +557,10 @@
>> samsung,dw-mshc-ciu-div = <3>;
>> samsung,dw-mshc-sdr-timing = <0 4>;
>> samsung,dw-mshc-ddr-timing = <0 2>;
>> + samsung,dw-mshc-hs400-timing = <0 2>;
>> + read-strobe-delay = <90>;
>> pinctrl-names = "default";
>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>> bus-width = <8>;
>> };
>>
>>
>
--
Regards,
Alim
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 1/2] mmc: dw_mmc: exynos: Support eMMC's HS400 mode
2015-01-20 23:02 ` Jaehoon Chung
@ 2015-01-21 23:42 ` Alim Akhtar
-1 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-21 23:42 UTC (permalink / raw)
To: Jaehoon Chung
Cc: Alim Akhtar, linux-mmc, Chris Ball, Ulf Hansson, Seungwon Jeon,
Douglas Anderson, kgene, linux-arm-kernel, devicetree,
linux-samsung-soc, Abhilash Kesavan
Hi Jaehoon
On Wed, Jan 21, 2015 at 4:32 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> Hi,
>
> This patch can be separated.
> When i tested on my board, it's not working fine.
> I think it depends on my timing, so i will check after change the timing.
>
> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>> From: Seungwon Jeon <tgih.jun@samsung.com>
>>
>> Implements HS400 mode support for exynos host driver.
>> This also include some updates as new mode is added.
>>
>> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>> [Alim: addressed review comments]
>> ---
>> .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
>> drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
>> drivers/mmc/host/dw_mmc-exynos.h | 19 +-
>> drivers/mmc/host/dw_mmc.c | 16 +-
>> drivers/mmc/host/dw_mmc.h | 2 +
>> 5 files changed, 196 insertions(+), 35 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
>> index ee4fc05..dcab52c 100644
>> --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
>> +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
>> @@ -36,6 +36,8 @@ Required Properties:
>> in transmit mode and CIU clock phase shift value in receive mode for double
>> data rate mode operation. Refer notes below for the order of the cells and the
>> valid values.
>> +* samsung,dw-mshc-hs400-timing: Specifies the value of CIU TX and RX clock phase
>> + shift value for hs400 mode operation.
>>
>> Notes for the sdr-timing and ddr-timing values:
>>
>> @@ -50,6 +52,9 @@ Required Properties:
>> - if CIU clock divider value is 0 (that is divide by 1), both tx and rx
>> phase shift clocks should be 0.
>>
>> +* read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode
>> + (Latency value for delay line in Read path)
>> +
>> Required properties for a slot (Deprecated - Recommend to use one slot per host):
>>
>> * gpios: specifies a list of gpios used for command, clock and data bus. The
>> @@ -82,5 +87,7 @@ Example:
>> samsung,dw-mshc-ciu-div = <3>;
>> samsung,dw-mshc-sdr-timing = <2 3>;
>> samsung,dw-mshc-ddr-timing = <1 2>;
>> + samsung,dw-mshc-hs400-timing = <0 2>;
>> + read-strobe-delay = <90>;
>
> read-strobe-delay is exynos specific, isn't?
> read-strobe-delay -> samsung.read-strobe-delay.
>
read-strobe are as per hs400 spec, ok I will change this to match the
naming with other properties.
>> bus-width = <8>;
>> };
>> diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
>> index 12a5eaa..172a2a8 100644
>> --- a/drivers/mmc/host/dw_mmc-exynos.c
>> +++ b/drivers/mmc/host/dw_mmc-exynos.c
>> @@ -40,7 +40,12 @@ struct dw_mci_exynos_priv_data {
>> u8 ciu_div;
>> u32 sdr_timing;
>> u32 ddr_timing;
>> + u32 hs400_timing;
>> + u32 tuned_sample;
>> u32 cur_speed;
>> + u32 dqs_delay;
>> + u32 saved_dqs_en;
>> + u32 saved_strobe_ctrl;
>> };
>>
>> static struct dw_mci_exynos_compatible {
>> @@ -71,6 +76,21 @@ static struct dw_mci_exynos_compatible {
>> },
>> };
>>
>> +static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> +
>> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
>> + return EXYNOS4412_FIXED_CIU_CLK_DIV;
>> + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
>> + return EXYNOS4210_FIXED_CIU_CLK_DIV;
>> + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
>> + else
>> + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1;
>> +}
>> +
>> static int dw_mci_exynos_priv_init(struct dw_mci *host)
>> {
>> struct dw_mci_exynos_priv_data *priv = host->priv;
>> @@ -85,6 +105,16 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
>> SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT);
>> }
>>
>> + if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) {
>> + priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL);
>> + priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN);
>> + priv->saved_dqs_en |= AXI_NON_BLOCKING_WR;
>> + mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en);
>> + if (!priv->dqs_delay)
>> + priv->dqs_delay =
>> + DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
>> + }
>> +
>> return 0;
>> }
>>
>> @@ -92,11 +122,31 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
>> {
>> struct dw_mci_exynos_priv_data *priv = host->priv;
>>
>> - host->bus_hz /= (priv->ciu_div + 1);
>> + host->bus_hz /= priv->ciu_div;
>
> Don't need to consider the case that priv->ciu_div set to 0?
>
Ah ok, I know at least one board sets ciu_div as zero, let me remove
this change. thanks
>>
>> return 0;
>> }
>>
>> +static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> + u32 clksel;
>> +
>> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> + clksel = mci_readl(host, CLKSEL64);
>> + else
>> + clksel = mci_readl(host, CLKSEL);
>> +
>> + clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing;
>> +
>> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> + mci_writel(host, CLKSEL64, clksel);
>> + else
>> + mci_writel(host, CLKSEL, clksel);
>> +}
>> +
>> #ifdef CONFIG_PM_SLEEP
>> static int dw_mci_exynos_suspend(struct device *dev)
>> {
>> @@ -172,30 +222,38 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
>> }
>> }
>>
>> -static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> +static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
>> {
>> struct dw_mci_exynos_priv_data *priv = host->priv;
>> - unsigned int wanted = ios->clock;
>> - unsigned long actual;
>> - u8 div = priv->ciu_div + 1;
>> + u32 dqs, strobe;
>>
>> - if (ios->timing == MMC_TIMING_MMC_DDR52) {
>> - if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> - priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> - mci_writel(host, CLKSEL64, priv->ddr_timing);
>> - else
>> - mci_writel(host, CLKSEL, priv->ddr_timing);
>> - /* Should be double rate for DDR mode */
>> - if (ios->bus_width == MMC_BUS_WIDTH_8)
>> - wanted <<= 1;
>> + /*
>> + * Not suppported to configure register
>
> Typo..supported
>
ok will correct.
>> + * related to HS400
>> + */
>> + if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420)
>> + return;
>> +
>> + dqs = priv->saved_dqs_en;
>> + strobe = priv->saved_strobe_ctrl;
>
> priv->saved_dqs_en is set at init-time.
> And you read the RDDQS_EN and HS400_DLINE_CTRL register at that time.
> Doesn't it need to consider the changed value at those register?
>
> priv->saved_xxx is reset value?
>
Default values are read in init and adjusted below, for now only these
bits are touched other bits of these register are kept as their reset
values.
>> +
>> + if (timing == MMC_TIMING_MMC_HS400) {
>> + dqs |= DATA_STROBE_EN;
>> + strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay);
>> } else {
>> - if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> - priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> - mci_writel(host, CLKSEL64, priv->sdr_timing);
>> - else
>> - mci_writel(host, CLKSEL, priv->sdr_timing);
>> + dqs &= ~DATA_STROBE_EN;
>> }
>>
>> + mci_writel(host, HS400_DQS_EN, dqs);
>> + mci_writel(host, HS400_DLINE_CTRL, strobe);
>> +}
>> +
>> +static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> + unsigned long actual;
>> + u8 div;
>> + int ret;
>> /*
>> * Don't care if wanted clock is zero or
>> * ciu clock is unavailable
>> @@ -207,17 +265,52 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> if (wanted < EXYNOS_CCLKIN_MIN)
>> wanted = EXYNOS_CCLKIN_MIN;
>>
>> - if (wanted != priv->cur_speed) {
>> - int ret = clk_set_rate(host->ciu_clk, wanted * div);
>> - if (ret)
>> - dev_warn(host->dev,
>> - "failed to set clk-rate %u error: %d\n",
>> - wanted * div, ret);
>> - actual = clk_get_rate(host->ciu_clk);
>> - host->bus_hz = actual / div;
>> - priv->cur_speed = wanted;
>> - host->current_speed = 0;
>> + if (wanted == priv->cur_speed)
>> + return;
>> +
>> + div = dw_mci_exynos_get_ciu_div(host);
>> + ret = clk_set_rate(host->ciu_clk, wanted * div);
>> + if (ret)
>> + dev_warn(host->dev,
>> + "failed to set clk-rate %u error: %d\n",
>> + wanted * div, ret);
>> + actual = clk_get_rate(host->ciu_clk);
>> + host->bus_hz = actual / div;
>> + priv->cur_speed = wanted;
>> + host->current_speed = 0;
>> +}
>> +
>> +static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> + unsigned int wanted = ios->clock;
>> + u32 timing = ios->timing, clksel;
>> +
>> + switch (timing) {
>> + case MMC_TIMING_MMC_HS400:
>> + /* Update tuned sample timing */
>> + clksel = SDMMC_CLKSEL_UP_SAMPLE(
>> + priv->hs400_timing, priv->tuned_sample);
>> + wanted <<= 1;
>> + break;
>> + case MMC_TIMING_MMC_DDR52:
>> + clksel = priv->ddr_timing;
>> + /* Should be double rate for DDR mode */
>> + if (ios->bus_width == MMC_BUS_WIDTH_8)
>> + wanted <<= 1;
>> + break;
>> + default:
>> + clksel = priv->sdr_timing;
>> }
>> +
>> + /* Set clock timing for the requested speed mode*/
>> + dw_mci_exynos_set_clksel_timing(host, clksel);
>> +
>> + /* Configure setting for HS400 */
>> + dw_mci_exynos_config_hs400(host, timing);
>> +
>> + /* Configure clock rate */
>> + dw_mci_exynos_adjust_clock(host, wanted);
>> }
>>
>> static int dw_mci_exynos_parse_dt(struct dw_mci *host)
>> @@ -260,6 +353,16 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host)
>> return ret;
>>
>> priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
>> +
>> + ret = of_property_read_u32_array(np,
>> + "samsung,dw-mshc-hs400-timing", timing, 2);
>> + if (!ret && of_property_read_u32(np,
>> + "read-strobe-delay", &priv->dqs_delay))
>> + dev_info(host->dev,
>> + "read-strobe-delay is not found, assuming usage of default value\n");
>
> Need the message?
>
Just in case the default values does not work, then user will know
this is something they need to change as per their boards.
>> +
>> + priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1],
>> + HS400_FIXED_CIU_CLK_DIV);
>
> Why useed the HS400_FIXED_CIU_CLK_DIV? always set to 1?
>
I thought about this, but I didn't find a case where it is anytime set
to more then div by 2 to support HS400 clock input value requirement.
So instead of getting this via DT, I kept fixed value,
Let me know your opinion on this, in case you wants me to change this.
> Best Regards,
> Jaehoon Chung
>
>> host->priv = priv;
>> return 0;
>> }
>> @@ -285,7 +388,7 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
>> clksel = mci_readl(host, CLKSEL64);
>> else
>> clksel = mci_readl(host, CLKSEL);
>> - clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample);
>> + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
>> if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> mci_writel(host, CLKSEL64, clksel);
>> @@ -304,13 +407,16 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
>> clksel = mci_readl(host, CLKSEL64);
>> else
>> clksel = mci_readl(host, CLKSEL);
>> +
>> sample = (clksel + 1) & 0x7;
>> - clksel = (clksel & ~0x7) | sample;
>> + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
>> +
>> if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> mci_writel(host, CLKSEL64, clksel);
>> else
>> mci_writel(host, CLKSEL, clksel);
>> +
>> return sample;
>> }
>>
>> @@ -343,6 +449,7 @@ out:
>> static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
>> {
>> struct dw_mci *host = slot->host;
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> struct mmc_host *mmc = slot->mmc;
>> u8 start_smpl, smpl, candiates = 0;
>> s8 found = -1;
>> @@ -360,14 +467,27 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
>> } while (start_smpl != smpl);
>>
>> found = dw_mci_exynos_get_best_clksmpl(candiates);
>> - if (found >= 0)
>> + if (found >= 0) {
>> dw_mci_exynos_set_clksmpl(host, found);
>> - else
>> + priv->tuned_sample = found;
>> + } else {
>> ret = -EIO;
>> + }
>>
>> return ret;
>> }
>>
>> +int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
>> + struct mmc_ios *ios)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> +
>> + dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing);
>> + dw_mci_exynos_adjust_clock(host, (ios->clock) << 1);
>> +
>> + return 0;
>> +}
>> +
>> /* Common capabilities of Exynos4/Exynos5 SoC */
>> static unsigned long exynos_dwmmc_caps[4] = {
>> MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
>> @@ -384,6 +504,7 @@ static const struct dw_mci_drv_data exynos_drv_data = {
>> .set_ios = dw_mci_exynos_set_ios,
>> .parse_dt = dw_mci_exynos_parse_dt,
>> .execute_tuning = dw_mci_exynos_execute_tuning,
>> + .prepare_hs400_tuning = dw_mci_exynos_prepare_hs400_tuning,
>> };
>>
>> static const struct of_device_id dw_mci_exynos_match[] = {
>> diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h
>> index 7872ce5..595c934 100644
>> --- a/drivers/mmc/host/dw_mmc-exynos.h
>> +++ b/drivers/mmc/host/dw_mmc-exynos.h
>> @@ -12,20 +12,36 @@
>> #ifndef _DW_MMC_EXYNOS_H_
>> #define _DW_MMC_EXYNOS_H_
>>
>> -/* Extended Register's Offset */
>> #define SDMMC_CLKSEL 0x09C
>> #define SDMMC_CLKSEL64 0x0A8
>>
>> +/* Extended Register's Offset */
>> +#define SDMMC_HS400_DQS_EN 0x180
>> +#define SDMMC_HS400_ASYNC_FIFO_CTRL 0x184
>> +#define SDMMC_HS400_DLINE_CTRL 0x188
>> +
>> /* CLKSEL register defines */
>> #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0)
>> #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16)
>> #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24)
>> #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7)
>> +#define SDMMC_CLKSEL_GET_DIV(x) (((x) >> 24) & 0x7)
>> +#define SDMMC_CLKSEL_UP_SAMPLE(x, y) (((x) & ~SDMMC_CLKSEL_CCLK_SAMPLE(7)) |\
>> + SDMMC_CLKSEL_CCLK_SAMPLE(y))
>> #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \
>> SDMMC_CLKSEL_CCLK_DRIVE(y) | \
>> SDMMC_CLKSEL_CCLK_DIVIDER(z))
>> +#define SDMMC_CLKSEL_TIMING_MASK SDMMC_CLKSEL_TIMING(0x7, 0x7, 0x7)
>> #define SDMMC_CLKSEL_WAKEUP_INT BIT(11)
>>
>> +/* RCLK_EN register defines */
>> +#define DATA_STROBE_EN BIT(0)
>> +#define AXI_NON_BLOCKING_WR BIT(7)
>> +
>> +/* DLINE_CTRL register defines */
>> +#define DQS_CTRL_RD_DELAY(x, y) (((x) & ~0x3FF) | ((y) & 0x3FF))
>> +#define DQS_CTRL_GET_RD_DELAY(x) ((x) & 0x3FF)
>> +
>> /* Protector Register */
>> #define SDMMC_EMMCP_BASE 0x1000
>> #define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010)
>> @@ -49,6 +65,7 @@
>> /* Fixed clock divider */
>> #define EXYNOS4210_FIXED_CIU_CLK_DIV 2
>> #define EXYNOS4412_FIXED_CIU_CLK_DIV 4
>> +#define HS400_FIXED_CIU_CLK_DIV 1
>>
>> /* Minimal required clock frequency for cclkin, unit: HZ */
>> #define EXYNOS_CCLKIN_MIN 50000000
>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>> index 2e8abc8..43a3a5b 100644
>> --- a/drivers/mmc/host/dw_mmc.c
>> +++ b/drivers/mmc/host/dw_mmc.c
>> @@ -1084,7 +1084,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>> regs = mci_readl(slot->host, UHS_REG);
>>
>> /* DDR mode set */
>> - if (ios->timing == MMC_TIMING_MMC_DDR52)
>> + if (ios->timing == MMC_TIMING_MMC_DDR52 ||
>> + ios->timing == MMC_TIMING_MMC_HS400)
>> regs |= ((0x1 << slot->id) << 16);
>> else
>> regs &= ~((0x1 << slot->id) << 16);
>> @@ -1321,6 +1322,18 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>> return err;
>> }
>>
>> +int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
>> +{
>> + struct dw_mci_slot *slot = mmc_priv(mmc);
>> + struct dw_mci *host = slot->host;
>> + const struct dw_mci_drv_data *drv_data = host->drv_data;
>> +
>> + if (drv_data && drv_data->prepare_hs400_tuning)
>> + return drv_data->prepare_hs400_tuning(host, ios);
>> +
>> + return 0;
>> +}
>> +
>> static const struct mmc_host_ops dw_mci_ops = {
>> .request = dw_mci_request,
>> .pre_req = dw_mci_pre_req,
>> @@ -1333,6 +1346,7 @@ static const struct mmc_host_ops dw_mci_ops = {
>> .card_busy = dw_mci_card_busy,
>> .start_signal_voltage_switch = dw_mci_switch_voltage,
>> .init_card = dw_mci_init_card,
>> + .prepare_hs400_tuning = dw_mci_prepare_hs400_tuning,
>> };
>>
>> static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
>> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
>> index 18c4afe..d239867 100644
>> --- a/drivers/mmc/host/dw_mmc.h
>> +++ b/drivers/mmc/host/dw_mmc.h
>> @@ -271,5 +271,7 @@ struct dw_mci_drv_data {
>> void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
>> int (*parse_dt)(struct dw_mci *host);
>> int (*execute_tuning)(struct dw_mci_slot *slot);
>> + int (*prepare_hs400_tuning)(struct dw_mci *host,
>> + struct mmc_ios *ios);
>> };
>> #endif /* _DW_MMC_H_ */
>>
>
--
Regards,
Alim
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 1/2] mmc: dw_mmc: exynos: Support eMMC's HS400 mode
@ 2015-01-21 23:42 ` Alim Akhtar
0 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-21 23:42 UTC (permalink / raw)
To: linux-arm-kernel
Hi Jaehoon
On Wed, Jan 21, 2015 at 4:32 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> Hi,
>
> This patch can be separated.
> When i tested on my board, it's not working fine.
> I think it depends on my timing, so i will check after change the timing.
>
> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>> From: Seungwon Jeon <tgih.jun@samsung.com>
>>
>> Implements HS400 mode support for exynos host driver.
>> This also include some updates as new mode is added.
>>
>> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>> [Alim: addressed review comments]
>> ---
>> .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 7 +
>> drivers/mmc/host/dw_mmc-exynos.c | 187 ++++++++++++++++----
>> drivers/mmc/host/dw_mmc-exynos.h | 19 +-
>> drivers/mmc/host/dw_mmc.c | 16 +-
>> drivers/mmc/host/dw_mmc.h | 2 +
>> 5 files changed, 196 insertions(+), 35 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
>> index ee4fc05..dcab52c 100644
>> --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
>> +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
>> @@ -36,6 +36,8 @@ Required Properties:
>> in transmit mode and CIU clock phase shift value in receive mode for double
>> data rate mode operation. Refer notes below for the order of the cells and the
>> valid values.
>> +* samsung,dw-mshc-hs400-timing: Specifies the value of CIU TX and RX clock phase
>> + shift value for hs400 mode operation.
>>
>> Notes for the sdr-timing and ddr-timing values:
>>
>> @@ -50,6 +52,9 @@ Required Properties:
>> - if CIU clock divider value is 0 (that is divide by 1), both tx and rx
>> phase shift clocks should be 0.
>>
>> +* read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode
>> + (Latency value for delay line in Read path)
>> +
>> Required properties for a slot (Deprecated - Recommend to use one slot per host):
>>
>> * gpios: specifies a list of gpios used for command, clock and data bus. The
>> @@ -82,5 +87,7 @@ Example:
>> samsung,dw-mshc-ciu-div = <3>;
>> samsung,dw-mshc-sdr-timing = <2 3>;
>> samsung,dw-mshc-ddr-timing = <1 2>;
>> + samsung,dw-mshc-hs400-timing = <0 2>;
>> + read-strobe-delay = <90>;
>
> read-strobe-delay is exynos specific, isn't?
> read-strobe-delay -> samsung.read-strobe-delay.
>
read-strobe are as per hs400 spec, ok I will change this to match the
naming with other properties.
>> bus-width = <8>;
>> };
>> diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
>> index 12a5eaa..172a2a8 100644
>> --- a/drivers/mmc/host/dw_mmc-exynos.c
>> +++ b/drivers/mmc/host/dw_mmc-exynos.c
>> @@ -40,7 +40,12 @@ struct dw_mci_exynos_priv_data {
>> u8 ciu_div;
>> u32 sdr_timing;
>> u32 ddr_timing;
>> + u32 hs400_timing;
>> + u32 tuned_sample;
>> u32 cur_speed;
>> + u32 dqs_delay;
>> + u32 saved_dqs_en;
>> + u32 saved_strobe_ctrl;
>> };
>>
>> static struct dw_mci_exynos_compatible {
>> @@ -71,6 +76,21 @@ static struct dw_mci_exynos_compatible {
>> },
>> };
>>
>> +static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> +
>> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
>> + return EXYNOS4412_FIXED_CIU_CLK_DIV;
>> + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
>> + return EXYNOS4210_FIXED_CIU_CLK_DIV;
>> + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
>> + else
>> + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1;
>> +}
>> +
>> static int dw_mci_exynos_priv_init(struct dw_mci *host)
>> {
>> struct dw_mci_exynos_priv_data *priv = host->priv;
>> @@ -85,6 +105,16 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
>> SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT);
>> }
>>
>> + if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) {
>> + priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL);
>> + priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN);
>> + priv->saved_dqs_en |= AXI_NON_BLOCKING_WR;
>> + mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en);
>> + if (!priv->dqs_delay)
>> + priv->dqs_delay =
>> + DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
>> + }
>> +
>> return 0;
>> }
>>
>> @@ -92,11 +122,31 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
>> {
>> struct dw_mci_exynos_priv_data *priv = host->priv;
>>
>> - host->bus_hz /= (priv->ciu_div + 1);
>> + host->bus_hz /= priv->ciu_div;
>
> Don't need to consider the case that priv->ciu_div set to 0?
>
Ah ok, I know at least one board sets ciu_div as zero, let me remove
this change. thanks
>>
>> return 0;
>> }
>>
>> +static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> + u32 clksel;
>> +
>> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> + clksel = mci_readl(host, CLKSEL64);
>> + else
>> + clksel = mci_readl(host, CLKSEL);
>> +
>> + clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing;
>> +
>> + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> + mci_writel(host, CLKSEL64, clksel);
>> + else
>> + mci_writel(host, CLKSEL, clksel);
>> +}
>> +
>> #ifdef CONFIG_PM_SLEEP
>> static int dw_mci_exynos_suspend(struct device *dev)
>> {
>> @@ -172,30 +222,38 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
>> }
>> }
>>
>> -static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> +static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
>> {
>> struct dw_mci_exynos_priv_data *priv = host->priv;
>> - unsigned int wanted = ios->clock;
>> - unsigned long actual;
>> - u8 div = priv->ciu_div + 1;
>> + u32 dqs, strobe;
>>
>> - if (ios->timing == MMC_TIMING_MMC_DDR52) {
>> - if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> - priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> - mci_writel(host, CLKSEL64, priv->ddr_timing);
>> - else
>> - mci_writel(host, CLKSEL, priv->ddr_timing);
>> - /* Should be double rate for DDR mode */
>> - if (ios->bus_width == MMC_BUS_WIDTH_8)
>> - wanted <<= 1;
>> + /*
>> + * Not suppported to configure register
>
> Typo..supported
>
ok will correct.
>> + * related to HS400
>> + */
>> + if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420)
>> + return;
>> +
>> + dqs = priv->saved_dqs_en;
>> + strobe = priv->saved_strobe_ctrl;
>
> priv->saved_dqs_en is set at init-time.
> And you read the RDDQS_EN and HS400_DLINE_CTRL register at that time.
> Doesn't it need to consider the changed value at those register?
>
> priv->saved_xxx is reset value?
>
Default values are read in init and adjusted below, for now only these
bits are touched other bits of these register are kept as their reset
values.
>> +
>> + if (timing == MMC_TIMING_MMC_HS400) {
>> + dqs |= DATA_STROBE_EN;
>> + strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay);
>> } else {
>> - if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> - priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> - mci_writel(host, CLKSEL64, priv->sdr_timing);
>> - else
>> - mci_writel(host, CLKSEL, priv->sdr_timing);
>> + dqs &= ~DATA_STROBE_EN;
>> }
>>
>> + mci_writel(host, HS400_DQS_EN, dqs);
>> + mci_writel(host, HS400_DLINE_CTRL, strobe);
>> +}
>> +
>> +static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> + unsigned long actual;
>> + u8 div;
>> + int ret;
>> /*
>> * Don't care if wanted clock is zero or
>> * ciu clock is unavailable
>> @@ -207,17 +265,52 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> if (wanted < EXYNOS_CCLKIN_MIN)
>> wanted = EXYNOS_CCLKIN_MIN;
>>
>> - if (wanted != priv->cur_speed) {
>> - int ret = clk_set_rate(host->ciu_clk, wanted * div);
>> - if (ret)
>> - dev_warn(host->dev,
>> - "failed to set clk-rate %u error: %d\n",
>> - wanted * div, ret);
>> - actual = clk_get_rate(host->ciu_clk);
>> - host->bus_hz = actual / div;
>> - priv->cur_speed = wanted;
>> - host->current_speed = 0;
>> + if (wanted == priv->cur_speed)
>> + return;
>> +
>> + div = dw_mci_exynos_get_ciu_div(host);
>> + ret = clk_set_rate(host->ciu_clk, wanted * div);
>> + if (ret)
>> + dev_warn(host->dev,
>> + "failed to set clk-rate %u error: %d\n",
>> + wanted * div, ret);
>> + actual = clk_get_rate(host->ciu_clk);
>> + host->bus_hz = actual / div;
>> + priv->cur_speed = wanted;
>> + host->current_speed = 0;
>> +}
>> +
>> +static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> + unsigned int wanted = ios->clock;
>> + u32 timing = ios->timing, clksel;
>> +
>> + switch (timing) {
>> + case MMC_TIMING_MMC_HS400:
>> + /* Update tuned sample timing */
>> + clksel = SDMMC_CLKSEL_UP_SAMPLE(
>> + priv->hs400_timing, priv->tuned_sample);
>> + wanted <<= 1;
>> + break;
>> + case MMC_TIMING_MMC_DDR52:
>> + clksel = priv->ddr_timing;
>> + /* Should be double rate for DDR mode */
>> + if (ios->bus_width == MMC_BUS_WIDTH_8)
>> + wanted <<= 1;
>> + break;
>> + default:
>> + clksel = priv->sdr_timing;
>> }
>> +
>> + /* Set clock timing for the requested speed mode*/
>> + dw_mci_exynos_set_clksel_timing(host, clksel);
>> +
>> + /* Configure setting for HS400 */
>> + dw_mci_exynos_config_hs400(host, timing);
>> +
>> + /* Configure clock rate */
>> + dw_mci_exynos_adjust_clock(host, wanted);
>> }
>>
>> static int dw_mci_exynos_parse_dt(struct dw_mci *host)
>> @@ -260,6 +353,16 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host)
>> return ret;
>>
>> priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
>> +
>> + ret = of_property_read_u32_array(np,
>> + "samsung,dw-mshc-hs400-timing", timing, 2);
>> + if (!ret && of_property_read_u32(np,
>> + "read-strobe-delay", &priv->dqs_delay))
>> + dev_info(host->dev,
>> + "read-strobe-delay is not found, assuming usage of default value\n");
>
> Need the message?
>
Just in case the default values does not work, then user will know
this is something they need to change as per their boards.
>> +
>> + priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1],
>> + HS400_FIXED_CIU_CLK_DIV);
>
> Why useed the HS400_FIXED_CIU_CLK_DIV? always set to 1?
>
I thought about this, but I didn't find a case where it is anytime set
to more then div by 2 to support HS400 clock input value requirement.
So instead of getting this via DT, I kept fixed value,
Let me know your opinion on this, in case you wants me to change this.
> Best Regards,
> Jaehoon Chung
>
>> host->priv = priv;
>> return 0;
>> }
>> @@ -285,7 +388,7 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
>> clksel = mci_readl(host, CLKSEL64);
>> else
>> clksel = mci_readl(host, CLKSEL);
>> - clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample);
>> + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
>> if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> mci_writel(host, CLKSEL64, clksel);
>> @@ -304,13 +407,16 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
>> clksel = mci_readl(host, CLKSEL64);
>> else
>> clksel = mci_readl(host, CLKSEL);
>> +
>> sample = (clksel + 1) & 0x7;
>> - clksel = (clksel & ~0x7) | sample;
>> + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
>> +
>> if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
>> priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
>> mci_writel(host, CLKSEL64, clksel);
>> else
>> mci_writel(host, CLKSEL, clksel);
>> +
>> return sample;
>> }
>>
>> @@ -343,6 +449,7 @@ out:
>> static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
>> {
>> struct dw_mci *host = slot->host;
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> struct mmc_host *mmc = slot->mmc;
>> u8 start_smpl, smpl, candiates = 0;
>> s8 found = -1;
>> @@ -360,14 +467,27 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
>> } while (start_smpl != smpl);
>>
>> found = dw_mci_exynos_get_best_clksmpl(candiates);
>> - if (found >= 0)
>> + if (found >= 0) {
>> dw_mci_exynos_set_clksmpl(host, found);
>> - else
>> + priv->tuned_sample = found;
>> + } else {
>> ret = -EIO;
>> + }
>>
>> return ret;
>> }
>>
>> +int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
>> + struct mmc_ios *ios)
>> +{
>> + struct dw_mci_exynos_priv_data *priv = host->priv;
>> +
>> + dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing);
>> + dw_mci_exynos_adjust_clock(host, (ios->clock) << 1);
>> +
>> + return 0;
>> +}
>> +
>> /* Common capabilities of Exynos4/Exynos5 SoC */
>> static unsigned long exynos_dwmmc_caps[4] = {
>> MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
>> @@ -384,6 +504,7 @@ static const struct dw_mci_drv_data exynos_drv_data = {
>> .set_ios = dw_mci_exynos_set_ios,
>> .parse_dt = dw_mci_exynos_parse_dt,
>> .execute_tuning = dw_mci_exynos_execute_tuning,
>> + .prepare_hs400_tuning = dw_mci_exynos_prepare_hs400_tuning,
>> };
>>
>> static const struct of_device_id dw_mci_exynos_match[] = {
>> diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h
>> index 7872ce5..595c934 100644
>> --- a/drivers/mmc/host/dw_mmc-exynos.h
>> +++ b/drivers/mmc/host/dw_mmc-exynos.h
>> @@ -12,20 +12,36 @@
>> #ifndef _DW_MMC_EXYNOS_H_
>> #define _DW_MMC_EXYNOS_H_
>>
>> -/* Extended Register's Offset */
>> #define SDMMC_CLKSEL 0x09C
>> #define SDMMC_CLKSEL64 0x0A8
>>
>> +/* Extended Register's Offset */
>> +#define SDMMC_HS400_DQS_EN 0x180
>> +#define SDMMC_HS400_ASYNC_FIFO_CTRL 0x184
>> +#define SDMMC_HS400_DLINE_CTRL 0x188
>> +
>> /* CLKSEL register defines */
>> #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0)
>> #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16)
>> #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24)
>> #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7)
>> +#define SDMMC_CLKSEL_GET_DIV(x) (((x) >> 24) & 0x7)
>> +#define SDMMC_CLKSEL_UP_SAMPLE(x, y) (((x) & ~SDMMC_CLKSEL_CCLK_SAMPLE(7)) |\
>> + SDMMC_CLKSEL_CCLK_SAMPLE(y))
>> #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \
>> SDMMC_CLKSEL_CCLK_DRIVE(y) | \
>> SDMMC_CLKSEL_CCLK_DIVIDER(z))
>> +#define SDMMC_CLKSEL_TIMING_MASK SDMMC_CLKSEL_TIMING(0x7, 0x7, 0x7)
>> #define SDMMC_CLKSEL_WAKEUP_INT BIT(11)
>>
>> +/* RCLK_EN register defines */
>> +#define DATA_STROBE_EN BIT(0)
>> +#define AXI_NON_BLOCKING_WR BIT(7)
>> +
>> +/* DLINE_CTRL register defines */
>> +#define DQS_CTRL_RD_DELAY(x, y) (((x) & ~0x3FF) | ((y) & 0x3FF))
>> +#define DQS_CTRL_GET_RD_DELAY(x) ((x) & 0x3FF)
>> +
>> /* Protector Register */
>> #define SDMMC_EMMCP_BASE 0x1000
>> #define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010)
>> @@ -49,6 +65,7 @@
>> /* Fixed clock divider */
>> #define EXYNOS4210_FIXED_CIU_CLK_DIV 2
>> #define EXYNOS4412_FIXED_CIU_CLK_DIV 4
>> +#define HS400_FIXED_CIU_CLK_DIV 1
>>
>> /* Minimal required clock frequency for cclkin, unit: HZ */
>> #define EXYNOS_CCLKIN_MIN 50000000
>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>> index 2e8abc8..43a3a5b 100644
>> --- a/drivers/mmc/host/dw_mmc.c
>> +++ b/drivers/mmc/host/dw_mmc.c
>> @@ -1084,7 +1084,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>> regs = mci_readl(slot->host, UHS_REG);
>>
>> /* DDR mode set */
>> - if (ios->timing == MMC_TIMING_MMC_DDR52)
>> + if (ios->timing == MMC_TIMING_MMC_DDR52 ||
>> + ios->timing == MMC_TIMING_MMC_HS400)
>> regs |= ((0x1 << slot->id) << 16);
>> else
>> regs &= ~((0x1 << slot->id) << 16);
>> @@ -1321,6 +1322,18 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>> return err;
>> }
>>
>> +int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
>> +{
>> + struct dw_mci_slot *slot = mmc_priv(mmc);
>> + struct dw_mci *host = slot->host;
>> + const struct dw_mci_drv_data *drv_data = host->drv_data;
>> +
>> + if (drv_data && drv_data->prepare_hs400_tuning)
>> + return drv_data->prepare_hs400_tuning(host, ios);
>> +
>> + return 0;
>> +}
>> +
>> static const struct mmc_host_ops dw_mci_ops = {
>> .request = dw_mci_request,
>> .pre_req = dw_mci_pre_req,
>> @@ -1333,6 +1346,7 @@ static const struct mmc_host_ops dw_mci_ops = {
>> .card_busy = dw_mci_card_busy,
>> .start_signal_voltage_switch = dw_mci_switch_voltage,
>> .init_card = dw_mci_init_card,
>> + .prepare_hs400_tuning = dw_mci_prepare_hs400_tuning,
>> };
>>
>> static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
>> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
>> index 18c4afe..d239867 100644
>> --- a/drivers/mmc/host/dw_mmc.h
>> +++ b/drivers/mmc/host/dw_mmc.h
>> @@ -271,5 +271,7 @@ struct dw_mci_drv_data {
>> void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
>> int (*parse_dt)(struct dw_mci *host);
>> int (*execute_tuning)(struct dw_mci_slot *slot);
>> + int (*prepare_hs400_tuning)(struct dw_mci *host,
>> + struct mmc_ios *ios);
>> };
>> #endif /* _DW_MMC_H_ */
>>
>
--
Regards,
Alim
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
2015-01-21 14:12 ` Alim Akhtar
@ 2015-01-22 2:28 ` Jaehoon Chung
-1 siblings, 0 replies; 24+ messages in thread
From: Jaehoon Chung @ 2015-01-22 2:28 UTC (permalink / raw)
To: Alim Akhtar
Cc: Alim Akhtar, linux-mmc, Chris Ball, Ulf Hansson, Seungwon Jeon,
Douglas Anderson, kgene, linux-arm-kernel, devicetree,
linux-samsung-soc, Abhilash Kesavan
Hi.
On 01/21/2015 11:12 PM, Alim Akhtar wrote:
> Hi Jaehoon
>
> On Wed, Jan 21, 2015 at 4:32 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
>> Hi,
>>
>> If you want to enable the hs400 mode, need to add "mmc-hs400-1_8v" or "mmc-hs400-1_2v".
>> But this patch didn't add them. do you have any other plan?
>>
> Yes, right, plan is to send separate patch to enable hs400, as of now
> I am not sure if all the 5800-peach-pi boards are populated with
> emmc5.0 device or not. So I will enable HS400 after confirming this
> point.
I know if card is not support hs400, then it should be enabled to other bus mode.
Best Regards,
Jaehoon Chung
>> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>>> From: Seungwon Jeon <tgih.jun@samsung.com>
>>>
>>> HS400 timing values are added for SMDK5420, exynos5420-peach-pit
>>> and exynos5800-peach-pi boards.
>>> This also adds RCLK GPIO line, this gpio should be in pull-down
>>> state.
>>>
>>> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
>>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>>> [Alim: addressed review comments]
>>> ---
>>> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
>>> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
>>> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
>>> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
>>> 4 files changed, 16 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>> index 9a050e1..7ffaba8 100644
>>> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>> @@ -569,8 +569,10 @@
>>> samsung,dw-mshc-ciu-div = <3>;
>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>> + read-strobe-delay = <90>;
>>> pinctrl-names = "default";
>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>> bus-width = <8>;
>>> };
>>>
>>> diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>> index ba686e4..8b15316 100644
>>> --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>> +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>> @@ -201,6 +201,13 @@
>>> samsung,pin-drv = <3>;
>>> };
>>>
>>> + sd0_rclk: sd0-rclk {
>>
>> I know it used to "sd0_rdqs", not "sd0_rclk".
>> Change name.
>>
> Ok, I will change as per UM of 5800/5420,
>
>> Best Regards,
>> Jaehoon Chung
>>> + samsung,pins = "gpc0-7";
>>> + samsung,pin-function = <2>;
>>> + samsung,pin-pud = <1>;
>>> + samsung,pin-drv = <3>;
>>> + };
>>> +
>>> sd1_cmd: sd1-cmd {
>>> samsung,pins = "gpc1-1";
>>> samsung,pin-function = <2>;
>>> diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>> index 8be3d7b..5290e79 100644
>>> --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>> +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>> @@ -80,8 +80,10 @@
>>> samsung,dw-mshc-ciu-div = <3>;
>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>> + read-strobe-delay = <90>;
>>> pinctrl-names = "default";
>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>> bus-width = <8>;
>>> cap-mmc-highspeed;
>>> };
>>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>> index e8fdda8..fa1c858 100644
>>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>> @@ -557,8 +557,10 @@
>>> samsung,dw-mshc-ciu-div = <3>;
>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>> + read-strobe-delay = <90>;
>>> pinctrl-names = "default";
>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>> bus-width = <8>;
>>> };
>>>
>>>
>>
>
>
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
@ 2015-01-22 2:28 ` Jaehoon Chung
0 siblings, 0 replies; 24+ messages in thread
From: Jaehoon Chung @ 2015-01-22 2:28 UTC (permalink / raw)
To: linux-arm-kernel
Hi.
On 01/21/2015 11:12 PM, Alim Akhtar wrote:
> Hi Jaehoon
>
> On Wed, Jan 21, 2015 at 4:32 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
>> Hi,
>>
>> If you want to enable the hs400 mode, need to add "mmc-hs400-1_8v" or "mmc-hs400-1_2v".
>> But this patch didn't add them. do you have any other plan?
>>
> Yes, right, plan is to send separate patch to enable hs400, as of now
> I am not sure if all the 5800-peach-pi boards are populated with
> emmc5.0 device or not. So I will enable HS400 after confirming this
> point.
I know if card is not support hs400, then it should be enabled to other bus mode.
Best Regards,
Jaehoon Chung
>> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>>> From: Seungwon Jeon <tgih.jun@samsung.com>
>>>
>>> HS400 timing values are added for SMDK5420, exynos5420-peach-pit
>>> and exynos5800-peach-pi boards.
>>> This also adds RCLK GPIO line, this gpio should be in pull-down
>>> state.
>>>
>>> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
>>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>>> [Alim: addressed review comments]
>>> ---
>>> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
>>> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
>>> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
>>> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
>>> 4 files changed, 16 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>> index 9a050e1..7ffaba8 100644
>>> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>> @@ -569,8 +569,10 @@
>>> samsung,dw-mshc-ciu-div = <3>;
>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>> + read-strobe-delay = <90>;
>>> pinctrl-names = "default";
>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>> bus-width = <8>;
>>> };
>>>
>>> diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>> index ba686e4..8b15316 100644
>>> --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>> +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>> @@ -201,6 +201,13 @@
>>> samsung,pin-drv = <3>;
>>> };
>>>
>>> + sd0_rclk: sd0-rclk {
>>
>> I know it used to "sd0_rdqs", not "sd0_rclk".
>> Change name.
>>
> Ok, I will change as per UM of 5800/5420,
>
>> Best Regards,
>> Jaehoon Chung
>>> + samsung,pins = "gpc0-7";
>>> + samsung,pin-function = <2>;
>>> + samsung,pin-pud = <1>;
>>> + samsung,pin-drv = <3>;
>>> + };
>>> +
>>> sd1_cmd: sd1-cmd {
>>> samsung,pins = "gpc1-1";
>>> samsung,pin-function = <2>;
>>> diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>> index 8be3d7b..5290e79 100644
>>> --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>> +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>> @@ -80,8 +80,10 @@
>>> samsung,dw-mshc-ciu-div = <3>;
>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>> + read-strobe-delay = <90>;
>>> pinctrl-names = "default";
>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>> bus-width = <8>;
>>> cap-mmc-highspeed;
>>> };
>>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>> index e8fdda8..fa1c858 100644
>>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>> @@ -557,8 +557,10 @@
>>> samsung,dw-mshc-ciu-div = <3>;
>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>> + read-strobe-delay = <90>;
>>> pinctrl-names = "default";
>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>> bus-width = <8>;
>>> };
>>>
>>>
>>
>
>
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
2015-01-22 2:28 ` Jaehoon Chung
@ 2015-01-29 2:43 ` Alim Akhtar
-1 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-29 2:43 UTC (permalink / raw)
To: Jaehoon Chung
Cc: Alim Akhtar, linux-mmc-u79uwXL29TY76Z2rM5mHXA, Chris Ball,
Ulf Hansson, Seungwon Jeon, Douglas Anderson, kgene,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA, Abhilash Kesavan
Hi Jaehoon,
Thanks for review.
On Thu, Jan 22, 2015 at 11:28 AM, Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> wrote:
> Hi.
>
> On 01/21/2015 11:12 PM, Alim Akhtar wrote:
>> Hi Jaehoon
>>
>> On Wed, Jan 21, 2015 at 4:32 AM, Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> wrote:
>>> Hi,
>>>
>>> If you want to enable the hs400 mode, need to add "mmc-hs400-1_8v" or "mmc-hs400-1_2v".
>>> But this patch didn't add them. do you have any other plan?
>>>
>> Yes, right, plan is to send separate patch to enable hs400, as of now
>> I am not sure if all the 5800-peach-pi boards are populated with
>> emmc5.0 device or not. So I will enable HS400 after confirming this
>> point.
>
> I know if card is not support hs400, then it should be enabled to other bus mode.
>
hmm...mmc-hs{200/400}-1_8v are host capabilities, so host should first
support this, then we can enable it.
ok, I will enable HS400 for peach-pi in this series.
Also I checked UMs for 5420/5800, in UM, strobe signal is named as
RCLK, so going to keep the same name as UM.
Will resend the patches after modification shortly.
> Best Regards,
> Jaehoon Chung
>
>>> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>>>> From: Seungwon Jeon <tgih.jun-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>>>>
>>>> HS400 timing values are added for SMDK5420, exynos5420-peach-pit
>>>> and exynos5800-peach-pi boards.
>>>> This also adds RCLK GPIO line, this gpio should be in pull-down
>>>> state.
>>>>
>>>> Signed-off-by: Seungwon Jeon <tgih.jun-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>>>> Signed-off-by: Alim Akhtar <alim.akhtar-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>>>> [Alim: addressed review comments]
>>>> ---
>>>> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
>>>> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
>>>> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
>>>> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
>>>> 4 files changed, 16 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>>> index 9a050e1..7ffaba8 100644
>>>> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>>> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>>> @@ -569,8 +569,10 @@
>>>> samsung,dw-mshc-ciu-div = <3>;
>>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>>> + read-strobe-delay = <90>;
>>>> pinctrl-names = "default";
>>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>>> bus-width = <8>;
>>>> };
>>>>
>>>> diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>>> index ba686e4..8b15316 100644
>>>> --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>>> +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>>> @@ -201,6 +201,13 @@
>>>> samsung,pin-drv = <3>;
>>>> };
>>>>
>>>> + sd0_rclk: sd0-rclk {
>>>
>>> I know it used to "sd0_rdqs", not "sd0_rclk".
>>> Change name.
>>>
>> Ok, I will change as per UM of 5800/5420,
>>
>>> Best Regards,
>>> Jaehoon Chung
>>>> + samsung,pins = "gpc0-7";
>>>> + samsung,pin-function = <2>;
>>>> + samsung,pin-pud = <1>;
>>>> + samsung,pin-drv = <3>;
>>>> + };
>>>> +
>>>> sd1_cmd: sd1-cmd {
>>>> samsung,pins = "gpc1-1";
>>>> samsung,pin-function = <2>;
>>>> diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>>> index 8be3d7b..5290e79 100644
>>>> --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>>> +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>>> @@ -80,8 +80,10 @@
>>>> samsung,dw-mshc-ciu-div = <3>;
>>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>>> + read-strobe-delay = <90>;
>>>> pinctrl-names = "default";
>>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>>> bus-width = <8>;
>>>> cap-mmc-highspeed;
>>>> };
>>>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>>> index e8fdda8..fa1c858 100644
>>>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>>> @@ -557,8 +557,10 @@
>>>> samsung,dw-mshc-ciu-div = <3>;
>>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>>> + read-strobe-delay = <90>;
>>>> pinctrl-names = "default";
>>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>>> bus-width = <8>;
>>>> };
>>>>
>>>>
>>>
>>
>>
>>
>
--
Regards,
Alim
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800
@ 2015-01-29 2:43 ` Alim Akhtar
0 siblings, 0 replies; 24+ messages in thread
From: Alim Akhtar @ 2015-01-29 2:43 UTC (permalink / raw)
To: linux-arm-kernel
Hi Jaehoon,
Thanks for review.
On Thu, Jan 22, 2015 at 11:28 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> Hi.
>
> On 01/21/2015 11:12 PM, Alim Akhtar wrote:
>> Hi Jaehoon
>>
>> On Wed, Jan 21, 2015 at 4:32 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
>>> Hi,
>>>
>>> If you want to enable the hs400 mode, need to add "mmc-hs400-1_8v" or "mmc-hs400-1_2v".
>>> But this patch didn't add them. do you have any other plan?
>>>
>> Yes, right, plan is to send separate patch to enable hs400, as of now
>> I am not sure if all the 5800-peach-pi boards are populated with
>> emmc5.0 device or not. So I will enable HS400 after confirming this
>> point.
>
> I know if card is not support hs400, then it should be enabled to other bus mode.
>
hmm...mmc-hs{200/400}-1_8v are host capabilities, so host should first
support this, then we can enable it.
ok, I will enable HS400 for peach-pi in this series.
Also I checked UMs for 5420/5800, in UM, strobe signal is named as
RCLK, so going to keep the same name as UM.
Will resend the patches after modification shortly.
> Best Regards,
> Jaehoon Chung
>
>>> On 01/14/2015 07:30 PM, Alim Akhtar wrote:
>>>> From: Seungwon Jeon <tgih.jun@samsung.com>
>>>>
>>>> HS400 timing values are added for SMDK5420, exynos5420-peach-pit
>>>> and exynos5800-peach-pi boards.
>>>> This also adds RCLK GPIO line, this gpio should be in pull-down
>>>> state.
>>>>
>>>> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
>>>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>>>> [Alim: addressed review comments]
>>>> ---
>>>> arch/arm/boot/dts/exynos5420-peach-pit.dts | 4 +++-
>>>> arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 7 +++++++
>>>> arch/arm/boot/dts/exynos5420-smdk5420.dts | 4 +++-
>>>> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++-
>>>> 4 files changed, 16 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>>> index 9a050e1..7ffaba8 100644
>>>> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>>> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>>> @@ -569,8 +569,10 @@
>>>> samsung,dw-mshc-ciu-div = <3>;
>>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>>> + read-strobe-delay = <90>;
>>>> pinctrl-names = "default";
>>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>>> bus-width = <8>;
>>>> };
>>>>
>>>> diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>>> index ba686e4..8b15316 100644
>>>> --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>>> +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
>>>> @@ -201,6 +201,13 @@
>>>> samsung,pin-drv = <3>;
>>>> };
>>>>
>>>> + sd0_rclk: sd0-rclk {
>>>
>>> I know it used to "sd0_rdqs", not "sd0_rclk".
>>> Change name.
>>>
>> Ok, I will change as per UM of 5800/5420,
>>
>>> Best Regards,
>>> Jaehoon Chung
>>>> + samsung,pins = "gpc0-7";
>>>> + samsung,pin-function = <2>;
>>>> + samsung,pin-pud = <1>;
>>>> + samsung,pin-drv = <3>;
>>>> + };
>>>> +
>>>> sd1_cmd: sd1-cmd {
>>>> samsung,pins = "gpc1-1";
>>>> samsung,pin-function = <2>;
>>>> diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>>> index 8be3d7b..5290e79 100644
>>>> --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>>> +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
>>>> @@ -80,8 +80,10 @@
>>>> samsung,dw-mshc-ciu-div = <3>;
>>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>>> + read-strobe-delay = <90>;
>>>> pinctrl-names = "default";
>>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>>> bus-width = <8>;
>>>> cap-mmc-highspeed;
>>>> };
>>>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>>> index e8fdda8..fa1c858 100644
>>>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>>> @@ -557,8 +557,10 @@
>>>> samsung,dw-mshc-ciu-div = <3>;
>>>> samsung,dw-mshc-sdr-timing = <0 4>;
>>>> samsung,dw-mshc-ddr-timing = <0 2>;
>>>> + samsung,dw-mshc-hs400-timing = <0 2>;
>>>> + read-strobe-delay = <90>;
>>>> pinctrl-names = "default";
>>>> - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
>>>> + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8 &sd0_rclk>;
>>>> bus-width = <8>;
>>>> };
>>>>
>>>>
>>>
>>
>>
>>
>
--
Regards,
Alim
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2015-01-29 2:43 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-14 10:30 [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support Alim Akhtar
2015-01-14 10:30 ` Alim Akhtar
2015-01-14 10:30 ` [PATCH v4 1/2] mmc: dw_mmc: exynos: Support eMMC's HS400 mode Alim Akhtar
2015-01-14 10:30 ` Alim Akhtar
2015-01-20 23:02 ` Jaehoon Chung
2015-01-20 23:02 ` Jaehoon Chung
2015-01-21 23:42 ` Alim Akhtar
2015-01-21 23:42 ` Alim Akhtar
2015-01-14 10:30 ` [PATCH v4 2/2] ARM: dts: Add HS400 support for exynos5420 and exynos5800 Alim Akhtar
2015-01-14 10:30 ` Alim Akhtar
[not found] ` <1421231446-4776-3-git-send-email-alim.akhtar-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-01-20 23:02 ` Jaehoon Chung
2015-01-20 23:02 ` Jaehoon Chung
2015-01-21 14:12 ` Alim Akhtar
2015-01-21 14:12 ` Alim Akhtar
2015-01-22 2:28 ` Jaehoon Chung
2015-01-22 2:28 ` Jaehoon Chung
[not found] ` <54C06049.5070106-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-01-29 2:43 ` Alim Akhtar
2015-01-29 2:43 ` Alim Akhtar
2015-01-14 13:32 ` [PATCH v4 0/2] mmc: dw_mmc: exynos: Add HS400 support Jaehoon Chung
2015-01-14 13:32 ` Jaehoon Chung
2015-01-14 15:35 ` Kukjin Kim
2015-01-14 15:35 ` Kukjin Kim
2015-01-14 15:56 ` Ulf Hansson
2015-01-14 15:56 ` Ulf Hansson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.