Skip to content

Commit a7ad5d9

Browse files
Ian TrambleStaphylo
Ian Tramble
authored andcommitted
Expose rook fan leds in /sys/class/leds
Change-Id: I4249d8aab79cadd7ea2f87d8dbea7085633a2e9e
1 parent d419696 commit a7ad5d9

File tree

1 file changed

+70
-8
lines changed

1 file changed

+70
-8
lines changed

src/rook-fan-cpld.c

+70-8
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222
#include <linux/i2c.h>
2323
#include <linux/slab.h>
2424
#include <linux/workqueue.h>
25+
#include <linux/leds.h>
2526

2627
#define DRIVER_NAME "rook-fan-cpld"
2728

29+
#define LED_NAME_MAX_SZ 20
2830
#define MAX_FAN_COUNT 8
2931

3032
#define MINOR_VERSION_REG 0x00
@@ -57,6 +59,8 @@
5759
#define FAN_INT_PRES (1 << 1)
5860
#define FAN_INT_ID (1 << 2)
5961

62+
#define FAN_LED_GREEN 1
63+
#define FAN_LED_RED 2
6064

6165
static bool managed_leds = true;
6266
module_param(managed_leds, bool, S_IRUSR | S_IWUSR);
@@ -92,12 +96,15 @@ static struct cpld_info cpld_infos[] = {
9296
};
9397

9498
struct cpld_fan_data {
99+
struct led_classdev cdev;
95100
bool ok;
96101
bool present;
97102
bool forward;
98103
u16 tach;
99104
u8 pwm;
100105
u8 ident;
106+
u8 index;
107+
char led_name[LED_NAME_MAX_SZ];
101108
};
102109

103110
struct cpld_data {
@@ -442,9 +449,9 @@ static s32 cpld_read_fan_led(struct cpld_data *data, u8 fan_id, u8 *val)
442449

443450
*val = 0;
444451
if (green)
445-
*val += 1;
452+
*val += FAN_LED_GREEN;
446453
if (red)
447-
*val += 2;
454+
*val += FAN_LED_RED;
448455

449456
return 0;
450457
}
@@ -453,12 +460,15 @@ static s32 cpld_write_fan_led(struct cpld_data *cpld, u8 fan_id, u8 val)
453460
{
454461
int err = 0;
455462

456-
if (val & 0x01)
463+
if (val > 3)
464+
return -EINVAL;
465+
466+
if (val & FAN_LED_GREEN)
457467
cpld->green_led |= (1 << fan_id);
458468
else
459469
cpld->green_led &= ~(1 << fan_id);
460470

461-
if (val & 0x2)
471+
if (val & FAN_LED_RED)
462472
cpld->red_led |= (1 << fan_id);
463473
else
464474
cpld->red_led &= ~(1 << fan_id);
@@ -472,6 +482,53 @@ static s32 cpld_write_fan_led(struct cpld_data *cpld, u8 fan_id, u8 val)
472482
return err;
473483
}
474484

485+
static int brightness_set(struct led_classdev *led_cdev, u8 val)
486+
{
487+
struct cpld_fan_data *fan = container_of(led_cdev, struct cpld_fan_data,
488+
cdev);
489+
struct cpld_data *data = dev_get_drvdata(led_cdev->dev->parent);
490+
491+
return cpld_write_fan_led(data, fan->index, val);
492+
}
493+
494+
static int brightness_get(struct led_classdev *led_cdev)
495+
{
496+
struct cpld_fan_data *fan = container_of(led_cdev, struct cpld_fan_data,
497+
cdev);
498+
struct cpld_data *data = dev_get_drvdata(led_cdev->dev->parent);
499+
int err;
500+
u8 val;
501+
502+
err = cpld_read_fan_led(data, fan->index, &val);
503+
if (err)
504+
return err;
505+
506+
return val;
507+
}
508+
509+
static int led_init(struct cpld_fan_data *fan, struct i2c_client *client,
510+
int fan_index)
511+
{
512+
fan->index = fan_index;
513+
fan->cdev.brightness_set = brightness_set;
514+
fan->cdev.brightness_get = brightness_get;
515+
scnprintf(fan->led_name, LED_NAME_MAX_SZ, "fan%d", fan->index + 1);
516+
fan->cdev.name = fan->led_name;
517+
518+
return led_classdev_register(&client->dev, &fan->cdev);
519+
}
520+
521+
static void cpld_leds_unregister(struct cpld_data *cpld, int num_leds)
522+
{
523+
int i = 0;
524+
struct cpld_fan_data *fan;
525+
526+
for (i = 0; i < num_leds; i++) {
527+
fan = fan_from_cpld(cpld, i);
528+
led_classdev_unregister(&fan->cdev);
529+
}
530+
}
531+
475532
static ssize_t cpld_fan_pwm_show(struct device *dev, struct device_attribute *da,
476533
char *buf)
477534
{
@@ -773,6 +830,11 @@ static int cpld_init(struct cpld_data *cpld)
773830
cpld_read_fan_id(cpld, i);
774831
cpld_read_fan_tach(cpld, i);
775832
cpld_read_fan_pwm(cpld, i);
833+
err = led_init(fan, cpld->client, i);
834+
if (err) {
835+
cpld_leds_unregister(cpld, i);
836+
return err;
837+
}
776838
}
777839
}
778840

@@ -807,9 +869,8 @@ static int cpld_probe(struct i2c_client *client,
807869
}
808870

809871
cpld = devm_kzalloc(dev, sizeof(struct cpld_data), GFP_KERNEL);
810-
if (!cpld) {
872+
if (!cpld)
811873
return -ENOMEM;
812-
}
813874

814875
i2c_set_clientdata(client, cpld);
815876
cpld->client = client;
@@ -824,9 +885,8 @@ static int cpld_probe(struct i2c_client *client,
824885

825886
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
826887
cpld, cpld->groups);
827-
if (IS_ERR(hwmon_dev)) {
888+
if (IS_ERR(hwmon_dev))
828889
return PTR_ERR(hwmon_dev);
829-
}
830890

831891
cpld->hwmon_dev = hwmon_dev;
832892

@@ -845,6 +905,8 @@ static int cpld_remove(struct i2c_client *client)
845905
cancel_delayed_work_sync(&cpld->dwork);
846906
mutex_unlock(&cpld->lock);
847907

908+
cpld_leds_unregister(cpld, cpld->info->fan_count);
909+
848910
return 0;
849911
}
850912

0 commit comments

Comments
 (0)