brintos

brintos / linux-shallow public Read only

0
0
Text · 3.0 KiB · dd319c7 Raw
134 lines · c
1// SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0-or-later2/*3 * Dell Wyse 3020 a.k.a. "Ariel" Embedded Controller LED Driver4 *5 * Copyright (C) 2020 Lubomir Rintel6 */7 8#include <linux/module.h>9#include <linux/leds.h>10#include <linux/platform_device.h>11#include <linux/regmap.h>12 13enum ec_index {14	EC_BLUE_LED	= 0x01,15	EC_AMBER_LED	= 0x02,16	EC_GREEN_LED	= 0x03,17};18 19enum {20	EC_LED_OFF	= 0x00,21	EC_LED_STILL	= 0x01,22	EC_LED_FADE	= 0x02,23	EC_LED_BLINK	= 0x03,24};25 26struct ariel_led {27	struct regmap *ec_ram;28	enum ec_index ec_index;29	struct led_classdev led_cdev;30};31 32#define led_cdev_to_ariel_led(c) container_of(c, struct ariel_led, led_cdev)33 34static enum led_brightness ariel_led_get(struct led_classdev *led_cdev)35{36	struct ariel_led *led = led_cdev_to_ariel_led(led_cdev);37	unsigned int led_status = 0;38 39	if (regmap_read(led->ec_ram, led->ec_index, &led_status))40		return LED_OFF;41 42	if (led_status == EC_LED_STILL)43		return LED_FULL;44	else45		return LED_OFF;46}47 48static void ariel_led_set(struct led_classdev *led_cdev,49			  enum led_brightness brightness)50{51	struct ariel_led *led = led_cdev_to_ariel_led(led_cdev);52 53	if (brightness == LED_OFF)54		regmap_write(led->ec_ram, led->ec_index, EC_LED_OFF);55	else56		regmap_write(led->ec_ram, led->ec_index, EC_LED_STILL);57}58 59static int ariel_blink_set(struct led_classdev *led_cdev,60			   unsigned long *delay_on, unsigned long *delay_off)61{62	struct ariel_led *led = led_cdev_to_ariel_led(led_cdev);63 64	if (*delay_on == 0 && *delay_off == 0)65		return -EINVAL;66 67	if (*delay_on == 0) {68		regmap_write(led->ec_ram, led->ec_index, EC_LED_OFF);69	} else if (*delay_off == 0) {70		regmap_write(led->ec_ram, led->ec_index, EC_LED_STILL);71	} else {72		*delay_on = 500;73		*delay_off = 500;74		regmap_write(led->ec_ram, led->ec_index, EC_LED_BLINK);75	}76 77	return 0;78}79 80#define NLEDS 381 82static int ariel_led_probe(struct platform_device *pdev)83{84	struct device *dev = &pdev->dev;85	struct ariel_led *leds;86	struct regmap *ec_ram;87	int ret;88	int i;89 90	ec_ram = dev_get_regmap(dev->parent, "ec_ram");91	if (!ec_ram)92		return -ENODEV;93 94	leds = devm_kcalloc(dev, NLEDS, sizeof(*leds), GFP_KERNEL);95	if (!leds)96		return -ENOMEM;97 98	leds[0].ec_index = EC_BLUE_LED;99	leds[0].led_cdev.name = "blue:power";100	leds[0].led_cdev.default_trigger = "default-on";101 102	leds[1].ec_index = EC_AMBER_LED;103	leds[1].led_cdev.name = "amber:status";104 105	leds[2].ec_index = EC_GREEN_LED;106	leds[2].led_cdev.name = "green:status";107	leds[2].led_cdev.default_trigger = "default-on";108 109	for (i = 0; i < NLEDS; i++) {110		leds[i].ec_ram = ec_ram;111		leds[i].led_cdev.brightness_get = ariel_led_get;112		leds[i].led_cdev.brightness_set = ariel_led_set;113		leds[i].led_cdev.blink_set = ariel_blink_set;114 115		ret = devm_led_classdev_register(dev, &leds[i].led_cdev);116		if (ret)117			return ret;118	}119 120	return 0;121}122 123static struct platform_driver ariel_led_driver = {124	.probe = ariel_led_probe,125	.driver = {126		.name = "dell-wyse-ariel-led",127	},128};129module_platform_driver(ariel_led_driver);130 131MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");132MODULE_DESCRIPTION("Dell Wyse 3020 Status LEDs Driver");133MODULE_LICENSE("Dual BSD/GPL");134