diff options
author | Jamie Lentin <jm@lentin.co.uk> | 2012-09-14 12:07:06 -0400 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2012-09-22 10:40:49 -0400 |
commit | 55fb8b06813b190a9366fee396fac109638a9c9d (patch) | |
tree | bdb224ab7df6228fed8ec0e4b716a3ce697ee99c /drivers | |
parent | f37fbd36c5f9fe716ddf783415a67de03fb0dc3d (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/gpio-fan.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 2f4b01bda87c..36509ae32083 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/hwmon.h> | 31 | #include <linux/hwmon.h> |
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/gpio-fan.h> | 33 | #include <linux/gpio-fan.h> |
34 | #include <linux/of_platform.h> | ||
35 | #include <linux/of_gpio.h> | ||
34 | 36 | ||
35 | struct gpio_fan_data { | 37 | struct gpio_fan_data { |
36 | struct platform_device *pdev; | 38 | struct platform_device *pdev; |
@@ -400,14 +402,131 @@ static ssize_t show_name(struct device *dev, | |||
400 | 402 | ||
401 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | 403 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
402 | 404 | ||
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 | |||
403 | static int __devinit gpio_fan_probe(struct platform_device *pdev) | 508 | static int __devinit gpio_fan_probe(struct platform_device *pdev) |
404 | { | 509 | { |
405 | int err; | 510 | int err; |
406 | struct gpio_fan_data *fan_data; | 511 | struct gpio_fan_data *fan_data; |
407 | struct gpio_fan_platform_data *pdata = pdev->dev.platform_data; | 512 | struct gpio_fan_platform_data *pdata = pdev->dev.platform_data; |
408 | 513 | ||
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 */ | ||
409 | if (!pdata) | 527 | if (!pdata) |
410 | return -EINVAL; | 528 | return -EINVAL; |
529 | #endif /* CONFIG_OF_GPIO */ | ||
411 | 530 | ||
412 | fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data), | 531 | fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data), |
413 | GFP_KERNEL); | 532 | GFP_KERNEL); |
@@ -511,6 +630,7 @@ static struct platform_driver gpio_fan_driver = { | |||
511 | .driver = { | 630 | .driver = { |
512 | .name = "gpio-fan", | 631 | .name = "gpio-fan", |
513 | .pm = GPIO_FAN_PM, | 632 | .pm = GPIO_FAN_PM, |
633 | .of_match_table = of_match_ptr(of_gpio_fan_match), | ||
514 | }, | 634 | }, |
515 | }; | 635 | }; |
516 | 636 | ||