From patchwork Thu May 17 15:10:11 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: 8762 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 96F3A23E61 for ; Thu, 17 May 2012 15:01:56 +0000 (UTC) Received: from mail-we0-f180.google.com (mail-we0-f180.google.com [74.125.82.180]) by fiordland.canonical.com (Postfix) with ESMTP id 8E464A186F5 for ; Thu, 17 May 2012 15:01:56 +0000 (UTC) Received: by weyt11 with SMTP id t11so1622178wey.11 for ; Thu, 17 May 2012 08:01:56 -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=fLN8bijXMXhbWAz9JyJVwgmuutFBi3lQieth7c+1rp8=; b=YEUVeh9FzXEXlUYgegHLF9vIOCx+mUUs7b8X0jYEl8ipkmhQy188zpvFukyU/8SMbD yfunX06FHemxrIxA2LZx/m4xr36fbpgoucCn30Zh/kppaDUYe3vsZ3/ZdXZXJIgqFwAw 6c+/9132Zb3KxP/YSimRtmnbmf2fpO+PQjvLYB6U7133Au5Nz7vUYjHvKdoQ2JXamo5l mEyEE2pjcJAnHqHD4SnniJOmeuj74RFf6+KygXfJz239kwfCRGhnrt5zp9L/8O7MmqD8 abYje09ofCSuEHcqUp27KIxHw+meKoXUMsqWPUELD4zFDBhuAxeLOVPJZjNjbQu3OMTs dj1Q== Received: by 10.50.222.202 with SMTP id qo10mr13969302igc.0.1337266916025; Thu, 17 May 2012 08:01: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.35.72 with SMTP id o8csp34328ibd; Thu, 17 May 2012 08:01:49 -0700 (PDT) Received: by 10.68.129.98 with SMTP id nv2mr27948565pbb.140.1337266904958; Thu, 17 May 2012 08:01:44 -0700 (PDT) Received: from mailout2.samsung.com (mailout2.samsung.com. [203.254.224.25]) by mx.google.com with ESMTP id ou2si10365707pbb.9.2012.05.17.08.01.43; Thu, 17 May 2012 08:01:44 -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 <0M46001JD9QRCG30@mailout2.samsung.com> for patches@linaro.org; Fri, 18 May 2012 00:01:42 +0900 (KST) X-AuditID: cbfee61b-b7bb6ae0000006fb-ac-4fb512d66ff0 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (MMPCPMTA) with SMTP id C1.99.01787.6D215BF4; Fri, 18 May 2012 00:01:42 +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 <0M460077M9HVVD80@mmp1.samsung.com> for patches@linaro.org; Fri, 18 May 2012 00:01:42 +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 v2 6/6] mmc: dw_mmc: add samsung exynos5250 specific extentions Date: Thu, 17 May 2012 20:40:11 +0530 Message-id: <1337267411-28226-7-git-send-email-thomas.abraham@linaro.org> X-Mailer: git-send-email 1.6.6.rc2 In-reply-to: <1337267411-28226-1-git-send-email-thomas.abraham@linaro.org> References: <1337267411-28226-1-git-send-email-thomas.abraham@linaro.org> X-Brightmail-Tracker: AAAAAA== X-TM-AS-MML: No X-Gm-Message-State: ALoCoQkwPuns/A93J61VWoLc45LMuRfkh0PycEwItVax/luQ5iQzwEVyogXjLkbpR4HEQaEGqDlJ 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 | 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, 105 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..99b166e 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,40 @@ Aliases: the following format 'mshc{n}' where n is a unique number for the alias. +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 = "snps,dw-mshc"; + compatible = "samsung,exynos5250-dw-mshc"; reg = <0x12200000 0x1000>; interrupts = <0 75 0>; #address-cells = <1>; @@ -94,6 +123,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 0317287..58bab5b 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; } @@ -787,10 +799,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); @@ -2076,6 +2097,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); @@ -2098,6 +2120,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;