Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932549AbcJZTBH (ORCPT ); Wed, 26 Oct 2016 15:01:07 -0400 Received: from mail-wm0-f52.google.com ([74.125.82.52]:35097 "EHLO mail-wm0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932196AbcJZTBA (ORCPT ); Wed, 26 Oct 2016 15:01:00 -0400 From: ahaslam@baylibre.com To: broonie@kernel.org, lgirdwood@gmail.com, khilman@baylibre.com, nsekhar@ti.com, david@lechnology.com Cc: linux-kernel@vger.kernel.org, Axel Haslam Subject: [RFC 2/3] regulator: fixed: Handle optional overcurrent pin Date: Wed, 26 Oct 2016 21:00:53 +0200 Message-Id: <20161026190054.11968-3-ahaslam@baylibre.com> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20161026190054.11968-1-ahaslam@baylibre.com> References: <20161026190054.11968-1-ahaslam@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3163 Lines: 112 From: Axel Haslam Fixed regulators (ex. TPS2087D) may have a over current pin that is activated when an over current condition is detected. Consumers may be interested to know about the status changes of this pin to disable the regulator and notify framework layers or userspace. Allow the fix regulator to take in an optional gpio pin to send the event changes to the consumer. Signed-off-by: Axel Haslam --- drivers/regulator/fixed.c | 47 +++++++++++++++++++++++++++++++++++++++++ include/linux/regulator/fixed.h | 3 +++ 2 files changed, 50 insertions(+) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 988a747..9937139 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; }; @@ -94,6 +98,22 @@ struct fixed_voltage_data { return config; } +static irqreturn_t reg_fixed_overcurrent_irq(int irq, void *data) +{ + struct fixed_voltage_data *drvdata = data; + unsigned long event = REGULATOR_EVENT_OVER_CURRENT_CHANGE; + int oc_value; + + oc_value = gpio_get_value_cansleep(drvdata->oc_gpio); + if (oc_value == drvdata->oc_high) + event |= REGULATOR_EVENT_OVER_CURRENT; + + regulator_notifier_call_chain(drvdata->dev, event, NULL); + + return IRQ_HANDLED; +} + + static struct regulator_ops fixed_voltage_ops = { }; @@ -175,6 +195,33 @@ 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) { + dev_err(&pdev->dev, + "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) { + dev_err(&pdev->dev, + "Failed tp 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/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; }; -- 1.9.1