Skip to content

Commit 55fb8b0

Browse files
lentinjJason Cooper
authored andcommitted
hwmon: Add devicetree bindings to gpio-fan
Allow a gpio-fan to be defined in devicetree, see binding documentation for details. Signed-off-by: Jamie Lentin <jm@lentin.co.uk> Acked-by: Andrew Lunn <andrew@lunn.ch> Acked-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
1 parent f37fbd3 commit 55fb8b0

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Bindings for fan connected to GPIO lines
2+
3+
Required properties:
4+
- compatible : "gpio-fan"
5+
- gpios: Specifies the pins that map to bits in the control value,
6+
ordered MSB-->LSB.
7+
- gpio-fan,speed-map: A mapping of possible fan RPM speeds and the
8+
control value that should be set to achieve them. This array
9+
must have the RPM values in ascending order.
10+
11+
Optional properties:
12+
- alarm-gpios: This pin going active indicates something is wrong with
13+
the fan, and a udev event will be fired.
14+
15+
Examples:
16+
17+
gpio_fan {
18+
compatible = "gpio-fan";
19+
gpios = <&gpio1 14 1
20+
&gpio1 13 1>;
21+
gpio-fan,speed-map = <0 0
22+
3000 1
23+
6000 2>;
24+
alarm-gpios = <&gpio1 15 1>;
25+
};

drivers/hwmon/gpio-fan.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include <linux/hwmon.h>
3232
#include <linux/gpio.h>
3333
#include <linux/gpio-fan.h>
34+
#include <linux/of_platform.h>
35+
#include <linux/of_gpio.h>
3436

3537
struct gpio_fan_data {
3638
struct platform_device *pdev;
@@ -400,14 +402,131 @@ static ssize_t show_name(struct device *dev,
400402

401403
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
402404

405+
406+
#ifdef CONFIG_OF_GPIO
407+
/*
408+
* Translate OpenFirmware node properties into platform_data
409+
*/
410+
static int gpio_fan_get_of_pdata(struct device *dev,
411+
struct gpio_fan_platform_data *pdata)
412+
{
413+
struct device_node *node;
414+
struct gpio_fan_speed *speed;
415+
unsigned *ctrl;
416+
unsigned i;
417+
u32 u;
418+
struct property *prop;
419+
const __be32 *p;
420+
421+
node = dev->of_node;
422+
423+
/* Fill GPIO pin array */
424+
pdata->num_ctrl = of_gpio_count(node);
425+
if (!pdata->num_ctrl) {
426+
dev_err(dev, "gpios DT property empty / missing");
427+
return -ENODEV;
428+
}
429+
ctrl = devm_kzalloc(dev, pdata->num_ctrl * sizeof(unsigned),
430+
GFP_KERNEL);
431+
if (!ctrl)
432+
return -ENOMEM;
433+
for (i = 0; i < pdata->num_ctrl; i++) {
434+
int val;
435+
436+
val = of_get_gpio(node, i);
437+
if (val < 0)
438+
return val;
439+
ctrl[i] = val;
440+
}
441+
pdata->ctrl = ctrl;
442+
443+
/* Get number of RPM/ctrl_val pairs in speed map */
444+
prop = of_find_property(node, "gpio-fan,speed-map", &i);
445+
if (!prop) {
446+
dev_err(dev, "gpio-fan,speed-map DT property missing");
447+
return -ENODEV;
448+
}
449+
i = i / sizeof(u32);
450+
if (i == 0 || i & 1) {
451+
dev_err(dev, "gpio-fan,speed-map contains zero/odd number of entries");
452+
return -ENODEV;
453+
}
454+
pdata->num_speed = i / 2;
455+
456+
/*
457+
* Populate speed map
458+
* Speed map is in the form <RPM ctrl_val RPM ctrl_val ...>
459+
* this needs splitting into pairs to create gpio_fan_speed structs
460+
*/
461+
speed = devm_kzalloc(dev,
462+
pdata->num_speed * sizeof(struct gpio_fan_speed),
463+
GFP_KERNEL);
464+
if (!speed)
465+
return -ENOMEM;
466+
p = NULL;
467+
for (i = 0; i < pdata->num_speed; i++) {
468+
p = of_prop_next_u32(prop, p, &u);
469+
if (!p)
470+
return -ENODEV;
471+
speed[i].rpm = u;
472+
p = of_prop_next_u32(prop, p, &u);
473+
if (!p)
474+
return -ENODEV;
475+
speed[i].ctrl_val = u;
476+
}
477+
pdata->speed = speed;
478+
479+
/* Alarm GPIO if one exists */
480+
if (of_gpio_named_count(node, "alarm-gpios")) {
481+
struct gpio_fan_alarm *alarm;
482+
int val;
483+
enum of_gpio_flags flags;
484+
485+
alarm = devm_kzalloc(dev, sizeof(struct gpio_fan_alarm),
486+
GFP_KERNEL);
487+
if (!alarm)
488+
return -ENOMEM;
489+
490+
val = of_get_named_gpio_flags(node, "alarm-gpios", 0, &flags);
491+
if (val < 0)
492+
return val;
493+
alarm->gpio = val;
494+
alarm->active_low = flags & OF_GPIO_ACTIVE_LOW;
495+
496+
pdata->alarm = alarm;
497+
}
498+
499+
return 0;
500+
}
501+
502+
static struct of_device_id of_gpio_fan_match[] __devinitdata = {
503+
{ .compatible = "gpio-fan", },
504+
{},
505+
};
506+
#endif /* CONFIG_OF_GPIO */
507+
403508
static int __devinit gpio_fan_probe(struct platform_device *pdev)
404509
{
405510
int err;
406511
struct gpio_fan_data *fan_data;
407512
struct gpio_fan_platform_data *pdata = pdev->dev.platform_data;
408513

514+
#ifdef CONFIG_OF_GPIO
515+
if (!pdata) {
516+
pdata = devm_kzalloc(&pdev->dev,
517+
sizeof(struct gpio_fan_platform_data),
518+
GFP_KERNEL);
519+
if (!pdata)
520+
return -ENOMEM;
521+
522+
err = gpio_fan_get_of_pdata(&pdev->dev, pdata);
523+
if (err)
524+
return err;
525+
}
526+
#else /* CONFIG_OF_GPIO */
409527
if (!pdata)
410528
return -EINVAL;
529+
#endif /* CONFIG_OF_GPIO */
411530

412531
fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data),
413532
GFP_KERNEL);
@@ -511,6 +630,7 @@ static struct platform_driver gpio_fan_driver = {
511630
.driver = {
512631
.name = "gpio-fan",
513632
.pm = GPIO_FAN_PM,
633+
.of_match_table = of_match_ptr(of_gpio_fan_match),
514634
},
515635
};
516636

0 commit comments

Comments
 (0)