.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * gpio-fan.c - Hwmon driver for fans connected to GPIO lines. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2010 LaCie |
---|
5 | 6 | * |
---|
6 | 7 | * 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 | 8 | */ |
---|
22 | 9 | |
---|
23 | 10 | #include <linux/module.h> |
---|
.. | .. |
---|
67 | 54 | struct gpio_fan_data *fan_data = |
---|
68 | 55 | container_of(ws, struct gpio_fan_data, alarm_work); |
---|
69 | 56 | |
---|
70 | | - sysfs_notify(&fan_data->dev->kobj, NULL, "fan1_alarm"); |
---|
71 | | - kobject_uevent(&fan_data->dev->kobj, KOBJ_CHANGE); |
---|
| 57 | + sysfs_notify(&fan_data->hwmon_dev->kobj, NULL, "fan1_alarm"); |
---|
| 58 | + kobject_uevent(&fan_data->hwmon_dev->kobj, KOBJ_CHANGE); |
---|
72 | 59 | } |
---|
73 | 60 | |
---|
74 | 61 | static irqreturn_t fan_alarm_irq_handler(int irq, void *dev_id) |
---|
.. | .. |
---|
307 | 294 | static DEVICE_ATTR_RO(fan1_min); |
---|
308 | 295 | static DEVICE_ATTR_RO(fan1_max); |
---|
309 | 296 | static DEVICE_ATTR_RO(fan1_input); |
---|
310 | | -static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, fan1_input_show, set_rpm); |
---|
| 297 | +static DEVICE_ATTR(fan1_target, 0644, fan1_input_show, set_rpm); |
---|
311 | 298 | |
---|
312 | 299 | static umode_t gpio_fan_is_visible(struct kobject *kobj, |
---|
313 | 300 | struct attribute *attr, int index) |
---|
.. | .. |
---|
404 | 391 | if (!fan_data) |
---|
405 | 392 | return -EINVAL; |
---|
406 | 393 | |
---|
| 394 | + if (state >= fan_data->num_speed) |
---|
| 395 | + return -EINVAL; |
---|
| 396 | + |
---|
407 | 397 | set_fan_speed(fan_data, state); |
---|
408 | 398 | return 0; |
---|
409 | 399 | } |
---|
.. | .. |
---|
498 | 488 | }; |
---|
499 | 489 | MODULE_DEVICE_TABLE(of, of_gpio_fan_match); |
---|
500 | 490 | |
---|
| 491 | +static void gpio_fan_stop(void *data) |
---|
| 492 | +{ |
---|
| 493 | + set_fan_speed(data, 0); |
---|
| 494 | +} |
---|
| 495 | + |
---|
501 | 496 | static int gpio_fan_probe(struct platform_device *pdev) |
---|
502 | 497 | { |
---|
503 | 498 | int err; |
---|
.. | .. |
---|
518 | 513 | platform_set_drvdata(pdev, fan_data); |
---|
519 | 514 | mutex_init(&fan_data->lock); |
---|
520 | 515 | |
---|
521 | | - /* Configure alarm GPIO if available. */ |
---|
522 | | - if (fan_data->alarm_gpio) { |
---|
523 | | - err = fan_alarm_init(fan_data); |
---|
524 | | - if (err) |
---|
525 | | - return err; |
---|
526 | | - } |
---|
527 | | - |
---|
528 | 516 | /* Configure control GPIOs if available. */ |
---|
529 | 517 | if (fan_data->gpios && fan_data->num_gpios > 0) { |
---|
530 | 518 | if (!fan_data->speed || fan_data->num_speed <= 1) |
---|
531 | 519 | return -EINVAL; |
---|
532 | 520 | err = fan_ctrl_init(fan_data); |
---|
| 521 | + if (err) |
---|
| 522 | + return err; |
---|
| 523 | + err = devm_add_action_or_reset(dev, gpio_fan_stop, fan_data); |
---|
533 | 524 | if (err) |
---|
534 | 525 | return err; |
---|
535 | 526 | } |
---|
.. | .. |
---|
542 | 533 | if (IS_ERR(fan_data->hwmon_dev)) |
---|
543 | 534 | return PTR_ERR(fan_data->hwmon_dev); |
---|
544 | 535 | |
---|
| 536 | + /* Configure alarm GPIO if available. */ |
---|
| 537 | + if (fan_data->alarm_gpio) { |
---|
| 538 | + err = fan_alarm_init(fan_data); |
---|
| 539 | + if (err) |
---|
| 540 | + return err; |
---|
| 541 | + } |
---|
| 542 | + |
---|
545 | 543 | /* Optional cooling device register for Device tree platforms */ |
---|
546 | | - fan_data->cdev = thermal_of_cooling_device_register(np, |
---|
547 | | - "gpio-fan", |
---|
548 | | - fan_data, |
---|
549 | | - &gpio_fan_cool_ops); |
---|
| 544 | + fan_data->cdev = devm_thermal_of_cooling_device_register(dev, np, |
---|
| 545 | + "gpio-fan", fan_data, &gpio_fan_cool_ops); |
---|
550 | 546 | |
---|
551 | 547 | dev_info(dev, "GPIO fan initialized\n"); |
---|
552 | 548 | |
---|
553 | 549 | return 0; |
---|
554 | 550 | } |
---|
555 | 551 | |
---|
556 | | -static int gpio_fan_remove(struct platform_device *pdev) |
---|
| 552 | +static void gpio_fan_shutdown(struct platform_device *pdev) |
---|
557 | 553 | { |
---|
558 | 554 | struct gpio_fan_data *fan_data = platform_get_drvdata(pdev); |
---|
559 | 555 | |
---|
560 | | - if (!IS_ERR(fan_data->cdev)) |
---|
561 | | - thermal_cooling_device_unregister(fan_data->cdev); |
---|
562 | | - |
---|
563 | 556 | if (fan_data->gpios) |
---|
564 | 557 | set_fan_speed(fan_data, 0); |
---|
565 | | - |
---|
566 | | - return 0; |
---|
567 | | -} |
---|
568 | | - |
---|
569 | | -static void gpio_fan_shutdown(struct platform_device *pdev) |
---|
570 | | -{ |
---|
571 | | - gpio_fan_remove(pdev); |
---|
572 | 558 | } |
---|
573 | 559 | |
---|
574 | 560 | #ifdef CONFIG_PM_SLEEP |
---|
.. | .. |
---|
602 | 588 | |
---|
603 | 589 | static struct platform_driver gpio_fan_driver = { |
---|
604 | 590 | .probe = gpio_fan_probe, |
---|
605 | | - .remove = gpio_fan_remove, |
---|
606 | 591 | .shutdown = gpio_fan_shutdown, |
---|
607 | 592 | .driver = { |
---|
608 | 593 | .name = "gpio-fan", |
---|