1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * gpio-fan.c - Hwmon driver for fans connected to GPIO lines.
4 *
5 * Copyright (C) 2010 LaCie
6 *
7 * Author: Simon Guinot <sguinot@lacie.com>
8 */
9
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
13 #include <linux/interrupt.h>
14 #include <linux/irq.h>
15 #include <linux/devm-helpers.h>
16 #include <linux/platform_device.h>
17 #include <linux/err.h>
18 #include <linux/kstrtox.h>
19 #include <linux/mutex.h>
20 #include <linux/hwmon.h>
21 #include <linux/gpio/consumer.h>
22 #include <linux/of.h>
23 #include <linux/of_platform.h>
24 #include <linux/pm.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/regulator/consumer.h>
27 #include <linux/thermal.h>
28
29 struct gpio_fan_speed {
30 int rpm;
31 int ctrl_val;
32 };
33
34 struct gpio_fan_data {
35 struct device *dev;
36 struct device *hwmon_dev;
37 /* Cooling device if any */
38 struct thermal_cooling_device *cdev;
39 struct mutex lock; /* lock GPIOs operations. */
40 int num_gpios;
41 struct gpio_desc **gpios;
42 int num_speed;
43 struct gpio_fan_speed *speed;
44 int speed_index;
45 int resume_speed;
46 bool pwm_enable;
47 struct gpio_desc *alarm_gpio;
48 struct work_struct alarm_work;
49 struct regulator *supply;
50 };
51
52 /*
53 * Alarm GPIO.
54 */
55
fan_alarm_notify(struct work_struct * ws)56 static 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->hwmon_dev->kobj, NULL, "fan1_alarm");
62 kobject_uevent(&fan_data->hwmon_dev->kobj, KOBJ_CHANGE);
63 }
64
fan_alarm_irq_handler(int irq,void * dev_id)65 static 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_HANDLED;
72 }
73
fan1_alarm_show(struct device * dev,struct device_attribute * attr,char * buf)74 static ssize_t fan1_alarm_show(struct device *dev,
75 struct device_attribute *attr, char *buf)
76 {
77 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
78
79 return sprintf(buf, "%d\n",
80 gpiod_get_value_cansleep(fan_data->alarm_gpio));
81 }
82
83 static DEVICE_ATTR_RO(fan1_alarm);
84
fan_alarm_init(struct gpio_fan_data * fan_data)85 static int fan_alarm_init(struct gpio_fan_data *fan_data)
86 {
87 int alarm_irq;
88 int err;
89 struct device *dev = fan_data->dev;
90
91 /*
92 * If the alarm GPIO don't support interrupts, just leave
93 * without initializing the fail notification support.
94 */
95 alarm_irq = gpiod_to_irq(fan_data->alarm_gpio);
96 if (alarm_irq <= 0)
97 return 0;
98
99 err = devm_work_autocancel(dev, &fan_data->alarm_work,
100 fan_alarm_notify);
101 if (err)
102 return err;
103
104 irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
105 return devm_request_irq(dev, alarm_irq, fan_alarm_irq_handler,
106 0, "GPIO fan alarm", fan_data);
107 }
108
109 /*
110 * Control GPIOs.
111 */
112
113 /* Must be called with fan_data->lock held, except during initialization. */
__set_fan_ctrl(struct gpio_fan_data * fan_data,int ctrl_val)114 static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val)
115 {
116 int i;
117
118 for (i = 0; i < fan_data->num_gpios; i++)
119 gpiod_set_value_cansleep(fan_data->gpios[i],
120 (ctrl_val >> i) & 1);
121 }
122
__get_fan_ctrl(struct gpio_fan_data * fan_data)123 static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
124 {
125 int i;
126 int ctrl_val = 0;
127
128 for (i = 0; i < fan_data->num_gpios; i++) {
129 int value;
130
131 value = gpiod_get_value_cansleep(fan_data->gpios[i]);
132 ctrl_val |= (value << i);
133 }
134 return ctrl_val;
135 }
136
137 /* Must be called with fan_data->lock held, except during initialization. */
set_fan_speed(struct gpio_fan_data * fan_data,int speed_index)138 static int set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
139 {
140 if (fan_data->speed_index == speed_index)
141 return 0;
142
143 if (fan_data->speed_index == 0 && speed_index > 0) {
144 int ret;
145
146 ret = pm_runtime_resume_and_get(fan_data->dev);
147 if (ret < 0)
148 return ret;
149 }
150
151 __set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val);
152
153 if (fan_data->speed_index > 0 && speed_index == 0) {
154 int ret;
155
156 ret = pm_runtime_put_sync(fan_data->dev);
157 if (ret < 0 && ret != -ENOSYS)
158 return ret;
159 }
160
161 fan_data->speed_index = speed_index;
162
163 return 0;
164 }
165
get_fan_speed_index(struct gpio_fan_data * fan_data)166 static int get_fan_speed_index(struct gpio_fan_data *fan_data)
167 {
168 int ctrl_val = __get_fan_ctrl(fan_data);
169 int i;
170
171 for (i = 0; i < fan_data->num_speed; i++)
172 if (fan_data->speed[i].ctrl_val == ctrl_val)
173 return i;
174
175 dev_warn(fan_data->dev,
176 "missing speed array entry for GPIO value 0x%x\n", ctrl_val);
177
178 return -ENODEV;
179 }
180
rpm_to_speed_index(struct gpio_fan_data * fan_data,unsigned long rpm)181 static int rpm_to_speed_index(struct gpio_fan_data *fan_data, unsigned long rpm)
182 {
183 struct gpio_fan_speed *speed = fan_data->speed;
184 int i;
185
186 for (i = 0; i < fan_data->num_speed; i++)
187 if (speed[i].rpm >= rpm)
188 return i;
189
190 return fan_data->num_speed - 1;
191 }
192
pwm1_show(struct device * dev,struct device_attribute * attr,char * buf)193 static ssize_t pwm1_show(struct device *dev, struct device_attribute *attr,
194 char *buf)
195 {
196 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
197 u8 pwm = fan_data->speed_index * 255 / (fan_data->num_speed - 1);
198
199 return sprintf(buf, "%d\n", pwm);
200 }
201
pwm1_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)202 static ssize_t pwm1_store(struct device *dev, struct device_attribute *attr,
203 const char *buf, size_t count)
204 {
205 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
206 unsigned long pwm;
207 int speed_index;
208 int ret;
209
210 if (kstrtoul(buf, 10, &pwm) || pwm > 255)
211 return -EINVAL;
212
213 mutex_lock(&fan_data->lock);
214
215 if (!fan_data->pwm_enable) {
216 ret = -EPERM;
217 goto exit_unlock;
218 }
219
220 speed_index = DIV_ROUND_UP(pwm * (fan_data->num_speed - 1), 255);
221 ret = set_fan_speed(fan_data, speed_index);
222
223 exit_unlock:
224 mutex_unlock(&fan_data->lock);
225
226 return ret ? ret : count;
227 }
228
pwm1_enable_show(struct device * dev,struct device_attribute * attr,char * buf)229 static ssize_t pwm1_enable_show(struct device *dev,
230 struct device_attribute *attr, char *buf)
231 {
232 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
233
234 return sprintf(buf, "%d\n", fan_data->pwm_enable);
235 }
236
pwm1_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)237 static ssize_t pwm1_enable_store(struct device *dev,
238 struct device_attribute *attr,
239 const char *buf, size_t count)
240 {
241 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
242 unsigned long val;
243 int ret = 0;
244
245 if (kstrtoul(buf, 10, &val) || val > 1)
246 return -EINVAL;
247
248 if (fan_data->pwm_enable == val)
249 return count;
250
251 mutex_lock(&fan_data->lock);
252
253 fan_data->pwm_enable = val;
254
255 /* Disable manual control mode: set fan at full speed. */
256 if (val == 0)
257 ret = set_fan_speed(fan_data, fan_data->num_speed - 1);
258
259 mutex_unlock(&fan_data->lock);
260
261 return ret ? ret : count;
262 }
263
pwm1_mode_show(struct device * dev,struct device_attribute * attr,char * buf)264 static ssize_t pwm1_mode_show(struct device *dev,
265 struct device_attribute *attr, char *buf)
266 {
267 return sprintf(buf, "0\n");
268 }
269
fan1_min_show(struct device * dev,struct device_attribute * attr,char * buf)270 static ssize_t fan1_min_show(struct device *dev,
271 struct device_attribute *attr, char *buf)
272 {
273 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
274
275 return sprintf(buf, "%d\n", fan_data->speed[0].rpm);
276 }
277
fan1_max_show(struct device * dev,struct device_attribute * attr,char * buf)278 static ssize_t fan1_max_show(struct device *dev,
279 struct device_attribute *attr, char *buf)
280 {
281 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
282
283 return sprintf(buf, "%d\n",
284 fan_data->speed[fan_data->num_speed - 1].rpm);
285 }
286
fan1_input_show(struct device * dev,struct device_attribute * attr,char * buf)287 static ssize_t fan1_input_show(struct device *dev,
288 struct device_attribute *attr, char *buf)
289 {
290 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
291
292 return sprintf(buf, "%d\n", fan_data->speed[fan_data->speed_index].rpm);
293 }
294
set_rpm(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)295 static ssize_t set_rpm(struct device *dev, struct device_attribute *attr,
296 const char *buf, size_t count)
297 {
298 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
299 unsigned long rpm;
300 int ret;
301
302 if (kstrtoul(buf, 10, &rpm))
303 return -EINVAL;
304
305 mutex_lock(&fan_data->lock);
306
307 if (!fan_data->pwm_enable) {
308 ret = -EPERM;
309 goto exit_unlock;
310 }
311
312 ret = set_fan_speed(fan_data, rpm_to_speed_index(fan_data, rpm));
313
314 exit_unlock:
315 mutex_unlock(&fan_data->lock);
316
317 return ret ? ret : count;
318 }
319
320 static DEVICE_ATTR_RW(pwm1);
321 static DEVICE_ATTR_RW(pwm1_enable);
322 static DEVICE_ATTR_RO(pwm1_mode);
323 static DEVICE_ATTR_RO(fan1_min);
324 static DEVICE_ATTR_RO(fan1_max);
325 static DEVICE_ATTR_RO(fan1_input);
326 static DEVICE_ATTR(fan1_target, 0644, fan1_input_show, set_rpm);
327
gpio_fan_is_visible(struct kobject * kobj,struct attribute * attr,int index)328 static umode_t gpio_fan_is_visible(struct kobject *kobj,
329 struct attribute *attr, int index)
330 {
331 struct device *dev = kobj_to_dev(kobj);
332 struct gpio_fan_data *data = dev_get_drvdata(dev);
333
334 if (index == 0 && !data->alarm_gpio)
335 return 0;
336 if (index > 0 && !data->gpios)
337 return 0;
338
339 return attr->mode;
340 }
341
342 static struct attribute *gpio_fan_attributes[] = {
343 &dev_attr_fan1_alarm.attr, /* 0 */
344 &dev_attr_pwm1.attr, /* 1 */
345 &dev_attr_pwm1_enable.attr,
346 &dev_attr_pwm1_mode.attr,
347 &dev_attr_fan1_input.attr,
348 &dev_attr_fan1_target.attr,
349 &dev_attr_fan1_min.attr,
350 &dev_attr_fan1_max.attr,
351 NULL
352 };
353
354 static const struct attribute_group gpio_fan_group = {
355 .attrs = gpio_fan_attributes,
356 .is_visible = gpio_fan_is_visible,
357 };
358
359 static const struct attribute_group *gpio_fan_groups[] = {
360 &gpio_fan_group,
361 NULL
362 };
363
fan_ctrl_init(struct gpio_fan_data * fan_data)364 static int fan_ctrl_init(struct gpio_fan_data *fan_data)
365 {
366 int num_gpios = fan_data->num_gpios;
367 struct gpio_desc **gpios = fan_data->gpios;
368 int i, err;
369
370 for (i = 0; i < num_gpios; i++) {
371 /*
372 * The GPIO descriptors were retrieved with GPIOD_ASIS so here
373 * we set the GPIO into output mode, carefully preserving the
374 * current value by setting it to whatever it is already set
375 * (no surprise changes in default fan speed).
376 */
377 err = gpiod_direction_output(gpios[i],
378 gpiod_get_value_cansleep(gpios[i]));
379 if (err)
380 return err;
381 }
382
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 return fan_data->speed_index;
387
388 return 0;
389 }
390
gpio_fan_get_max_state(struct thermal_cooling_device * cdev,unsigned long * state)391 static int gpio_fan_get_max_state(struct thermal_cooling_device *cdev,
392 unsigned long *state)
393 {
394 struct gpio_fan_data *fan_data = cdev->devdata;
395
396 if (!fan_data)
397 return -EINVAL;
398
399 *state = fan_data->num_speed - 1;
400 return 0;
401 }
402
gpio_fan_get_cur_state(struct thermal_cooling_device * cdev,unsigned long * state)403 static int gpio_fan_get_cur_state(struct thermal_cooling_device *cdev,
404 unsigned long *state)
405 {
406 struct gpio_fan_data *fan_data = cdev->devdata;
407
408 if (!fan_data)
409 return -EINVAL;
410
411 *state = fan_data->speed_index;
412 return 0;
413 }
414
gpio_fan_set_cur_state(struct thermal_cooling_device * cdev,unsigned long state)415 static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev,
416 unsigned long state)
417 {
418 struct gpio_fan_data *fan_data = cdev->devdata;
419 int ret;
420
421 if (!fan_data)
422 return -EINVAL;
423
424 if (state >= fan_data->num_speed)
425 return -EINVAL;
426
427 mutex_lock(&fan_data->lock);
428
429 ret = set_fan_speed(fan_data, state);
430
431 mutex_unlock(&fan_data->lock);
432
433 return ret;
434 }
435
436 static const struct thermal_cooling_device_ops gpio_fan_cool_ops = {
437 .get_max_state = gpio_fan_get_max_state,
438 .get_cur_state = gpio_fan_get_cur_state,
439 .set_cur_state = gpio_fan_set_cur_state,
440 };
441
442 /*
443 * Translate OpenFirmware node properties into platform_data
444 */
gpio_fan_get_of_data(struct gpio_fan_data * fan_data)445 static int gpio_fan_get_of_data(struct gpio_fan_data *fan_data)
446 {
447 struct gpio_fan_speed *speed;
448 struct device *dev = fan_data->dev;
449 struct device_node *np = dev->of_node;
450 struct gpio_desc **gpios;
451 unsigned i;
452 u32 u;
453 struct property *prop;
454 const __be32 *p;
455
456 /* Alarm GPIO if one exists */
457 fan_data->alarm_gpio = devm_gpiod_get_optional(dev, "alarm", GPIOD_IN);
458 if (IS_ERR(fan_data->alarm_gpio))
459 return PTR_ERR(fan_data->alarm_gpio);
460
461 /* Fill GPIO pin array */
462 fan_data->num_gpios = gpiod_count(dev, NULL);
463 if (fan_data->num_gpios <= 0) {
464 if (fan_data->alarm_gpio)
465 return 0;
466 dev_err(dev, "DT properties empty / missing");
467 return -ENODEV;
468 }
469 gpios = devm_kcalloc(dev,
470 fan_data->num_gpios, sizeof(struct gpio_desc *),
471 GFP_KERNEL);
472 if (!gpios)
473 return -ENOMEM;
474 for (i = 0; i < fan_data->num_gpios; i++) {
475 gpios[i] = devm_gpiod_get_index(dev, NULL, i, GPIOD_ASIS);
476 if (IS_ERR(gpios[i]))
477 return PTR_ERR(gpios[i]);
478 }
479 fan_data->gpios = gpios;
480
481 /* Get number of RPM/ctrl_val pairs in speed map */
482 prop = of_find_property(np, "gpio-fan,speed-map", &i);
483 if (!prop) {
484 dev_err(dev, "gpio-fan,speed-map DT property missing");
485 return -ENODEV;
486 }
487 i = i / sizeof(u32);
488 if (i == 0 || i & 1) {
489 dev_err(dev, "gpio-fan,speed-map contains zero/odd number of entries");
490 return -ENODEV;
491 }
492 fan_data->num_speed = i / 2;
493
494 /*
495 * Populate speed map
496 * Speed map is in the form <RPM ctrl_val RPM ctrl_val ...>
497 * this needs splitting into pairs to create gpio_fan_speed structs
498 */
499 speed = devm_kcalloc(dev,
500 fan_data->num_speed, sizeof(struct gpio_fan_speed),
501 GFP_KERNEL);
502 if (!speed)
503 return -ENOMEM;
504 p = NULL;
505 for (i = 0; i < fan_data->num_speed; i++) {
506 p = of_prop_next_u32(prop, p, &u);
507 if (!p)
508 return -ENODEV;
509 speed[i].rpm = u;
510 p = of_prop_next_u32(prop, p, &u);
511 if (!p)
512 return -ENODEV;
513 speed[i].ctrl_val = u;
514 }
515 fan_data->speed = speed;
516
517 return 0;
518 }
519
520 static const struct of_device_id of_gpio_fan_match[] = {
521 { .compatible = "gpio-fan", },
522 {},
523 };
524 MODULE_DEVICE_TABLE(of, of_gpio_fan_match);
525
gpio_fan_stop(void * data)526 static void gpio_fan_stop(void *data)
527 {
528 struct gpio_fan_data *fan_data = data;
529
530 mutex_lock(&fan_data->lock);
531 set_fan_speed(data, 0);
532 mutex_unlock(&fan_data->lock);
533
534 pm_runtime_disable(fan_data->dev);
535 }
536
gpio_fan_probe(struct platform_device * pdev)537 static int gpio_fan_probe(struct platform_device *pdev)
538 {
539 int err;
540 struct gpio_fan_data *fan_data;
541 struct device *dev = &pdev->dev;
542 struct device_node *np = dev->of_node;
543
544 fan_data = devm_kzalloc(dev, sizeof(struct gpio_fan_data),
545 GFP_KERNEL);
546 if (!fan_data)
547 return -ENOMEM;
548
549 fan_data->dev = dev;
550 err = gpio_fan_get_of_data(fan_data);
551 if (err)
552 return err;
553
554 platform_set_drvdata(pdev, fan_data);
555 mutex_init(&fan_data->lock);
556
557 fan_data->supply = devm_regulator_get(dev, "fan");
558 if (IS_ERR(fan_data->supply))
559 return dev_err_probe(dev, PTR_ERR(fan_data->supply),
560 "Failed to get fan-supply");
561
562 /* Configure control GPIOs if available. */
563 if (fan_data->gpios && fan_data->num_gpios > 0) {
564 if (!fan_data->speed || fan_data->num_speed <= 1)
565 return -EINVAL;
566 err = fan_ctrl_init(fan_data);
567 if (err)
568 return err;
569 err = devm_add_action_or_reset(dev, gpio_fan_stop, fan_data);
570 if (err)
571 return err;
572 }
573
574 /* Make this driver part of hwmon class. */
575 fan_data->hwmon_dev =
576 devm_hwmon_device_register_with_groups(dev,
577 "gpio_fan", fan_data,
578 gpio_fan_groups);
579 if (IS_ERR(fan_data->hwmon_dev))
580 return PTR_ERR(fan_data->hwmon_dev);
581
582 /* Configure alarm GPIO if available. */
583 if (fan_data->alarm_gpio) {
584 err = fan_alarm_init(fan_data);
585 if (err)
586 return err;
587 }
588
589 pm_runtime_set_suspended(&pdev->dev);
590 pm_runtime_enable(&pdev->dev);
591 /* If current GPIO state is active, mark RPM as active as well */
592 if (fan_data->speed_index > 0) {
593 int ret;
594
595 ret = pm_runtime_resume_and_get(&pdev->dev);
596 if (ret)
597 return ret;
598 }
599
600 /* Optional cooling device register for Device tree platforms */
601 fan_data->cdev = devm_thermal_of_child_cooling_device_register(dev, np,
602 "gpio-fan",
603 fan_data,
604 &gpio_fan_cool_ops);
605
606 dev_info(dev, "GPIO fan initialized\n");
607
608 return 0;
609 }
610
gpio_fan_shutdown(struct platform_device * pdev)611 static void gpio_fan_shutdown(struct platform_device *pdev)
612 {
613 struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
614
615 if (fan_data->gpios) {
616 mutex_lock(&fan_data->lock);
617 set_fan_speed(fan_data, 0);
618 mutex_unlock(&fan_data->lock);
619 }
620 }
621
gpio_fan_runtime_suspend(struct device * dev)622 static int gpio_fan_runtime_suspend(struct device *dev)
623 {
624 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
625 int ret = 0;
626
627 if (fan_data->supply)
628 ret = regulator_disable(fan_data->supply);
629
630 return ret;
631 }
632
gpio_fan_runtime_resume(struct device * dev)633 static int gpio_fan_runtime_resume(struct device *dev)
634 {
635 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
636 int ret = 0;
637
638 if (fan_data->supply)
639 ret = regulator_enable(fan_data->supply);
640
641 return ret;
642 }
643
gpio_fan_suspend(struct device * dev)644 static int gpio_fan_suspend(struct device *dev)
645 {
646 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
647 int ret = 0;
648
649 if (fan_data->gpios) {
650 fan_data->resume_speed = fan_data->speed_index;
651 mutex_lock(&fan_data->lock);
652 ret = set_fan_speed(fan_data, 0);
653 mutex_unlock(&fan_data->lock);
654 }
655
656 return ret;
657 }
658
gpio_fan_resume(struct device * dev)659 static int gpio_fan_resume(struct device *dev)
660 {
661 struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
662 int ret = 0;
663
664 if (fan_data->gpios) {
665 mutex_lock(&fan_data->lock);
666 ret = set_fan_speed(fan_data, fan_data->resume_speed);
667 mutex_unlock(&fan_data->lock);
668 }
669
670 return ret;
671 }
672
673 static const struct dev_pm_ops gpio_fan_pm = {
674 RUNTIME_PM_OPS(gpio_fan_runtime_suspend,
675 gpio_fan_runtime_resume, NULL)
676 SYSTEM_SLEEP_PM_OPS(gpio_fan_suspend, gpio_fan_resume)
677 };
678
679 static struct platform_driver gpio_fan_driver = {
680 .probe = gpio_fan_probe,
681 .shutdown = gpio_fan_shutdown,
682 .driver = {
683 .name = "gpio-fan",
684 .pm = pm_ptr(&gpio_fan_pm),
685 .of_match_table = of_gpio_fan_match,
686 },
687 };
688
689 module_platform_driver(gpio_fan_driver);
690
691 MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
692 MODULE_DESCRIPTION("GPIO FAN driver");
693 MODULE_LICENSE("GPL");
694 MODULE_ALIAS("platform:gpio-fan");
695