From patchwork Wed May 2 05:07:43 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: thomas.abraham@linaro.org X-Patchwork-Id: 8347 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 6AC8523E1D for ; Wed, 2 May 2012 05:12:23 +0000 (UTC) Received: from mail-ob0-f180.google.com (mail-ob0-f180.google.com [209.85.214.180]) by fiordland.canonical.com (Postfix) with ESMTP id 15E33A186A7 for ; Wed, 2 May 2012 05:12:22 +0000 (UTC) Received: by obbup16 with SMTP id up16so596457obb.11 for ; Tue, 01 May 2012 22:12:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=g9K6MaOiUEyvlay4iTqbv9mRNmO0wZViTnBr4x0btyU=; b=IUU8nfMjJHu9SawTYZPrVOtWMsxFuKJ/L+rguKS9RPIjb+Cw7oR7HUrDdc3tYOhxc8 CS4Dne0U05f9I1DEFH/dw3ChDFWig7oPIyJ52bN7S1TyyzyELb/mlccqgWzNsnFmpM3/ wxwLjULyX0QyLWKMv1veF9nHHlDmT6YlAA7nou9z7Fm1LnbyhrmW9uPK80j1j3qG5HDb XEO4a/ur+J1Alt1OACOEbsC69RUBUcQ4uJXUqGqqxNcbs/4rP3z5+jG3TRKsE7cPNBgj o/BNfgrDlwxxp/JOVIsLrPt7DDtmjRs7WtcuGeFaCVCcYsebe/pWNw6EhBFvvbc8CqT0 hJ+g== Received: by 10.50.47.131 with SMTP id d3mr3629994ign.33.1335935542266; Tue, 01 May 2012 22:12:22 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.137.198 with SMTP id x6csp227447ibt; Tue, 1 May 2012 22:12:21 -0700 (PDT) Received: by 10.68.191.228 with SMTP id hb4mr6386261pbc.97.1335935541447; Tue, 01 May 2012 22:12:21 -0700 (PDT) Received: from mail-pb0-f50.google.com (mail-pb0-f50.google.com [209.85.160.50]) by mx.google.com with ESMTPS id oo6si750775pbc.97.2012.05.01.22.12.20 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 01 May 2012 22:12:21 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of thomas.abraham@linaro.org) client-ip=209.85.160.50; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of thomas.abraham@linaro.org) smtp.mail=thomas.abraham@linaro.org Received: by mail-pb0-f50.google.com with SMTP id rr4so686111pbb.37 for ; Tue, 01 May 2012 22:12:20 -0700 (PDT) Received: by 10.68.239.33 with SMTP id vp1mr3123175pbc.146.1335935540769; Tue, 01 May 2012 22:12:20 -0700 (PDT) Received: from localhost.localdomain ([216.239.45.23]) by mx.google.com with ESMTPS id gv2sm887161pbc.73.2012.05.01.22.12.19 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 01 May 2012 22:12:20 -0700 (PDT) From: Thomas Abraham To: linux-mmc@vger.kernel.org, devicetree-discuss@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, cjb@laptop.org, grant.likely@secretlab.ca, rob.herring@calxeda.com, linux-samsung-soc@vger.kernel.org, kgene.kim@samsung.com, patches@linaro.org Subject: [PATCH 4/7] mmc: dw_mmc: add samsung exynos5250 specific extentions Date: Tue, 1 May 2012 22:07:43 -0700 Message-Id: <1335935266-25289-5-git-send-email-thomas.abraham@linaro.org> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1335935266-25289-1-git-send-email-thomas.abraham@linaro.org> References: <1335935266-25289-1-git-send-email-thomas.abraham@linaro.org> X-Gm-Message-State: ALoCoQkVCwUeAl+PxARuK96KnkNV6FEZ8RrT4Wam24J69SK0ZrO8EJiWyyiMlUMF6A5hlKRwV6yG The instantiation of the Synopsis Designware controller on Exynos5250 include extension for SDR and DDR specific tx/rx phase shift timing and CIU internal divider. In addition to that, the option to skip the command hold stage is also introduced. Add support for these Exynos5250 specfic extenstions. Signed-off-by: Abhilash Kesavan Signed-off-by: Thomas Abraham --- .../devicetree/bindings/mmc/synposis-dw-mshc.txt | 33 +++++++++++++++++++- drivers/mmc/host/dw_mmc-pltfm.c | 8 +++++ drivers/mmc/host/dw_mmc.c | 32 ++++++++++++++++++- drivers/mmc/host/dw_mmc.h | 13 ++++++++ include/linux/mmc/dw_mmc.h | 6 +++ 5 files changed, 89 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt index c1ed70e..465fc31 100644 --- a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt @@ -7,6 +7,8 @@ Required Properties: * compatible: should be one of the following - synopsis,dw-mshc: for controllers compliant with synopsis dw-mshc. + - synopsis,dw-mshc-exynos5250: for controllers with Samsung + Exynos5250 specific extentions. * reg: physical base address of the dw-mshc controller and size of its memory region. @@ -55,13 +57,40 @@ Optional properties: * no-write-protect: The write protect pad of the controller is not connected to the write protect pin on the slot. +Samsung Exynos5250 specific properties: + +* samsung,dw-mshc-sdr-timing: Specifies the value of CUI clock divider, CIU + clock phase shift value in transmit mode and CIU clock phase shift value in + receive mode for single data rate mode operation. Refer notes of the valid + values below. + +* samsung,dw-mshc-ddr-timing: Specifies the value of CUI clock divider, CIU + clock phase shift value in transmit mode and CIU clock phase shift value in + receive mode for double data rate mode operation. Refer notes of the valid + values below. The order of the cells should be + + - First Cell: CIU clock divider value. + - Second Cell: CIU clock phase shift value for tx mode. + - Third Cell: CIU clock phase shift value for rx mode. + + Valid values for SDR and DDR CIU clock timing: + + - valid values for CIU clock divider, tx phase shift and rx phase shift + is 0 to 7. + + - When CIU clock divider value is set to 3, all possible 8 phase shift + values can be used. + + - If CIU clock divider value is 0 (that is divide by 1), both tx and rx + phase shift clocks should be 0. + Example: The MSHC controller node can be split into two portions, SoC specific and board specific portions as listed below. dwmmc0@12200000 { - compatible = "synopsis,dw-mshc"; + compatible = "synopsis,dw-mshc-exynos5250"; reg = <0x12200000 0x1000>; interrupts = <0 75 0>; }; @@ -72,6 +101,8 @@ Example: no-write-protect; fifo-depth = <0x80>; card-detect-delay = <200>; + samsung,dw-mshc-sdr-timing = <2 3 3>; + samsung,dw-mshc-ddr-timing = <1 2 3>; slot0 { bus-width = <8>; diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 2b2c9bd..35056fd 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -27,9 +27,17 @@ static struct dw_mci_drv_data synopsis_drv_data = { .ctrl_type = DW_MCI_TYPE_SYNOPSIS, }; +static struct dw_mci_drv_data exynos5250_drv_data = { + .ctrl_type = DW_MCI_TYPE_EXYNOS5250, + .caps = MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | + MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, +}; + static const struct of_device_id dw_mci_pltfm_match[] = { { .compatible = "synopsis,dw-mshc", .data = (void *)&synopsis_drv_data, }, + { .compatible = "synopsis,dw-mshc-exynos5250", + .data = (void *)&exynos5250_drv_data, }, {}, }; MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index bcf66d7..9174a69 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -236,6 +236,7 @@ static void dw_mci_set_timeout(struct dw_mci *host) static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) { struct mmc_data *data; + struct dw_mci_slot *slot = mmc_priv(mmc); u32 cmdr; cmd->error = -EINPROGRESS; @@ -265,6 +266,10 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) cmdr |= SDMMC_CMD_DAT_WR; } + if (slot->host->drv_data->ctrl_type == DW_MCI_TYPE_EXYNOS5250) + if (SDMMC_CLKSEL_GET_SELCLK_DRV(mci_readl(slot->host, CLKSEL))) + cmdr |= SDMMC_USE_HOLD_REG; + return cmdr; } @@ -787,10 +792,19 @@ 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_UHS_DDR50) + if (ios->timing == MMC_TIMING_UHS_DDR50) { regs |= (0x1 << slot->id) << 16; - else + mci_writel(slot->host, CLKSEL, slot->host->ddr_timing); + } else { regs &= ~(0x1 << slot->id) << 16; + mci_writel(slot->host, CLKSEL, slot->host->sdr_timing); + } + + if (slot->host->drv_data->ctrl_type == DW_MCI_TYPE_EXYNOS5250) { + slot->host->bus_hz = clk_get_rate(slot->host->ciu_clk); + slot->host->bus_hz /= SDMMC_CLKSEL_GET_DIVRATIO( + mci_readl(slot->host, CLKSEL)); + } mci_writel(slot->host, UHS_REG, regs); @@ -2074,6 +2088,20 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) if (of_get_property(np, of_quriks[idx].quirk, NULL)) pdata->quirks |= of_quriks[idx].id; + if (of_property_read_u32_array(dev->of_node, + "samsung,dw-mshc-sdr-timing", timing, 3)) + host->sdr_timing = DW_MCI_DEF_SDR_TIMING; + else + host->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], + timing[1], timing[2]); + + if (of_property_read_u32_array(dev->of_node, + "samsung,dw-mshc-ddr-timing", timing, 3)) + host->ddr_timing = DW_MCI_DEF_DDR_TIMING; + else + host->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], + timing[1], timing[2]); + if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth)) dev_info(dev, "fifo-depth property not found, using " "value of FIFOTH register as default\n"); diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 8b8862b..4b7e42b 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -53,6 +53,7 @@ #define SDMMC_IDINTEN 0x090 #define SDMMC_DSCADDR 0x094 #define SDMMC_BUFADDR 0x098 +#define SDMMC_CLKSEL 0x09C /* specific to Samsung Exynos5250 */ #define SDMMC_DATA(x) (x) /* @@ -111,6 +112,7 @@ #define SDMMC_INT_ERROR 0xbfc2 /* Command register defines */ #define SDMMC_CMD_START BIT(31) +#define SDMMC_USE_HOLD_REG BIT(29) #define SDMMC_CMD_CCS_EXP BIT(23) #define SDMMC_CMD_CEATA_RD BIT(22) #define SDMMC_CMD_UPD_CLK BIT(21) @@ -142,6 +144,17 @@ /* Version ID register define */ #define SDMMC_GET_VERID(x) ((x) & 0xFFFF) +#define DW_MCI_DEF_SDR_TIMING 0x03030002 +#define DW_MCI_DEF_DDR_TIMING 0x03020001 +#define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 3) << 0) +#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 3) << 16) +#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 3) << 24) +#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_GET_DIVRATIO(x) ((((x) >> 24) & 0x7) + 1) +#define SDMMC_CLKSEL_GET_SELCLK_DRV(x) (((x) >> 16) & 0x7) + /* Register access macros */ #define mci_readl(dev, reg) \ __raw_readl((dev)->regs + SDMMC_##reg) diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 71d2b56..6e6d036 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -82,6 +82,8 @@ struct mmc_data; * @biu_clk: Pointer to bus interface unit clock instance. * @ciu_clk: Pointer to card interface unit clock instance. * @slot: Slots sharing this MMC controller. + * @sdr_timing: Clock phase shifting for driving and sampling in sdr mode + * @ddr_timing: Clock phase shifting for driving and sampling in ddr mode * @fifo_depth: depth of FIFO. * @data_shift: log2 of FIFO item size. * @part_buf_start: Start index in part_buf. @@ -166,6 +168,10 @@ struct dw_mci { struct clk *ciu_clk; struct dw_mci_slot *slot[MAX_MCI_SLOTS]; + /* Phase Shift Value (for exynos5250 variant) */ + u32 sdr_timing; + u32 ddr_timing; + /* FIFO push and pull */ int fifo_depth; int data_shift;