linux/drivers/hwmon/gpio-fan.c
<<
>>
Prefs
   1/*
   2 * gpio-fan.c - Hwmon driver for fans connected to GPIO lines.
   3 *
   4 * Copyright (C) 2010 LaCie
   5 *
   6 * Author: Simon Guinot <sguinot@lacie.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 */
  22
  23#include <linux/module.h>
  24#include <linux/init.h>
  25#include <linux/slab.h>
  26#include <linux/interrupt.h>
  27#include <linux/irq.h>
  28#include <linux/platform_device.h>
  29#include <linux/err.h>
  30#include <linux/mutex.h>
  31#include <linux/hwmon.h>
  32#include <linux/gpio.h>
  33#include <linux/gpio-fan.h>
  34
  35struct gpio_fan_data {
  36        struct platform_device  *pdev;
  37        struct device           *hwmon_dev;
  38        struct mutex            lock; /* lock GPIOs operations. */
  39        int                     num_ctrl;
  40        unsigned                *ctrl;
  41        int                     num_speed;
  42        struct gpio_fan_speed   *speed;
  43        int                     speed_index;
  44#ifdef CONFIG_PM
  45        int                     resume_speed;
  46#endif
  47        bool                    pwm_enable;
  48        struct gpio_fan_alarm   *alarm;
  49        struct work_struct      alarm_work;
  50};
  51
  52/*
  53 * Alarm GPIO.
  54 */
  55
  56static void fan_alarm_notify(struct work_struct *ws)
  57{
  58        struct gpio_fan_data *fan_data =
  59                container_of(ws, struct gpio_fan_data, alarm_work);
  60
  61        sysfs_notify(&fan_data->pdev->dev.kobj, NULL, "fan1_alarm");
  62        kobject_uevent(&fan_data->pdev->dev.kobj, KOBJ_CHANGE);
  63}
  64
  65static irqreturn_t fan_alarm_irq_handler(int irq, void *dev_id)
  66{
  67        struct gpio_fan_data *fan_data = dev_id;
  68
  69        schedule_work(&fan_data->alarm_work);
  70
  71        return IRQ_NONE;
  72}
  73
  74static ssize_t show_fan_alarm(struct device *dev,
  75                              struct device_attribute *attr, char *buf)
  76{
  77        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
  78        struct gpio_fan_alarm *alarm = fan_data->alarm;
  79        int value = gpio_get_value(alarm->gpio);
  80
  81        if (alarm->active_low)
  82                value = !value;
  83
  84        return sprintf(buf, "%d\n", value);
  85}
  86
  87static DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL);
  88
  89static int fan_alarm_init(struct gpio_fan_data *fan_data,
  90                          struct gpio_fan_alarm *alarm)
  91{
  92        int err;
  93        int alarm_irq;
  94        struct platform_device *pdev = fan_data->pdev;
  95
  96        fan_data->alarm = alarm;
  97
  98        err = gpio_request(alarm->gpio, "GPIO fan alarm");
  99        if (err)
 100                return err;
 101
 102        err = gpio_direction_input(alarm->gpio);
 103        if (err)
 104                goto err_free_gpio;
 105
 106        err = device_create_file(&pdev->dev, &dev_attr_fan1_alarm);
 107        if (err)
 108                goto err_free_gpio;
 109
 110        /*
 111         * If the alarm GPIO don't support interrupts, just leave
 112         * without initializing the fail notification support.
 113         */
 114        alarm_irq = gpio_to_irq(alarm->gpio);
 115        if (alarm_irq < 0)
 116                return 0;
 117
 118        INIT_WORK(&fan_data->alarm_work, fan_alarm_notify);
 119        irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
 120        err = request_irq(alarm_irq, fan_alarm_irq_handler, IRQF_SHARED,
 121                          "GPIO fan alarm", fan_data);
 122        if (err)
 123                goto err_free_sysfs;
 124
 125        return 0;
 126
 127err_free_sysfs:
 128        device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
 129err_free_gpio:
 130        gpio_free(alarm->gpio);
 131
 132        return err;
 133}
 134
 135static void fan_alarm_free(struct gpio_fan_data *fan_data)
 136{
 137        struct platform_device *pdev = fan_data->pdev;
 138        int alarm_irq = gpio_to_irq(fan_data->alarm->gpio);
 139
 140        if (alarm_irq >= 0)
 141                free_irq(alarm_irq, fan_data);
 142        device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
 143        gpio_free(fan_data->alarm->gpio);
 144}
 145
 146/*
 147 * Control GPIOs.
 148 */
 149
 150/* Must be called with fan_data->lock held, except during initialization. */
 151static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val)
 152{
 153        int i;
 154
 155        for (i = 0; i < fan_data->num_ctrl; i++)
 156                gpio_set_value(fan_data->ctrl[i], (ctrl_val >> i) & 1);
 157}
 158
 159static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
 160{
 161        int i;
 162        int ctrl_val = 0;
 163
 164        for (i = 0; i < fan_data->num_ctrl; i++) {
 165                int value;
 166
 167                value = gpio_get_value(fan_data->ctrl[i]);
 168                ctrl_val |= (value << i);
 169        }
 170        return ctrl_val;
 171}
 172
 173/* Must be called with fan_data->lock held, except during initialization. */
 174static void set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
 175{
 176        if (fan_data->speed_index == speed_index)
 177                return;
 178
 179        __set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val);
 180        fan_data->speed_index = speed_index;
 181}
 182
 183static int get_fan_speed_index(struct gpio_fan_data *fan_data)
 184{
 185        int ctrl_val = __get_fan_ctrl(fan_data);
 186        int i;
 187
 188        for (i = 0; i < fan_data->num_speed; i++)
 189                if (fan_data->speed[i].ctrl_val == ctrl_val)
 190                        return i;
 191
 192        dev_warn(&fan_data->pdev->dev,
 193                 "missing speed array entry for GPIO value 0x%x\n", ctrl_val);
 194
 195        return -EINVAL;
 196}
 197
 198static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
 199{
 200        struct gpio_fan_speed *speed = fan_data->speed;
 201        int i;
 202
 203        for (i = 0; i < fan_data->num_speed; i++)
 204                if (speed[i].rpm >= rpm)
 205                        return i;
 206
 207        return fan_data->num_speed - 1;
 208}
 209
 210static ssize_t show_pwm(struct device *dev,
 211                        struct device_attribute *attr, char *buf)
 212{
 213        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
 214        u8 pwm = fan_data->speed_index * 255 / (fan_data->num_speed - 1);
 215
 216        return sprintf(buf, "%d\n", pwm);
 217}
 218
 219static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 220                       const char *buf, size_t count)
 221{
 222        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
 223        unsigned long pwm;
 224        int speed_index;
 225        int ret = count;
 226
 227        if (kstrtoul(buf, 10, &pwm) || pwm > 255)
 228                return -EINVAL;
 229
 230        mutex_lock(&fan_data->lock);
 231
 232        if (!fan_data->pwm_enable) {
 233                ret = -EPERM;
 234                goto exit_unlock;
 235        }
 236
 237        speed_index = DIV_ROUND_UP(pwm * (fan_data->num_speed - 1), 255);
 238        set_fan_speed(fan_data, speed_index);
 239
 240exit_unlock:
 241        mutex_unlock(&fan_data->lock);
 242
 243        return ret;
 244}
 245
 246static ssize_t show_pwm_enable(struct device *dev,
 247                               struct device_attribute *attr, char *buf)
 248{
 249        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
 250
 251        return sprintf(buf, "%d\n", fan_data->pwm_enable);
 252}
 253
 254static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
 255                              const char *buf, size_t count)
 256{
 257        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
 258        unsigned long val;
 259
 260        if (kstrtoul(buf, 10, &val) || val > 1)
 261                return -EINVAL;
 262
 263        if (fan_data->pwm_enable == val)
 264                return count;
 265
 266        mutex_lock(&fan_data->lock);
 267
 268        fan_data->pwm_enable = val;
 269
 270        /* Disable manual control mode: set fan at full speed. */
 271        if (val == 0)
 272                set_fan_speed(fan_data, fan_data->num_speed - 1);
 273
 274        mutex_unlock(&fan_data->lock);
 275
 276        return count;
 277}
 278
 279static ssize_t show_pwm_mode(struct device *dev,
 280                             struct device_attribute *attr, char *buf)
 281{
 282        return sprintf(buf, "0\n");
 283}
 284
 285static ssize_t show_rpm_min(struct device *dev,
 286                            struct device_attribute *attr, char *buf)
 287{
 288        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
 289
 290        return sprintf(buf, "%d\n", fan_data->speed[0].rpm);
 291}
 292
 293static ssize_t show_rpm_max(struct device *dev,
 294                            struct device_attribute *attr, char *buf)
 295{
 296        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
 297
 298        return sprintf(buf, "%d\n",
 299                       fan_data->speed[fan_data->num_speed - 1].rpm);
 300}
 301
 302static ssize_t show_rpm(struct device *dev,
 303                        struct device_attribute *attr, char *buf)
 304{
 305        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
 306
 307        return sprintf(buf, "%d\n", fan_data->speed[fan_data->speed_index].rpm);
 308}
 309
 310static ssize_t set_rpm(struct device *dev, struct device_attribute *attr,
 311                       const char *buf, size_t count)
 312{
 313        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
 314        unsigned long rpm;
 315        int ret = count;
 316
 317        if (kstrtoul(buf, 10, &rpm))
 318                return -EINVAL;
 319
 320        mutex_lock(&fan_data->lock);
 321
 322        if (!fan_data->pwm_enable) {
 323                ret = -EPERM;
 324                goto exit_unlock;
 325        }
 326
 327        set_fan_speed(fan_data, rpm_to_speed_index(fan_data, rpm));
 328
 329exit_unlock:
 330        mutex_unlock(&fan_data->lock);
 331
 332        return ret;
 333}
 334
 335static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
 336static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
 337                   show_pwm_enable, set_pwm_enable);
 338static DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL);
 339static DEVICE_ATTR(fan1_min, S_IRUGO, show_rpm_min, NULL);
 340static DEVICE_ATTR(fan1_max, S_IRUGO, show_rpm_max, NULL);
 341static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
 342static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
 343
 344static struct attribute *gpio_fan_ctrl_attributes[] = {
 345        &dev_attr_pwm1.attr,
 346        &dev_attr_pwm1_enable.attr,
 347        &dev_attr_pwm1_mode.attr,
 348        &dev_attr_fan1_input.attr,
 349        &dev_attr_fan1_target.attr,
 350        &dev_attr_fan1_min.attr,
 351        &dev_attr_fan1_max.attr,
 352        NULL
 353};
 354
 355static const struct attribute_group gpio_fan_ctrl_group = {
 356        .attrs = gpio_fan_ctrl_attributes,
 357};
 358
 359static int fan_ctrl_init(struct gpio_fan_data *fan_data,
 360                         struct gpio_fan_platform_data *pdata)
 361{
 362        struct platform_device *pdev = fan_data->pdev;
 363        int num_ctrl = pdata->num_ctrl;
 364        unsigned *ctrl = pdata->ctrl;
 365        int i, err;
 366
 367        for (i = 0; i < num_ctrl; i++) {
 368                err = gpio_request(ctrl[i], "GPIO fan control");
 369                if (err)
 370                        goto err_free_gpio;
 371
 372                err = gpio_direction_output(ctrl[i], gpio_get_value(ctrl[i]));
 373                if (err) {
 374                        gpio_free(ctrl[i]);
 375                        goto err_free_gpio;
 376                }
 377        }
 378
 379        fan_data->num_ctrl = num_ctrl;
 380        fan_data->ctrl = ctrl;
 381        fan_data->num_speed = pdata->num_speed;
 382        fan_data->speed = pdata->speed;
 383        fan_data->pwm_enable = true; /* Enable manual fan speed control. */
 384        fan_data->speed_index = get_fan_speed_index(fan_data);
 385        if (fan_data->speed_index < 0) {
 386                err = -ENODEV;
 387                goto err_free_gpio;
 388        }
 389
 390        err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
 391        if (err)
 392                goto err_free_gpio;
 393
 394        return 0;
 395
 396err_free_gpio:
 397        for (i = i - 1; i >= 0; i--)
 398                gpio_free(ctrl[i]);
 399
 400        return err;
 401}
 402
 403static void fan_ctrl_free(struct gpio_fan_data *fan_data)
 404{
 405        struct platform_device *pdev = fan_data->pdev;
 406        int i;
 407
 408        sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
 409        for (i = 0; i < fan_data->num_ctrl; i++)
 410                gpio_free(fan_data->ctrl[i]);
 411}
 412
 413/*
 414 * Platform driver.
 415 */
 416
 417static ssize_t show_name(struct device *dev,
 418                         struct device_attribute *attr, char *buf)
 419{
 420        return sprintf(buf, "gpio-fan\n");
 421}
 422
 423static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 424
 425static int __devinit gpio_fan_probe(struct platform_device *pdev)
 426{
 427        int err;
 428        struct gpio_fan_data *fan_data;
 429        struct gpio_fan_platform_data *pdata = pdev->dev.platform_data;
 430
 431        if (!pdata)
 432                return -EINVAL;
 433
 434        fan_data = kzalloc(sizeof(struct gpio_fan_data), GFP_KERNEL);
 435        if (!fan_data)
 436                return -ENOMEM;
 437
 438        fan_data->pdev = pdev;
 439        platform_set_drvdata(pdev, fan_data);
 440        mutex_init(&fan_data->lock);
 441
 442        /* Configure alarm GPIO if available. */
 443        if (pdata->alarm) {
 444                err = fan_alarm_init(fan_data, pdata->alarm);
 445                if (err)
 446                        goto err_free_data;
 447        }
 448
 449        /* Configure control GPIOs if available. */
 450        if (pdata->ctrl && pdata->num_ctrl > 0) {
 451                if (!pdata->speed || pdata->num_speed <= 1) {
 452                        err = -EINVAL;
 453                        goto err_free_alarm;
 454                }
 455                err = fan_ctrl_init(fan_data, pdata);
 456                if (err)
 457                        goto err_free_alarm;
 458        }
 459
 460        err = device_create_file(&pdev->dev, &dev_attr_name);
 461        if (err)
 462                goto err_free_ctrl;
 463
 464        /* Make this driver part of hwmon class. */
 465        fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
 466        if (IS_ERR(fan_data->hwmon_dev)) {
 467                err = PTR_ERR(fan_data->hwmon_dev);
 468                goto err_remove_name;
 469        }
 470
 471        dev_info(&pdev->dev, "GPIO fan initialized\n");
 472
 473        return 0;
 474
 475err_remove_name:
 476        device_remove_file(&pdev->dev, &dev_attr_name);
 477err_free_ctrl:
 478        if (fan_data->ctrl)
 479                fan_ctrl_free(fan_data);
 480err_free_alarm:
 481        if (fan_data->alarm)
 482                fan_alarm_free(fan_data);
 483err_free_data:
 484        platform_set_drvdata(pdev, NULL);
 485        kfree(fan_data);
 486
 487        return err;
 488}
 489
 490static int __devexit gpio_fan_remove(struct platform_device *pdev)
 491{
 492        struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
 493
 494        hwmon_device_unregister(fan_data->hwmon_dev);
 495        device_remove_file(&pdev->dev, &dev_attr_name);
 496        if (fan_data->alarm)
 497                fan_alarm_free(fan_data);
 498        if (fan_data->ctrl)
 499                fan_ctrl_free(fan_data);
 500        kfree(fan_data);
 501
 502        return 0;
 503}
 504
 505#ifdef CONFIG_PM
 506static int gpio_fan_suspend(struct platform_device *pdev, pm_message_t state)
 507{
 508        struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
 509
 510        if (fan_data->ctrl) {
 511                fan_data->resume_speed = fan_data->speed_index;
 512                set_fan_speed(fan_data, 0);
 513        }
 514
 515        return 0;
 516}
 517
 518static int gpio_fan_resume(struct platform_device *pdev)
 519{
 520        struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
 521
 522        if (fan_data->ctrl)
 523                set_fan_speed(fan_data, fan_data->resume_speed);
 524
 525        return 0;
 526}
 527#else
 528#define gpio_fan_suspend NULL
 529#define gpio_fan_resume NULL
 530#endif
 531
 532static struct platform_driver gpio_fan_driver = {
 533        .probe          = gpio_fan_probe,
 534        .remove         = __devexit_p(gpio_fan_remove),
 535        .suspend        = gpio_fan_suspend,
 536        .resume         = gpio_fan_resume,
 537        .driver = {
 538                .name   = "gpio-fan",
 539        },
 540};
 541
 542module_platform_driver(gpio_fan_driver);
 543
 544MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
 545MODULE_DESCRIPTION("GPIO FAN driver");
 546MODULE_LICENSE("GPL");
 547MODULE_ALIAS("platform:gpio-fan");
 548