From patchwork Thu Jul 12 12:54:28 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: 9960 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 8082F23E3D for ; Thu, 12 Jul 2012 12:40:57 +0000 (UTC) Received: from mail-gg0-f180.google.com (mail-gg0-f180.google.com [209.85.161.180]) by fiordland.canonical.com (Postfix) with ESMTP id 50504A186D4 for ; Thu, 12 Jul 2012 12:40:57 +0000 (UTC) Received: by mail-gg0-f180.google.com with SMTP id f1so2530971ggn.11 for ; Thu, 12 Jul 2012 05:40:57 -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:x-auditid :from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-brightmail-tracker:x-tm-as-mml:x-gm-message-state; bh=zGAOAyHgINc6P5GIJny9CJLRsvo3SDJIFlwVdobFQqY=; b=NYK9qI0madhMDJoVnfoQOGi/wJOWQVa36OB5mqvTVQd9nuzot0nUjztRLT7eCUB2k6 h9XG/Tn/Wb6IrfzkK7k2i7uXL6xNx5cUDqbmRTvLIqSrnwyoRtRZBij1eL0HdL7DoNvS xw8jRXIrxEaSGANhY7IsVdBlU9rfnuypPojS+lutVeVsnm48NEWLLjS00ZQzaIn7MNyv j9gg5NevivEjb9aZbP9/nlZaCwVxWZUhVeK9YJrAXJfM/xXIxtp15tYThZY9s3/tocTK BBcy+vXWZbd6cfdaDiC814oszs46QJv4wc1Swf3Arm5CR0u2UrmA0O61p86oAVa9vwGJ FxMg== Received: by 10.50.160.198 with SMTP id xm6mr17530754igb.0.1342096856786; Thu, 12 Jul 2012 05:40:56 -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.241.2 with SMTP id lc2csp2598ibb; Thu, 12 Jul 2012 05:40:56 -0700 (PDT) Received: by 10.66.78.42 with SMTP id y10mr89999825paw.31.1342096855989; Thu, 12 Jul 2012 05:40:55 -0700 (PDT) Received: from mailout2.samsung.com (mailout2.samsung.com. [203.254.224.25]) by mx.google.com with ESMTP id hw8si8882523pbc.86.2012.07.12.05.40.55; Thu, 12 Jul 2012 05:40:55 -0700 (PDT) Received-SPF: neutral (google.com: 203.254.224.25 is neither permitted nor denied by best guess record for domain of thomas.abraham@linaro.org) client-ip=203.254.224.25; Authentication-Results: mx.google.com; spf=neutral (google.com: 203.254.224.25 is neither permitted nor denied by best guess record for domain of thomas.abraham@linaro.org) smtp.mail=thomas.abraham@linaro.org Received: from epcpsbgm2.samsung.com (mailout2.samsung.com [203.254.224.25]) by mailout2.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0M71003DOSJUSDB0@mailout2.samsung.com> for patches@linaro.org; Thu, 12 Jul 2012 21:40:54 +0900 (KST) X-AuditID: cbfee61b-b7f566d000005c8a-df-4ffec5d63758 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id D3.5E.23690.6D5CEFF4; Thu, 12 Jul 2012 21:40:54 +0900 (KST) Received: from localhost.localdomain ([107.108.73.37]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0M7100BYUSJJH720@mmp1.samsung.com> for patches@linaro.org; Thu, 12 Jul 2012 21:40:54 +0900 (KST) 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 v3 6/6] mmc: dw_mmc: add samsung exynos5250 specific extentions Date: Thu, 12 Jul 2012 18:24:28 +0530 Message-id: <1342097668-25243-7-git-send-email-thomas.abraham@linaro.org> X-Mailer: git-send-email 1.6.6.rc2 In-reply-to: <1342097668-25243-1-git-send-email-thomas.abraham@linaro.org> References: <1342097668-25243-1-git-send-email-thomas.abraham@linaro.org> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrEJMWRmVeSWpSXmKPExsVy+t9jAd1rR//5G1xeI2sx5fAXFgdGjzvX 9rAFMEZx2aSk5mSWpRbp2yVwZSzcup2p4JR/xe3bt9gaGHc4dDFyckgImEjMP/yEHcIWk7hw bz1bFyMXh5DAIkaJ67N2M0E4c5kkZh9aywJSxSZgIPFo4TuwDhEBJ4klcycwgxQxC9xhlHg0 6yRjFyMHh7CAv0THqwCQGhYBVYm789eygti8Ap4SJ9a+Y4XYpiSxofcoE4jNKeAlcX1lCytI qxBQzas/DhMYeRcwMqxiFE0tSC4oTkrPNdIrTswtLs1L10vOz93ECPb5M+kdjKsaLA4xCnAw KvHwPtj0z1+INbGsuDL3EKMEB7OSCG9/LlCINyWxsiq1KD++qDQntfgQozQHi5I4r4n3V38h gfTEktTs1NSC1CKYLBMHp1QDo8D21q5qu21Pyj8WyR9//+eRN9eCu0ZHVkwyW/N21pGtN5S5 r/NbGh4Jvp861cxL8vSs9l8CkYVq3y4ZZE9fdlSoY2Pu7PfX7pTGBkSwyfy4t6r2+j+RMskY gZsfow7dfWZyTbGzoXvnpq7U/isGzmz9lsf6/k9hyZz//NKRB3WC3oasN64tz1BiKc5INNRi LipOBAASm/gN9QEAAA== X-TM-AS-MML: No X-Gm-Message-State: ALoCoQlc5U31EZgQ/qyXuAvNgI+qNOBuAEgHj6H75FOafxK8TJhCRgNeySyJG+Q1Yvq6TzE5b7AK 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 | 38 ++++++++++++++++++- drivers/mmc/host/dw_mmc-pltfm.c | 15 +++++++ drivers/mmc/host/dw_mmc.c | 40 +++++++++++++++++++- drivers/mmc/host/dw_mmc.h | 14 +++++++ include/linux/mmc/dw_mmc.h | 6 +++ 5 files changed, 110 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt index 3acd6c9..69d78c1 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 - snps,dw-mshc: for controllers compliant with synopsis dw-mshc. + - samsung,exynos5250-dw-mshc: for controllers with Samsung + Exynos5250 specific extentions. * reg: physical base address of the dw-mshc controller and size of its memory region. @@ -74,13 +76,45 @@ Aliases: the following format 'mshc{n}' where n is a unique number for the alias. +Samsung Exynos4/5 specific properties: + +Some of the variants of Exynos4 (such as Exynos4412) and Exynos5 SoC's +includes few extensions to the Synopsis Designware Mobile Storage Host +Controller. The following properties are used to describe those extensions. + +* 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 (applicable only for Exynos5 + SoC's, should be zero for Exynos4 SoC's) + - 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 for Exynos5250: + + - 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 = "snps,dw-mshc"; + compatible = "samsung,exynos5250-dw-mshc"; reg = <0x12200000 0x1000>; interrupts = <0 75 0>; #address-cells = <1>; @@ -94,6 +128,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>; slot@0 { reg = <0>; diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 8d24f6d..900f412 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -27,9 +27,24 @@ static struct dw_mci_drv_data synopsis_drv_data = { .ctrl_type = DW_MCI_TYPE_SYNOPSIS, }; +static unsigned long exynos5250_dwmmc_caps[4] = { + MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | + MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, +}; + +static struct dw_mci_drv_data exynos5250_drv_data = { + .ctrl_type = DW_MCI_TYPE_EXYNOS5250, + .caps = exynos5250_dwmmc_caps, +}; + static const struct of_device_id dw_mci_pltfm_match[] = { { .compatible = "snps,dw-mshc", .data = (void *)&synopsis_drv_data, }, + { .compatible = "samsung,exynos5250-dw-mshc", + .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 3bc276d..bbf1209 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,17 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) cmdr |= SDMMC_CMD_DAT_WR; } + /* + * Samsung Exynos5250 extends the use of CMD register with the use of + * bit 29 (which is reserved on standard MSHC controllers) for + * optionally bypassing the HOLD register for command and data. The + * HOLD register should be bypassed in case there is no phase shift + * applied on CMD/DATA that is sent to the card. + */ + if (slot->host->drv_data->ctrl_type == DW_MCI_TYPE_EXYNOS5250) + if (SDMMC_CLKSEL_GET_SELCLK_DRV(mci_readl(slot->host, CLKSEL))) + cmdr |= SDMMC_CMD_USE_HOLD_REG; + return cmdr; } @@ -802,10 +814,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); @@ -2086,6 +2107,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) struct dw_mci_board *pdata; struct device *dev = host->dev; struct device_node *np = dev->of_node; + u32 timing[3]; int idx, cnt; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); @@ -2108,6 +2130,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 1ecaa02..6c17282 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_CMD_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) @@ -184,6 +197,7 @@ extern int dw_mci_resume(struct dw_mci *host); /* Variations in the dw_mci controller */ #define DW_MCI_TYPE_SYNOPSIS 0 +#define DW_MCI_TYPE_EXYNOS5250 1 /* Samsung Exynos5250 Extensions */ /* dw_mci platform driver data */ struct dw_mci_drv_data { diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index ae45e4f..32c778f 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;