From patchwork Fri Sep 7 16:34:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jamie Lentin X-Patchwork-Id: 1424401 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 608BFDF283 for ; Fri, 7 Sep 2012 16:51:15 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TA1hV-0006S7-Un; Fri, 07 Sep 2012 16:46:39 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TA1VF-00062j-6U for linux-arm-kernel@merlin.infradead.org; Fri, 07 Sep 2012 16:33:57 +0000 Received: from marmot.wormnet.eu ([2a03:9800:10:2d:3203:b3a5:8bdc:5b68]) by casper.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TA1VC-0001ps-O1 for linux-arm-kernel@lists.infradead.org; Fri, 07 Sep 2012 16:33:55 +0000 Received: from mijo.vandergast.wormnet.eu ([80.229.158.163] helo=bunsen.vandergast.wormnet.eu) by marmot.wormnet.eu with esmtpa (Exim 4.80) (envelope-from ) id 1TA1Uk-00008x-Ft; Fri, 07 Sep 2012 17:33:26 +0100 From: Jamie Lentin To: Grant Likely , Rob Herring , Jean Delvare , Guenter Roeck , Jason Cooper , Andrew Lunn Subject: [PATCH 1/2] hwmon: Add devicetree bindings to gpio-fan Date: Fri, 7 Sep 2012 17:34:34 +0100 Message-Id: <1347035675-23907-2-git-send-email-jm@lentin.co.uk> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1347035675-23907-1-git-send-email-jm@lentin.co.uk> References: <1347035675-23907-1-git-send-email-jm@lentin.co.uk> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20120907_173354_904097_A2C9AF4D X-CRM114-Status: GOOD ( 22.41 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on casper.infradead.org summary: Content analysis details: (-1.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: devicetree-discuss@lists.ozlabs.org, Jamie Lentin , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Allow a gpio-fan to be defined in devicetree, see binding documentation for details. Signed-off-by: Jamie Lentin --- .../devicetree/bindings/gpio/gpio-fan.txt | 25 +++++ drivers/hwmon/gpio-fan.c | 111 ++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-fan.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio-fan.txt b/Documentation/devicetree/bindings/gpio/gpio-fan.txt new file mode 100644 index 0000000..2dd457a --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-fan.txt @@ -0,0 +1,25 @@ +Bindings for fan connected to GPIO lines + +Required properties: +- compatible : "gpio-fan" +- gpios: Specifies the pins that map to bits in the control value, + ordered MSB-->LSB. +- gpio-fan,speed-map: A mapping of possible fan RPM speeds and the + control value that should be set to achieve them. This array + must have the RPM values in ascending order. + +Optional properties: +- alarm-gpios: This pin going active indicates something is wrong with + the fan, and a udev event will be fired. + +Examples: + + gpio_fan { + compatible = "gpio-fan"; + gpios = <&gpio1 14 1 + &gpio1 13 1>; + gpio-fan,speed-map = <0 0 + 3000 1 + 6000 2>; + alarm-gpios = <&gpio1 15 1>; + }; diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 2f4b01b..876ce41 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include struct gpio_fan_data { struct platform_device *pdev; @@ -400,12 +402,120 @@ static ssize_t show_name(struct device *dev, static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +#ifdef CONFIG_OF +/* + * Translate OpenFirmware node properties into platform_data + */ +static int gpio_fan_get_of_pdata(struct device *dev, + struct gpio_fan_platform_data *pdata) +{ + struct device_node *node; + struct gpio_fan_speed *speed; + unsigned *ctrl; + unsigned i; + u32 u; + struct property *prop; + const __be32 *p; + + node = dev->of_node; + + /* Fill GPIO pin array */ + pdata->num_ctrl = of_gpio_count(node); + ctrl = devm_kzalloc(dev, pdata->num_ctrl * sizeof(unsigned), + GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + for (i = 0; i < of_gpio_count(node); i++) { + int val; + + val = of_get_gpio(node, i); + if (val >= 0) + ctrl[i] = val; + else + return -EINVAL; + } + pdata->ctrl = ctrl; + + /* Get speed map array size */ + i = 0; + of_property_for_each_u32(node, "gpio-fan,speed-map", prop, p, u) + i++; + if (i & 1) { + dev_err(dev, "gpio-fan,speed-map contains odd number of entries"); + return -ENODEV; + } + pdata->num_speed = i >> 1; + speed = devm_kzalloc(dev, + pdata->num_speed * sizeof(struct gpio_fan_speed), + GFP_KERNEL); + if (!speed) + return -ENOMEM; + + /* Populate speed map */ + i = 0; + of_property_for_each_u32(node, "gpio-fan,speed-map", prop, p, u) { + if (i & 1) + speed[i >> 1].ctrl_val = (int)u; + else + speed[i >> 1].rpm = (int)u; + i++; + } + pdata->speed = speed; + + /* Alarm GPIO if one exists */ + if (of_gpio_named_count(node, "alarm-gpios")) { + struct gpio_fan_alarm *alarm; + int val; + enum of_gpio_flags flags; + + alarm = devm_kzalloc(dev, sizeof(struct gpio_fan_alarm), + GFP_KERNEL); + if (!alarm) + return -ENOMEM; + + val = of_get_named_gpio_flags(node, "alarm-gpios", 0, &flags); + if (val >= 0) { + alarm->gpio = val; + alarm->active_low = flags & OF_GPIO_ACTIVE_LOW; + } else + return -EINVAL; + + pdata->alarm = alarm; + } + + return 0; +} + +static const struct of_device_id of_gpio_fan_match[] = { + { .compatible = "gpio-fan", }, + {}, +}; +#endif /* CONFIG_OF_GPIO */ + static int __devinit gpio_fan_probe(struct platform_device *pdev) { int err; struct gpio_fan_data *fan_data; struct gpio_fan_platform_data *pdata = pdev->dev.platform_data; +#ifdef CONFIG_OF + if (!pdata) { + struct gpio_fan_platform_data *alt_pdata; + + alt_pdata = devm_kzalloc(&pdev->dev, + sizeof(struct gpio_fan_platform_data), + GFP_KERNEL); + if (!alt_pdata) + return -ENOMEM; + + err = gpio_fan_get_of_pdata(&pdev->dev, alt_pdata); + if (err) + return err; + pdata = alt_pdata; + } +#endif /* CONFIG_OF_GPIO */ + if (!pdata) return -EINVAL; @@ -511,6 +621,7 @@ static struct platform_driver gpio_fan_driver = { .driver = { .name = "gpio-fan", .pm = GPIO_FAN_PM, + .of_match_table = of_match_ptr(of_gpio_fan_match), }, };