From patchwork Tue Jan 27 08:11:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 5715221 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 1701FC058D for ; Tue, 27 Jan 2015 08:12:24 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2356C20211 for ; Tue, 27 Jan 2015 08:12:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2DE1F201FB for ; Tue, 27 Jan 2015 08:12:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757791AbbA0IMU (ORCPT ); Tue, 27 Jan 2015 03:12:20 -0500 Received: from mailout2.w1.samsung.com ([210.118.77.12]:24294 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757583AbbA0IMO (ORCPT ); Tue, 27 Jan 2015 03:12:14 -0500 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout2.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0NIT00KUYTN2OY70@mailout2.w1.samsung.com>; Tue, 27 Jan 2015 08:16:14 +0000 (GMT) X-AuditID: cbfec7f4-b7f126d000001e9a-c7-54c747c9f318 Received: from eusync3.samsung.com ( [203.254.199.213]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id 05.F1.07834.9C747C45; Tue, 27 Jan 2015 08:09:45 +0000 (GMT) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync3.samsung.com (Oracle Communications Messaging Server 7u4-23.01 (7.0.4.23.0) 64bit (built Aug 10 2011)) with ESMTPA id <0NIT00BIXTG6OQ90@eusync3.samsung.com>; Tue, 27 Jan 2015 08:12:10 +0000 (GMT) From: Marek Szyprowski To: linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , Kukjin Kim , Tobias Jakobi , Daniel Drake , Sebastian Reichel , Seungwon Jeon , Jaehoon Chung , Ulf Hansson , Joonyoung Shim Subject: [PATCH 1/2] mmc: dw_mmc-exynos: add support for controlling emmc reset pin Date: Tue, 27 Jan 2015 09:11:28 +0100 Message-id: <1422346289-9348-2-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1422346289-9348-1-git-send-email-m.szyprowski@samsung.com> References: <1422346289-9348-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprALMWRmVeSWpSXmKPExsVy+t/xq7on3Y+HGGx4Z2Ax/8g5VotH8x8z W9z41cZq8eLeRRaL/sevmS0+9x5htJhxfh+TRdfPn2wWa4/cZbc4vbvE4sP9i8wWx9eGO/B4 LPqe5bF40342j02rOtk87lzbw+bRt2UVo8fnTXIBbFFcNimpOZllqUX6dglcGQtX7WQr2KRY 8exLL3sD403pLkYODgkBE4m7Nwu7GDmBTDGJC/fWs3UxcnEICSxllLi+8hkzhNPHJLF7+k1G kCo2AUOJrrddbCC2iECsxMStP8A6mAUeMEn8OzUDrEhYIFTiy7mJTCA2i4CqRNu1vcwg23gF 3CW2z8+F2CYn8f/lCrASTgEPiZ7bU8FsIaCSxQenME1g5F3AyLCKUTS1NLmgOCk911CvODG3 uDQvXS85P3cTIyQUv+xgXHzM6hCjAAejEg/vhIlHQ4RYE8uKK3MPMUpwMCuJ8La5Hg8R4k1J rKxKLcqPLyrNSS0+xMjEwSnVwGj94Osh+aa5web8uVZLyhe0lKovuiK284CC4ZIHKyeq7/Hv er18fbkcZ13euxnpASnr535ZsPyJ1t71daf7H19+/d2xrORmxUaRF09OSW/r/7iI5WKomeBM nTwrX8W1V2ay//zy4tVkYeOuP3Y+4vufRn+J+Fp342ZJ16ywFtU9nMvCv/n/aQ9SYinOSDTU Yi4qTgQAUJpkCiMCAAA= Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There are boards (like Hardkernel's Odroid boards) on which eMMC card's reset line is connected to SoC GPIO line instead of the hardware reset logic. In case of such boards, before performing system reboot, additional reset of eMMC card is required to boot again properly. This patch adds code for handling such cases. Signed-off-by: Marek Szyprowski --- .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 6 +++ drivers/mmc/host/dw_mmc-exynos.c | 43 +++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt index ee4fc0576c7d..fc53d335e7db 100644 --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt @@ -50,6 +50,12 @@ Required Properties: - if CIU clock divider value is 0 (that is divide by 1), both tx and rx phase shift clocks should be 0. +Optional properties: + +* dw-mshc-reset-gpios: optional property specifying gpio for the eMMC nreset + line, it will be triggered on system reboot to properly reset eMMC card for + next system boot. + 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 diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 509365cb22c6..2add5a93859d 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -12,12 +12,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include "dw_mmc.h" #include "dw_mmc-pltfm.h" @@ -77,8 +79,23 @@ struct dw_mci_exynos_priv_data { u32 sdr_timing; u32 ddr_timing; u32 cur_speed; + struct gpio_desc *reset_gpio; + struct notifier_block reset_nb; }; +static int dw_mci_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + struct dw_mci_exynos_priv_data *data; + data = container_of(this, struct dw_mci_exynos_priv_data, reset_nb); + + gpiod_direction_output(data->reset_gpio, 0); + mdelay(150); + gpiod_direction_output(data->reset_gpio, 1); + + return NOTIFY_DONE; +} + static struct dw_mci_exynos_compatible { char *compatible; enum dw_mci_exynos_type ctrl_type; @@ -295,7 +312,20 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host) return ret; priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); + + priv->reset_gpio = devm_gpiod_get_optional(host->dev, + "samsung,dw-mshc-reset", + GPIOD_OUT_HIGH); + if (!IS_ERR_OR_NULL(priv->reset_gpio)) { + priv->reset_nb.notifier_call = dw_mci_restart_handler; + priv->reset_nb.priority = 255; + ret = register_restart_handler(&priv->reset_nb); + if (ret) + dev_err(host->dev, "cannot register restart handler\n"); + } + host->priv = priv; + return 0; } @@ -490,6 +520,17 @@ static int dw_mci_exynos_probe(struct platform_device *pdev) return dw_mci_pltfm_register(pdev, drv_data); } +static int dw_mci_exynos_remove(struct platform_device *pdev) +{ + struct dw_mci *host = platform_get_drvdata(pdev); + struct dw_mci_exynos_priv_data *priv = host->priv; + + if (priv->reset_gpio) + unregister_restart_handler(&priv->reset_nb); + + return dw_mci_pltfm_remove(pdev); +} + static const struct dev_pm_ops dw_mci_exynos_pmops = { SET_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend, dw_mci_exynos_resume) .resume_noirq = dw_mci_exynos_resume_noirq, @@ -499,7 +540,7 @@ static const struct dev_pm_ops dw_mci_exynos_pmops = { static struct platform_driver dw_mci_exynos_pltfm_driver = { .probe = dw_mci_exynos_probe, - .remove = __exit_p(dw_mci_pltfm_remove), + .remove = dw_mci_exynos_remove, .driver = { .name = "dwmmc_exynos", .of_match_table = dw_mci_exynos_match,