From patchwork Mon Oct 24 16:46:26 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ahaslam@baylibre.com X-Patchwork-Id: 685995 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3t2j0Q3xy0z9t1L for ; Tue, 25 Oct 2016 03:48:38 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b=FBVsWaVs; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965409AbcJXQsY (ORCPT ); Mon, 24 Oct 2016 12:48:24 -0400 Received: from mail-wm0-f47.google.com ([74.125.82.47]:38828 "EHLO mail-wm0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S938729AbcJXQqw (ORCPT ); Mon, 24 Oct 2016 12:46:52 -0400 Received: by mail-wm0-f47.google.com with SMTP id c78so125390574wme.1 for ; Mon, 24 Oct 2016 09:46:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZMOgpersub2qE25F2Z+ellTx7Jh6+343sQp42wIICXE=; b=FBVsWaVs2FTg2lEKWAn+arrxvYo0rrnd4ekwigeHeS1ggqAUU4/uXOV8SPHOWwpNuJ q1z4TBcMn+42im4HdcfF2hRvSezdMf40yLBYbgUJ+Z2OSOwlgANdxXsDIyEHzUhIrWbq 03PZM3JeK/UpPKUDLxnV26zgVeFuVPEt82huk3C/ebXX0Tz0TGnJGNus4tsizoUgUyFk w9qVYhxHd8Yco7EpmIAtrlVftnasbZG00ZJBZTvmDW9XdGjl7adjxk36Ub/1jSxZYwqS FIlXRsL2O0aFoczwgB6oNSlR1AbZrihfbNCQ14u18IlEWsTGZTQSjDwwgkE4eQiSVi6N eM2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ZMOgpersub2qE25F2Z+ellTx7Jh6+343sQp42wIICXE=; b=EjNVqUhvCnemg6YI2ixphlmjdT0/8NAfE0GjOIJmJmjFwsvg6yZiLmpw0R3yMc4gm6 jvrMMIzpvErfRPp+q+2kktM5MMtrgQJrNqBXBh6pKzAdQVVJ/31npN+GcqyKRdpPTQt+ rb7q4oJXzhds1UNDRq4P5ZWUWMbTKhfjk7D5ukif8bqdyA9orV+s8XB2iqHUQBajq6rP IEo3Zvfx7N6ld9AUsAoX+3I92yJkgMKRmXoE677ErfHVlBnyAUSMUNvsU6oWkGWNaQst Nk9nXHEMPp6HSZOZ3dJq1n6uEjfq6S91bRIC3b1TDHB6hX6/R/SMT7gh1zTfFrnVaTYl zCEg== X-Gm-Message-State: AA6/9Rkh72Ls5Wn2HMNbiu1ngR1QMFmAuiCH2ACwme/M88hkVZ5qz/DNA5qcKI5rYqJ/RlGD X-Received: by 10.28.224.139 with SMTP id x133mr24638975wmg.6.1477327610297; Mon, 24 Oct 2016 09:46:50 -0700 (PDT) Received: from localhost.localdomain ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id o62sm15710148wmg.9.2016.10.24.09.46.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 24 Oct 2016 09:46:49 -0700 (PDT) From: ahaslam@baylibre.com To: gregkh@linuxfoundation.org, johan@kernel.org, robh+dt@kernel.org, nsekhar@ti.com, stern@rowland.harvard.edu, khilman@baylibre.com, sshtylyov@ru.mvista.com, david@lechnology.com, manjunath.goudar@linaro.org, broonie@kernel.org, abailon@baylibre.com Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Axel Haslam Subject: [PATCH/RFT v2 09/17] regulator: fixed: Add over current event Date: Mon, 24 Oct 2016 18:46:26 +0200 Message-Id: <20161024164634.4330-10-ahaslam@baylibre.com> X-Mailer: git-send-email 2.10.1.502.g6598894 In-Reply-To: <20161024164634.4330-1-ahaslam@baylibre.com> References: <20161024164634.4330-1-ahaslam@baylibre.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Axel Haslam Some regulator supplies have an over-current pin that is activated when the hw detects an over current condition. When this happens, the hardware enters a current limited mode. Extend the fixed regulator driver with the ability to handle irq's from the over-current pin and report an over current event to the consumers via a regulator notifier. Also, add device tree bindings to allow to pass a gpio for over current monitoring. Signed-off-by: Axel Haslam --- .../bindings/regulator/fixed-regulator.txt | 4 ++ drivers/regulator/fixed.c | 64 ++++++++++++++++++++++ include/linux/regulator/consumer.h | 5 ++ include/linux/regulator/fixed.h | 3 + 4 files changed, 76 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt index 4fae41d..d20bf67 100644 --- a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt @@ -11,6 +11,8 @@ If this property is missing, the default assumed is Active low. - gpio-open-drain: GPIO is open drain type. If this property is missing then default assumption is false. -vin-supply: Input supply name. +- oc-gpio: Input gpio that signals an over current condition +- oc-active-high: The polarity of the over current pin is high Any property defined as part of the core regulator binding, defined in regulator.txt, can also be used. @@ -26,9 +28,11 @@ Example: regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; gpio = <&gpio1 16 0>; + oc-gpio = <&gpio1 18 0>; startup-delay-us = <70000>; enable-active-high; regulator-boot-on; gpio-open-drain; + oc-active-high; vin-supply = <&parent_reg>; }; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 988a747..e7964bb 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -30,10 +30,14 @@ #include #include #include +#include struct fixed_voltage_data { struct regulator_desc desc; struct regulator_dev *dev; + int oc_gpio; + unsigned has_oc_gpio:1; + unsigned oc_high:1; }; @@ -82,6 +86,14 @@ struct fixed_voltage_data { if ((config->gpio < 0) && (config->gpio != -ENOENT)) return ERR_PTR(config->gpio); + config->oc_gpio = of_get_named_gpio(np, "oc-gpio", 0); + if (config->oc_gpio >= 0) + config->has_oc_gpio = true; + else if (config->oc_gpio != -ENOENT) + return ERR_PTR(config->oc_gpio); + + config->oc_high = of_property_read_bool(np, "oc-active-high"); + of_property_read_u32(np, "startup-delay-us", &config->startup_delay); config->enable_high = of_property_read_bool(np, "enable-active-high"); @@ -94,7 +106,34 @@ struct fixed_voltage_data { return config; } +static irqreturn_t reg_fixed_overcurrent_irq(int irq, void *data) +{ + struct fixed_voltage_data *drvdata = data; + + regulator_notifier_call_chain(drvdata->dev, + REGULATOR_EVENT_OVER_CURRENT, NULL); + + return IRQ_HANDLED; +} + +static unsigned int reg_fixed_get_mode(struct regulator_dev *rdev) +{ + struct fixed_voltage_data *drvdata = rdev_get_drvdata(rdev); + unsigned int ret = REGULATOR_MODE_NORMAL; + int oc_value; + + if (!drvdata->has_oc_gpio) + return ret; + + oc_value = gpio_get_value(drvdata->oc_gpio); + if ((oc_value && drvdata->oc_high) || (!oc_value && !drvdata->oc_high)) + ret = REGULATOR_MODE_OVERCURRENT; + + return ret; +} + static struct regulator_ops fixed_voltage_ops = { + .get_mode = reg_fixed_get_mode, }; static int reg_fixed_voltage_probe(struct platform_device *pdev) @@ -175,6 +214,31 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) cfg.driver_data = drvdata; cfg.of_node = pdev->dev.of_node; + if (config->has_oc_gpio && gpio_is_valid(config->oc_gpio)) { + ret = devm_gpio_request_one(&pdev->dev, + config->oc_gpio, + GPIOF_DIR_IN, "oc_gpio"); + if (ret) { + pr_err("Failed to request gpio: %d\n", ret); + return ret; + } + + ret = devm_request_threaded_irq(&pdev->dev, + gpio_to_irq(config->oc_gpio), NULL, + reg_fixed_overcurrent_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + "over_current", drvdata); + if (ret) { + pr_err("Failed to request irq: %d\n", ret); + return ret; + } + + drvdata->oc_gpio = config->oc_gpio; + drvdata->oc_high = config->oc_high; + drvdata->has_oc_gpio = config->has_oc_gpio; + } + drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 6921082..9269217 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -74,6 +74,10 @@ * the most noisy and may not be able to handle fast load * switching. * + * OVERCURRENT Regulator has detected an overcurrent condition, and + * may be limiting the supply output. + * + * * NOTE: Most regulators will only support a subset of these modes. Some * will only just support NORMAL. * @@ -84,6 +88,7 @@ #define REGULATOR_MODE_NORMAL 0x2 #define REGULATOR_MODE_IDLE 0x4 #define REGULATOR_MODE_STANDBY 0x8 +#define REGULATOR_MODE_OVERCURRENT 0x10 /* * Regulator notifier events. diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h index 48918be..79357be 100644 --- a/include/linux/regulator/fixed.h +++ b/include/linux/regulator/fixed.h @@ -50,10 +50,13 @@ struct fixed_voltage_config { const char *input_supply; int microvolts; int gpio; + int oc_gpio; unsigned startup_delay; unsigned gpio_is_open_drain:1; unsigned enable_high:1; unsigned enabled_at_boot:1; + unsigned has_oc_gpio:1; + unsigned oc_high:1; struct regulator_init_data *init_data; };