From patchwork Wed Jun 1 08:02:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Krzysztof Kozlowski X-Patchwork-Id: 9146319 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6A69760751 for ; Wed, 1 Jun 2016 08:11:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 59CAD20410 for ; Wed, 1 Jun 2016 08:11:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4D2282654B; Wed, 1 Jun 2016 08:11:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4AD2C20410 for ; Wed, 1 Jun 2016 08:11:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757745AbcFAIKK (ORCPT ); Wed, 1 Jun 2016 04:10:10 -0400 Received: from mailout3.w1.samsung.com ([210.118.77.13]:57869 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757270AbcFAICy (ORCPT ); Wed, 1 Jun 2016 04:02:54 -0400 Received: from eucpsbgm2.samsung.com (unknown [203.254.199.245]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0O8300MBC2CPET40@mailout3.w1.samsung.com>; Wed, 01 Jun 2016 09:02:49 +0100 (BST) X-AuditID: cbfec7f5-f792a6d000001302-05-574e96a9df6d Received: from eusync3.samsung.com ( [203.254.199.213]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id 68.1E.04866.9A69E475; Wed, 1 Jun 2016 09:02:49 +0100 (BST) Received: from AMDC2174.DIGITAL.local ([106.120.53.17]) by eusync3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0O830012K2CGIS90@eusync3.samsung.com>; Wed, 01 Jun 2016 09:02:49 +0100 (BST) From: Krzysztof Kozlowski To: hzpeterchen@gmail.com, Ulf Hansson , Sebastian Reichel , Dmitry Eremin-Solenikov , David Woodhouse , Krzysztof Kozlowski , Javier Martinez Canillas , linux-kernel@vger.kernel.org, linux-mmc@vger.kernel.org, linux-pm@vger.kernel.or, Alan Stern , linux-usb@vger.kernel.org, Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , Kukjin Kim , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org Cc: Greg Kroah-Hartman , Bartlomiej Zolnierkiewicz Subject: [PATCH v3 06/12] power: pwrseq: simple: Add support for regulator and generic property Date: Wed, 01 Jun 2016 10:02:15 +0200 Message-id: <1464768141-25420-7-git-send-email-k.kozlowski@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1464768141-25420-1-git-send-email-k.kozlowski@samsung.com> References: <1464768141-25420-1-git-send-email-k.kozlowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupmkeLIzCtJLcpLzFFi42I5/e/4Vd2V0/zCDZ7PZbXYOGM9q8WkJ++Z LeYfOcdqMXHlZGaL/jcLWS2aF69ns+i6uonN4tyrlYwWb96uYbJ4/cLQov/xa2aLTY+vsVpc 3jWHzeLI/35Gi5kXV7NYzDi/j8li0bJWZoul1y8yWUyYvpbFonXvEXaL07tLLCb8vsBmcXxt uIO4x5p5axg9Lvf1MnnsnHWX3WPl8i9sHptXaHlsWtXJ5nHn2h42j/1z17B7bF5S77GlH6hg 9t0fjB59W1Yxehz5Op3F4/MmuQC+KC6blNSczLLUIn27BK6MFWu/MRa8Ma34t0qkgfGFdhcj J4eEgInEi81zmCBsMYkL99azdTFycQgJLGWUOPRjOzOE08gk0f3wATNIFZuAscTm5UvAqkQE OtgkNm19ww6SYBbIljh17z0riC0skCjxZP17oLEcHCwCqhInn1aBhHkF3CUWtT1nhNgmJ3Hy 2GSwck4BD4kTE/6DxYWAahqnTWadwMi7gJFhFaNoamlyQXFSeq6RXnFibnFpXrpecn7uJkZI FH3dwbj0mNUhRgEORiUe3orLvuFCrIllxZW5hxglOJiVRHgFJ/uFC/GmJFZWpRblxxeV5qQW H2KU5mBREueduet9iJBAemJJanZqakFqEUyWiYNTqoHxyodNj0/UmXccUVw0c5eNws+nYUeP R75+FG+lF7Sp6fxh54vPV9adFptYqPP15K/UcxvWX2vuPvvnTWbkIv+UH0wLZ1dz3LkZeSnj a1zqkmitec0Benc1l4eXlMXceG98dIrMcY61UybE3DM2q/Ky7DM4v6H/7LfyXacXqhQVzlc9 1lhbP/+WhRJLcUaioRZzUXEiALNIrJSeAgAA Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some devices need real hard-reset by cutting the power. During power sequence turn off and on the regulator, if it is provided. Additionally add support for instantiating the pwrseq-simple device on a generic property 'power-sequence'. The device will attach itself to the node containing the property and parse the node's properties like reset-gpios, ext-supply etc. Signed-off-by: Krzysztof Kozlowski --- .../bindings/power/pwrseq/pwrseq-simple.txt | 29 +++++++- drivers/power/pwrseq/pwrseq_simple.c | 85 +++++++++++++++++++++- 2 files changed, 107 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/power/pwrseq/pwrseq-simple.txt b/Documentation/devicetree/bindings/power/pwrseq/pwrseq-simple.txt index ce0e76749671..a8c3f13ee83f 100644 --- a/Documentation/devicetree/bindings/power/pwrseq/pwrseq-simple.txt +++ b/Documentation/devicetree/bindings/power/pwrseq/pwrseq-simple.txt @@ -1,11 +1,17 @@ -* The simple MMC power sequence provider +* The simple power sequence provider -The purpose of the simple MMC power sequence provider is to supports a set of +The purpose of the simple power sequence provider is to supports a set of common properties between various SOC designs. It thus enables us to use the same provider for several SOC designs. -Required properties: -- compatible : contains "mmc-pwrseq-simple". +The driver supports two types of bindings: +1. Separate node + Required properties: + - compatible : contains "mmc-pwrseq-simple". + +2. Property for any node + Required properties: + - power-sequence Optional properties: - reset-gpios : contains a list of GPIO specifiers. The reset GPIOs are asserted @@ -16,6 +22,7 @@ Optional properties: See ../clocks/clock-bindings.txt for details. - clock-names : Must include the following entry: "ext_clock" (External clock provided to the card). +- ext-supply : External regulator supply Example: @@ -24,4 +31,18 @@ Example: reset-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; clocks = <&clk_32768_ck>; clock-names = "ext_clock"; + ext-supply = <&buck8>; } + + usb3503@08 { + compatible = "smsc,usb3503"; + reg = <0x08>; + + intn-gpios = <&gpx3 0 GPIO_ACTIVE_HIGH>; + connect-gpios = <&gpx3 4 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpx3 5 GPIO_ACTIVE_HIGH>; + initial-mode = <1>; + + power-sequence; + ext-supply = <&buck8_reg>; + }; diff --git a/drivers/power/pwrseq/pwrseq_simple.c b/drivers/power/pwrseq/pwrseq_simple.c index 93807a6ef162..4096261b16a4 100644 --- a/drivers/power/pwrseq/pwrseq_simple.c +++ b/drivers/power/pwrseq/pwrseq_simple.c @@ -1,12 +1,15 @@ /* - * Copyright (C) 2014 Linaro Ltd + * Copyright (C) 2014 Linaro Ltd + * Copyright (C) 2016 Samsung Electronics * * Author: Ulf Hansson + * Krzysztof Kozlowski * * License terms: GNU General Public License (GPL) version 2 * * Simple MMC power sequence management */ +#include #include #include #include @@ -16,13 +19,16 @@ #include #include #include +#include #include +#include struct mmc_pwrseq_simple { struct pwrseq pwrseq; bool clk_enabled; struct clk *ext_clk; struct gpio_descs *reset_gpios; + struct regulator *ext_reg; }; #define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq) @@ -60,6 +66,13 @@ static void mmc_pwrseq_simple_post_power_on(struct pwrseq *_pwrseq) { struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(_pwrseq); + if (pwrseq->ext_reg) { + int err; + + err = regulator_enable(pwrseq->ext_reg); + WARN_ON_ONCE(err); + } + mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); } @@ -73,6 +86,13 @@ static void mmc_pwrseq_simple_power_off(struct pwrseq *_pwrseq) clk_disable_unprepare(pwrseq->ext_clk); pwrseq->clk_enabled = false; } + + if (pwrseq->ext_reg) { + int err; + + err = regulator_disable(pwrseq->ext_reg); + WARN_ON_ONCE(err); + } } static const struct pwrseq_ops mmc_pwrseq_simple_ops = { @@ -100,12 +120,40 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev) if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT) return PTR_ERR(pwrseq->ext_clk); + pwrseq->ext_reg = devm_regulator_get_optional(dev, "ext"); + if (IS_ERR(pwrseq->ext_reg)) { + if (PTR_ERR(pwrseq->ext_reg) == -ENODEV) + pwrseq->ext_reg = NULL; + else + return PTR_ERR(pwrseq->ext_reg); + } else { + int err; + /* + * Be sure that regulator is off, before the driver will start + * power sequence. It is likely that regulator is on by default + * and it without toggling it here, it would be disabled much + * later by the core. + */ + + err = regulator_enable(pwrseq->ext_reg); + WARN_ON_ONCE(err); + + err = regulator_disable(pwrseq->ext_reg); + WARN_ON_ONCE(err); + } + pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(pwrseq->reset_gpios) && PTR_ERR(pwrseq->reset_gpios) != -ENOENT && PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) { - return PTR_ERR(pwrseq->reset_gpios); + /* + * Don't care about errors. If this pwrseq device was added + * to node with existing reset-gpios, then the GPIO reset will + * be handled by other device. + */ + dev_warn(dev, "Cannot get reset gpio: %ld\n", + PTR_ERR(pwrseq->reset_gpios)); } pwrseq->pwrseq.dev = dev; @@ -122,6 +170,13 @@ static int mmc_pwrseq_simple_remove(struct platform_device *pdev) pwrseq_unregister(&pwrseq->pwrseq); + if (pwrseq->ext_reg) { + int err; + + err = regulator_disable(pwrseq->ext_reg); + WARN_ON_ONCE(err); + } + return 0; } @@ -134,5 +189,29 @@ static struct platform_driver mmc_pwrseq_simple_driver = { }, }; -module_platform_driver(mmc_pwrseq_simple_driver); +static int __init mmc_pwrseq_simple_driver_init(void) +{ + struct platform_device *pdev; + struct device_node *np; + + for_each_node_with_property(np, "power-sequence") { + pdev = platform_device_register_simple("pwrseq_simple", + PLATFORM_DEVID_AUTO, + NULL, 0); + if (!IS_ERR(pdev)) { + of_node_get(np); + pdev->dev.of_node = np; + } + } + + return platform_driver_register(&mmc_pwrseq_simple_driver); +} +module_init(mmc_pwrseq_simple_driver_init); + +static void __exit mmc_pwrseq_simple_driver_exit(void) +{ + /* FIXME: of_node_put? */ + platform_driver_unregister(&mmc_pwrseq_simple_driver); +} +module_exit(mmc_pwrseq_simple_driver_exit); MODULE_LICENSE("GPL v2");