From patchwork Fri May 24 15:41:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dinh Nguyen X-Patchwork-Id: 2611831 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork2.kernel.org (Postfix) with ESMTP id B582BDFF68 for ; Fri, 24 May 2013 15:43:06 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Ufu7R-0004kz-5U; Fri, 24 May 2013 15:41:27 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Ufu6j-00021t-J6; Fri, 24 May 2013 15:40:41 +0000 Received: from tx2ehsobe002.messaging.microsoft.com ([65.55.88.12] helo=tx2outboundpool.messaging.microsoft.com) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Ufu5u-0001vK-Cl for linux-arm-kernel@lists.infradead.org; Fri, 24 May 2013 15:39:56 +0000 Received: from mail160-tx2-R.bigfish.com (10.9.14.247) by TX2EHSOBE007.bigfish.com (10.9.40.27) with Microsoft SMTP Server id 14.1.225.23; Fri, 24 May 2013 15:39:29 +0000 Received: from mail160-tx2 (localhost [127.0.0.1]) by mail160-tx2-R.bigfish.com (Postfix) with ESMTP id EE47D1C0687; Fri, 24 May 2013 15:39:29 +0000 (UTC) X-Forefront-Antispam-Report: CIP:66.35.236.232; KIP:(null); UIP:(null); IPV:NLI; H:SJ-ITEXEDGE02.altera.priv.altera.com; RD:none; EFVD:NLI X-SpamScore: 3 X-BigFish: VS3(zzc8kzz1f42h1ee6h1de0h1fdah1202h1e76h1d1ah1d2ah1fc6hzz8275bh8275dh8275chz2fh2a8h668h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h14ddh1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1d0ch1d2eh1d3fh1155h) Received-SPF: pass (mail160-tx2: domain of altera.com designates 66.35.236.232 as permitted sender) client-ip=66.35.236.232; envelope-from=dinguyen@altera.com; helo=SJ-ITEXEDGE02.altera.priv.altera.com ; v.altera.com ; Received: from mail160-tx2 (localhost.localdomain [127.0.0.1]) by mail160-tx2 (MessageSwitch) id 1369409966919855_14466; Fri, 24 May 2013 15:39:26 +0000 (UTC) Received: from TX2EHSMHS023.bigfish.com (unknown [10.9.14.253]) by mail160-tx2.bigfish.com (Postfix) with ESMTP id DC4DF3E004E; Fri, 24 May 2013 15:39:26 +0000 (UTC) Received: from SJ-ITEXEDGE02.altera.priv.altera.com (66.35.236.232) by TX2EHSMHS023.bigfish.com (10.9.99.123) with Microsoft SMTP Server (TLS) id 14.1.225.23; Fri, 24 May 2013 15:39:26 +0000 Received: from sj-mail01.altera.com (137.57.1.6) by SJ-ITEXEDGE02.altera.priv.altera.com (66.35.236.232) with Microsoft SMTP Server id 8.3.298.1; Fri, 24 May 2013 08:29:29 -0700 Received: from linux-builds1.altera.com (linux-builds1.altera.com [137.57.188.121]) by sj-mail01.altera.com (8.13.7+Sun/8.13.7) with ESMTP id r4OFdG4A015120; Fri, 24 May 2013 08:39:24 -0700 (PDT) From: To: Subject: [PATCHv4 6/6] mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA Date: Fri, 24 May 2013 10:41:20 -0500 Message-ID: <1369410080-436-6-git-send-email-dinguyen@altera.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1369410080-436-1-git-send-email-dinguyen@altera.com> References: <1369410080-436-1-git-send-email-dinguyen@altera.com> MIME-Version: 1.0 X-OriginatorOrg: altera.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130524_113950_539044_E404D459 X-CRM114-Status: GOOD ( 23.44 ) X-Spam-Score: -4.2 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [65.55.88.12 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: dinh.linux@gmail.com, Arnd Bergmann , Seungwon Jeon , Pavel Machek , linux-mmc@vger.kernel.org, Jaehoon Chung , Olof Johansson , Dinh Nguyen X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Dinh Nguyen Add platform specific functionality for the DW SD/MMC driver for SoCFPGA. Move SDMMC_CMD_USE_HOLD_REG to dw_mmc.h so other platforms can use this define. Signed-off-by: Dinh Nguyen CC: Seungwon Jeon CC: Jaehoon Chung CC: Arnd Bergmann CC: Olof Johansson CC: Pavel Machek CC: linux-mmc@vger.kernel.org v4: - Fix up SYSMGR_SDMMC_CTRL_SET macro v3: - Addressed comments from Seugwon, Jaehoon, and Pavel - Use clk_disable_unprepare/clk_prepare_enable v2: - Use syscon and regmap - Avoid divide by zero - Remove the need to set PWR_EN --- drivers/mmc/host/Kconfig | 8 +++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/dw_mmc-exynos.c | 2 - drivers/mmc/host/dw_mmc-socfpga.c | 138 +++++++++++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.h | 1 + 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 drivers/mmc/host/dw_mmc-socfpga.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 9ab8f8d..1be2289 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -556,6 +556,14 @@ config MMC_DW_EXYNOS Synopsys DesignWare Memory Card Interface driver. Select this option for platforms based on Exynos4 and Exynos5 SoC's. +config MMC_DW_SOCFPGA + tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" + depends on MMC_DW + select MMC_DW_PLTFM + help + This selects support for Altera SoCFPGA specific extensions to the + Synopsys DesignWare Memory Card Interface driver. + config MMC_DW_PCI tristate "Synopsys Designware MCI support on PCI bus" depends on MMC_DW && PCI diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index cd32280..67718c1 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_MMC_DW) += dw_mmc.o obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o +obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index f013e7e..866edef 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -31,8 +31,6 @@ SDMMC_CLKSEL_CCLK_DRIVE(y) | \ SDMMC_CLKSEL_CCLK_DIVIDER(z)) -#define SDMMC_CMD_USE_HOLD_REG BIT(29) - #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 diff --git a/drivers/mmc/host/dw_mmc-socfpga.c b/drivers/mmc/host/dw_mmc-socfpga.c new file mode 100644 index 0000000..4c19fd8 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-socfpga.c @@ -0,0 +1,138 @@ +/* + * Altera SoCFPGA Specific Extensions for Synopsys DW Multimedia Card Interface driver + * + * Copyright (C) 2012, Samsung Electronics Co., Ltd. + * Copyright (C) 2013 Altera Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Taken from dw_mmc-exynos.c + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dw_mmc.h" +#include "dw_mmc-pltfm.h" + +#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 +#define DRV_CLK_PHASE_SHIFT_SEL_MASK 0x7 +#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \ + ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0)) + +/* SOCFPGA implementation specific driver private data */ +struct dw_mci_socfpga_priv_data { + u8 ciu_div; /* card interface unit divisor */ + u32 hs_timing; /* bitmask for CIU clock phase shift */ + struct regmap *sysreg; /* regmap for system manager register */ +}; + +static int dw_mci_socfpga_priv_init(struct dw_mci *host) +{ + struct dw_mci_socfpga_priv_data *priv; + + priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + dev_err(host->dev, "mem alloc failed for private data\n"); + return -ENOMEM; + } + + priv->sysreg = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); + if (IS_ERR(priv->sysreg)) { + dev_err(host->dev, "regmap for altr,sys-mgr lookup failed.\n"); + return PTR_ERR(priv->sysreg); + } + host->priv = priv; + + return 0; +} + +static int dw_mci_socfpga_setup_clock(struct dw_mci *host) +{ + struct dw_mci_socfpga_priv_data *priv = host->priv; + + clk_disable_unprepare(host->ciu_clk); + regmap_write(priv->sysreg, SYSMGR_SDMMCGRP_CTRL_OFFSET, priv->hs_timing); + clk_prepare_enable(host->ciu_clk); + + host->bus_hz /= (priv->ciu_div + 1); + return 0; +} + +static void dw_mci_socfpga_prepare_command(struct dw_mci *host, u32 *cmdr) +{ + struct dw_mci_socfpga_priv_data *priv = host->priv; + + if (priv->hs_timing & DRV_CLK_PHASE_SHIFT_SEL_MASK) + *cmdr |= SDMMC_CMD_USE_HOLD_REG; +} + +static int dw_mci_socfpga_parse_dt(struct dw_mci *host) +{ + struct dw_mci_socfpga_priv_data *priv = host->priv; + struct device_node *np = host->dev->of_node; + u32 timing[2]; + u32 div = 0; + int ret; + + ret = of_property_read_u32(np, "altr,dw-mshc-ciu-div", &div); + if (ret) + dev_info(host->dev, "No dw-mshc-ciu-div specified, assuming 1"); + priv->ciu_div = div; + + ret = of_property_read_u32_array(np, + "altr,dw-mshc-sdr-timing", timing, 2); + if (ret) + return ret; + + priv->hs_timing = SYSMGR_SDMMC_CTRL_SET(timing[0], timing[1]); + return 0; +} + +static const struct dw_mci_drv_data socfpga_drv_data = { + .init = dw_mci_socfpga_priv_init, + .setup_clock = dw_mci_socfpga_setup_clock, + .prepare_command = dw_mci_socfpga_prepare_command, + .parse_dt = dw_mci_socfpga_parse_dt, +}; + +static const struct of_device_id dw_mci_socfpga_match[] = { + { .compatible = "altr,socfpga-dw-mshc", + .data = &socfpga_drv_data, }, + {}, +}; +MODULE_DEVICE_TABLE(of, dw_mci_socfpga_match); + +int dw_mci_socfpga_probe(struct platform_device *pdev) +{ + const struct dw_mci_drv_data *drv_data; + const struct of_device_id *match; + + match = of_match_node(dw_mci_socfpga_match, pdev->dev.of_node); + drv_data = match->data; + return dw_mci_pltfm_register(pdev, drv_data); +} + +static struct platform_driver dw_mci_socfpga_pltfm_driver = { + .probe = dw_mci_socfpga_probe, + .remove = __exit_p(dw_mci_pltfm_remove), + .driver = { + .name = "dwmmc_socfpga", + .of_match_table = of_match_ptr(dw_mci_socfpga_match), + .pm = &dw_mci_pltfm_pmops, + }, +}; + +module_platform_driver(dw_mci_socfpga_pltfm_driver); + +MODULE_DESCRIPTION("Altera SOCFPGA Specific DW-MSHC Driver Extension"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:dwmmc-socfpga"); diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 0b74189..3700cb2 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -111,6 +111,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)