aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-10-17 14:17:06 +0200
committerGraeme Gregory <graeme.gregory@linaro.org>2014-11-06 11:57:48 +0000
commitc26715f28a8076e4194e07247f72e0dab4d2040d (patch)
treedafffa89922a6ae09ffa7da0b32cd7676d9cf014
parent409a20d06cf1837090d591536e666df87136c4ec (diff)
downloadleg-kernel-c26715f28a8076e4194e07247f72e0dab4d2040d.tar.gz
leds: leds-gpio: Make use of device property API
Make use of device property API in this driver so that both OF and ACPI based system can use the same driver. This change contains material from Max Eliaser and Mika Westerberg. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Bryan Wu <cooloney@gmail.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/leds/leds-gpio.c108
1 files changed, 51 insertions, 57 deletions
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index bc30168023c0..bbf737dbc97b 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -1,7 +1,7 @@
/*
* LEDs driver for GPIOs
*
- * Copyright (C) 2007 8, 4D Technologies inc.
+ * Copyright (C) 2007 8D Technologies inc.
* Raphael Assenat <raph@8d.com>
* Copyright (C) 2008 Freescale Semiconductor, Inc.
*
@@ -16,12 +16,10 @@
#include <linux/gpio/consumer.h>
#include <linux/leds.h>
#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include <linux/property.h>
struct gpio_led_data {
struct led_classdev cdev;
@@ -171,65 +169,59 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
(sizeof(struct gpio_led_data) * num_leds);
}
-/* Code to create from OpenFirmware platform devices */
-#ifdef CONFIG_OF_GPIO
-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
+static int gpio_leds_create_led(struct device *dev, void *child, void *data)
+{
+ struct gpio_leds_priv *priv = data;
+ struct gpio_led led = {};
+ const char *state = NULL;
+
+ led.gpiod = devm_get_named_gpiod_from_child(dev, child, "gpios", 0);
+ if (IS_ERR(led.gpiod))
+ return PTR_ERR(led.gpiod);
+
+ device_child_property_read_string(dev, child, "label", &led.name);
+ device_child_property_read_string(dev, child, "linux,default-trigger",
+ &led.default_trigger);
+
+ device_child_property_read_string(dev, child, "linux,default_state",
+ &state);
+ if (state) {
+ if (!strcmp(state, "keep"))
+ led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
+ else if (!strcmp(state, "on"))
+ led.default_state = LEDS_GPIO_DEFSTATE_ON;
+ else
+ led.default_state = LEDS_GPIO_DEFSTATE_OFF;
+ }
+
+ if (!device_get_child_property(dev, child, "retain-state-suspended", NULL))
+ led.retain_state_suspended = 1;
+
+ return create_gpio_led(&led, &priv->leds[priv->num_leds++], dev, NULL);
+}
+
+static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node, *child;
struct gpio_leds_priv *priv;
- int count, ret;
+ int ret, count;
- /* count LEDs in this device, so we know how much to allocate */
- count = of_get_available_child_count(np);
+ count = device_get_child_node_count(&pdev->dev);
if (!count)
return ERR_PTR(-ENODEV);
- for_each_available_child_of_node(np, child)
- if (of_get_gpio(child, 0) == -EPROBE_DEFER)
- return ERR_PTR(-EPROBE_DEFER);
-
priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count),
GFP_KERNEL);
if (!priv)
return ERR_PTR(-ENOMEM);
- for_each_available_child_of_node(np, child) {
- struct gpio_led led = {};
- enum of_gpio_flags flags;
- const char *state;
-
- led.gpio = of_get_gpio_flags(child, 0, &flags);
- led.active_low = flags & OF_GPIO_ACTIVE_LOW;
- led.name = of_get_property(child, "label", NULL) ? : child->name;
- led.default_trigger =
- of_get_property(child, "linux,default-trigger", NULL);
- state = of_get_property(child, "default-state", NULL);
- if (state) {
- if (!strcmp(state, "keep"))
- led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
- else if (!strcmp(state, "on"))
- led.default_state = LEDS_GPIO_DEFSTATE_ON;
- else
- led.default_state = LEDS_GPIO_DEFSTATE_OFF;
- }
-
- if (of_get_property(child, "retain-state-suspended", NULL))
- led.retain_state_suspended = 1;
-
- ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
- &pdev->dev, NULL);
- if (ret < 0) {
- of_node_put(child);
- goto err;
- }
+ ret = device_for_each_child_node(&pdev->dev, gpio_leds_create_led, priv);
+ if (ret) {
+ for (count = priv->num_leds - 2; count >= 0; count--)
+ delete_gpio_led(&priv->leds[count]);
+ return ERR_PTR(ret);
}
return priv;
-
-err:
- for (count = priv->num_leds - 2; count >= 0; count--)
- delete_gpio_led(&priv->leds[count]);
- return ERR_PTR(-ENODEV);
}
static const struct of_device_id of_gpio_leds_match[] = {
@@ -238,12 +230,13 @@ static const struct of_device_id of_gpio_leds_match[] = {
};
MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
-#else /* CONFIG_OF_GPIO */
-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
-{
- return ERR_PTR(-ENODEV);
-}
-#endif /* CONFIG_OF_GPIO */
+
+static const struct acpi_device_id acpi_gpio_leds_match[] = {
+ { "PRP0001" }, /* Device Tree shoehorned into ACPI */
+ {},
+};
+
+MODULE_DEVICE_TABLE(acpi, acpi_gpio_leds_match);
static int gpio_led_probe(struct platform_device *pdev)
{
@@ -271,7 +264,7 @@ static int gpio_led_probe(struct platform_device *pdev)
}
}
} else {
- priv = gpio_leds_create_of(pdev);
+ priv = gpio_leds_create(pdev);
if (IS_ERR(priv))
return PTR_ERR(priv);
}
@@ -298,7 +291,8 @@ static struct platform_driver gpio_led_driver = {
.driver = {
.name = "leds-gpio",
.owner = THIS_MODULE,
- .of_match_table = of_match_ptr(of_gpio_leds_match),
+ .of_match_table = of_gpio_leds_match,
+ .acpi_match_table = acpi_gpio_leds_match,
},
};