]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/hwmon/gpio-fan.c
Merge tag 'powerpc-4.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux
[karo-tx-linux.git] / drivers / hwmon / gpio-fan.c
index c241f5b0b7cf2c1005183cc1db702208e3f7eed0..a3dae6d0082a0d08e4183f63e27b79ae5510b863 100644 (file)
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/thermal.h>
 
 struct gpio_fan_data {
        struct platform_device  *pdev;
        struct device           *hwmon_dev;
+       /* Cooling device if any */
+       struct thermal_cooling_device *cdev;
        struct mutex            lock; /* lock GPIOs operations. */
        int                     num_ctrl;
        unsigned                *ctrl;
@@ -387,6 +390,53 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data,
        return 0;
 }
 
+static int gpio_fan_get_max_state(struct thermal_cooling_device *cdev,
+                                 unsigned long *state)
+{
+       struct gpio_fan_data *fan_data = cdev->devdata;
+
+       if (!fan_data)
+               return -EINVAL;
+
+       *state = fan_data->num_speed - 1;
+       return 0;
+}
+
+static int gpio_fan_get_cur_state(struct thermal_cooling_device *cdev,
+                                 unsigned long *state)
+{
+       struct gpio_fan_data *fan_data = cdev->devdata;
+       int r;
+
+       if (!fan_data)
+               return -EINVAL;
+
+       r = get_fan_speed_index(fan_data);
+       if (r < 0)
+               return r;
+
+       *state = r;
+       return 0;
+}
+
+static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev,
+                                 unsigned long state)
+{
+       struct gpio_fan_data *fan_data = cdev->devdata;
+
+       if (!fan_data)
+               return -EINVAL;
+
+       set_fan_speed(fan_data, state);
+       return 0;
+}
+
+static const struct thermal_cooling_device_ops gpio_fan_cool_ops = {
+       .get_max_state = gpio_fan_get_max_state,
+       .get_cur_state = gpio_fan_get_cur_state,
+       .set_cur_state = gpio_fan_set_cur_state,
+};
+
 #ifdef CONFIG_OF_GPIO
 /*
  * Translate OpenFirmware node properties into platform_data
@@ -497,6 +547,11 @@ static int gpio_fan_probe(struct platform_device *pdev)
        struct gpio_fan_data *fan_data;
        struct gpio_fan_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
+       fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data),
+                               GFP_KERNEL);
+       if (!fan_data)
+               return -ENOMEM;
+
 #ifdef CONFIG_OF_GPIO
        if (!pdata) {
                pdata = devm_kzalloc(&pdev->dev,
@@ -514,11 +569,6 @@ static int gpio_fan_probe(struct platform_device *pdev)
                return -EINVAL;
 #endif /* CONFIG_OF_GPIO */
 
-       fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data),
-                               GFP_KERNEL);
-       if (!fan_data)
-               return -ENOMEM;
-
        fan_data->pdev = pdev;
        platform_set_drvdata(pdev, fan_data);
        mutex_init(&fan_data->lock);
@@ -546,18 +596,39 @@ static int gpio_fan_probe(struct platform_device *pdev)
                                                       gpio_fan_groups);
        if (IS_ERR(fan_data->hwmon_dev))
                return PTR_ERR(fan_data->hwmon_dev);
+#ifdef CONFIG_OF_GPIO
+       /* Optional cooling device register for Device tree platforms */
+       fan_data->cdev = thermal_of_cooling_device_register(pdev->dev.of_node,
+                                                           "gpio-fan",
+                                                           fan_data,
+                                                           &gpio_fan_cool_ops);
+#else /* CONFIG_OF_GPIO */
+       /* Optional cooling device register for non Device tree platforms */
+       fan_data->cdev = thermal_cooling_device_register("gpio-fan", fan_data,
+                                                        &gpio_fan_cool_ops);
+#endif /* CONFIG_OF_GPIO */
 
        dev_info(&pdev->dev, "GPIO fan initialized\n");
 
        return 0;
 }
 
-static void gpio_fan_shutdown(struct platform_device *pdev)
+static int gpio_fan_remove(struct platform_device *pdev)
 {
-       struct gpio_fan_data *fan_data = dev_get_drvdata(&pdev->dev);
+       struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+       if (!IS_ERR(fan_data->cdev))
+               thermal_cooling_device_unregister(fan_data->cdev);
 
        if (fan_data->ctrl)
                set_fan_speed(fan_data, 0);
+
+       return 0;
+}
+
+static void gpio_fan_shutdown(struct platform_device *pdev)
+{
+       gpio_fan_remove(pdev);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -591,6 +662,7 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
 
 static struct platform_driver gpio_fan_driver = {
        .probe          = gpio_fan_probe,
+       .remove         = gpio_fan_remove,
        .shutdown       = gpio_fan_shutdown,
        .driver = {
                .name   = "gpio-fan",