diff options
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/Kconfig | 14 | ||||
-rw-r--r-- | drivers/leds/Makefile | 1 | ||||
-rw-r--r-- | drivers/leds/led-triggers.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-gpio.c | 5 | ||||
-rw-r--r-- | drivers/leds/leds-hp6xx.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-is31fl32xx.c | 24 | ||||
-rw-r--r-- | drivers/leds/leds-lp3952.c | 301 | ||||
-rw-r--r-- | drivers/leds/leds-pca9532.c | 75 | ||||
-rw-r--r-- | drivers/leds/leds-powernv.c | 2 | ||||
-rw-r--r-- | drivers/leds/trigger/Kconfig | 8 | ||||
-rw-r--r-- | drivers/leds/trigger/Makefile | 2 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-cpu.c | 32 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-disk.c | 41 |
13 files changed, 470 insertions, 39 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 5ae28340a..9dcc9b13d 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -228,6 +228,20 @@ config LEDS_LP3944 To compile this driver as a module, choose M here: the module will be called leds-lp3944. +config LEDS_LP3952 + tristate "LED Support for TI LP3952 2 channel LED driver" + depends on LEDS_CLASS + depends on I2C + depends on ACPI + depends on GPIOLIB + select REGMAP_I2C + help + This option enables support for LEDs connected to the Texas + Instruments LP3952 LED driver. + + To compile this driver as a module, choose M here: the + module will be called leds-lp3952. + config LEDS_LP55XX_COMMON tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501" depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501 diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index cb2013df5..0684c865a 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o +obj-$(CONFIG_LEDS_LP3952) += leds-lp3952.o obj-$(CONFIG_LEDS_LP55XX_COMMON) += leds-lp55xx-common.o obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 55fa65e1a..c92702a68 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -60,6 +60,8 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, goto unlock; } } + /* we come here only if buf matches no trigger */ + ret = -EINVAL; up_read(&triggers_list_lock); unlock: diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 8229f063b..9b991d46e 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -165,6 +165,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) return ERR_PTR(-ENOMEM); device_for_each_child_node(dev, child) { + struct gpio_led_data *led_dat = &priv->leds[priv->num_leds]; struct gpio_led led = {}; const char *state = NULL; @@ -205,12 +206,12 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) if (fwnode_property_present(child, "panic-indicator")) led.panic_indicator = 1; - ret = create_gpio_led(&led, &priv->leds[priv->num_leds], - dev, NULL); + ret = create_gpio_led(&led, led_dat, dev, NULL); if (ret < 0) { fwnode_handle_put(child); goto err; } + led_dat->cdev.dev->of_node = np; priv->num_leds++; } diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c index a6b8db0e2..137969fce 100644 --- a/drivers/leds/leds-hp6xx.c +++ b/drivers/leds/leds-hp6xx.c @@ -50,7 +50,7 @@ static struct led_classdev hp6xx_red_led = { static struct led_classdev hp6xx_green_led = { .name = "hp6xx:green", - .default_trigger = "ide-disk", + .default_trigger = "disk-activity", .brightness_set = hp6xxled_green_set, .flags = LED_CORE_SUSPENDRESUME, }; diff --git a/drivers/leds/leds-is31fl32xx.c b/drivers/leds/leds-is31fl32xx.c index c901d132d..478844c5c 100644 --- a/drivers/leds/leds-is31fl32xx.c +++ b/drivers/leds/leds-is31fl32xx.c @@ -422,7 +422,7 @@ err: return ret; } -static const struct of_device_id of_is31fl31xx_match[] = { +static const struct of_device_id of_is31fl32xx_match[] = { { .compatible = "issi,is31fl3236", .data = &is31fl3236_cdef, }, { .compatible = "issi,is31fl3235", .data = &is31fl3235_cdef, }, { .compatible = "issi,is31fl3218", .data = &is31fl3218_cdef, }, @@ -432,7 +432,7 @@ static const struct of_device_id of_is31fl31xx_match[] = { {}, }; -MODULE_DEVICE_TABLE(of, of_is31fl31xx_match); +MODULE_DEVICE_TABLE(of, of_is31fl32xx_match); static int is31fl32xx_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -444,7 +444,7 @@ static int is31fl32xx_probe(struct i2c_client *client, int count; int ret = 0; - of_dev_id = of_match_device(of_is31fl31xx_match, dev); + of_dev_id = of_match_device(of_is31fl32xx_match, dev); if (!of_dev_id) return -EINVAL; @@ -482,23 +482,29 @@ static int is31fl32xx_remove(struct i2c_client *client) } /* - * i2c-core requires that id_table be non-NULL, even though - * it is not used for DeviceTree based instantiation. + * i2c-core (and modalias) requires that id_table be properly filled, + * even though it is not used for DeviceTree based instantiation. */ -static const struct i2c_device_id is31fl31xx_id[] = { +static const struct i2c_device_id is31fl32xx_id[] = { + { "is31fl3236" }, + { "is31fl3235" }, + { "is31fl3218" }, + { "sn3218" }, + { "is31fl3216" }, + { "sn3216" }, {}, }; -MODULE_DEVICE_TABLE(i2c, is31fl31xx_id); +MODULE_DEVICE_TABLE(i2c, is31fl32xx_id); static struct i2c_driver is31fl32xx_driver = { .driver = { .name = "is31fl32xx", - .of_match_table = of_is31fl31xx_match, + .of_match_table = of_is31fl32xx_match, }, .probe = is31fl32xx_probe, .remove = is31fl32xx_remove, - .id_table = is31fl31xx_id, + .id_table = is31fl32xx_id, }; module_i2c_driver(is31fl32xx_driver); diff --git a/drivers/leds/leds-lp3952.c b/drivers/leds/leds-lp3952.c new file mode 100644 index 000000000..a73c8ff08 --- /dev/null +++ b/drivers/leds/leds-lp3952.c @@ -0,0 +1,301 @@ +/* + * LED driver for TI lp3952 controller + * + * Copyright (C) 2016, DAQRI, LLC. + * Author: Tony Makkiel <tony.makkiel@daqri.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/acpi.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/leds.h> +#include <linux/leds-lp3952.h> +#include <linux/module.h> +#include <linux/notifier.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/reboot.h> +#include <linux/regmap.h> + +static int lp3952_register_write(struct i2c_client *client, u8 reg, u8 val) +{ + int ret; + struct lp3952_led_array *priv = i2c_get_clientdata(client); + + ret = regmap_write(priv->regmap, reg, val); + + if (ret) + dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", + __func__, reg, val, ret); + return ret; +} + +static void lp3952_on_off(struct lp3952_led_array *priv, + enum lp3952_leds led_id, bool on) +{ + int ret, val; + + dev_dbg(&priv->client->dev, "%s LED %d to %d\n", __func__, led_id, on); + + val = 1 << led_id; + if (led_id == LP3952_LED_ALL) + val = LP3952_LED_MASK_ALL; + + ret = regmap_update_bits(priv->regmap, LP3952_REG_LED_CTRL, val, + on ? val : 0); + if (ret) + dev_err(&priv->client->dev, "%s, Error %d\n", __func__, ret); +} + +/* + * Using Imax to control brightness. There are 4 possible + * setting 25, 50, 75 and 100 % of Imax. Possible values are + * values 0-4. 0 meaning turn off. + */ +static int lp3952_set_brightness(struct led_classdev *cdev, + enum led_brightness value) +{ + unsigned int reg, shift_val; + struct lp3952_ctrl_hdl *led = container_of(cdev, + struct lp3952_ctrl_hdl, + cdev); + struct lp3952_led_array *priv = (struct lp3952_led_array *)led->priv; + + dev_dbg(cdev->dev, "Brightness request: %d on %d\n", value, + led->channel); + + if (value == LED_OFF) { + lp3952_on_off(priv, led->channel, false); + return 0; + } + + if (led->channel > LP3952_RED_1) { + dev_err(cdev->dev, " %s Invalid LED requested", __func__); + return -EINVAL; + } + + if (led->channel >= LP3952_BLUE_1) { + reg = LP3952_REG_RGB1_MAX_I_CTRL; + shift_val = (led->channel - LP3952_BLUE_1) * 2; + } else { + reg = LP3952_REG_RGB2_MAX_I_CTRL; + shift_val = led->channel * 2; + } + + /* Enable the LED in case it is not enabled already */ + lp3952_on_off(priv, led->channel, true); + + return regmap_update_bits(priv->regmap, reg, 3 << shift_val, + --value << shift_val); +} + +static int lp3952_get_label(struct device *dev, const char *label, char *dest) +{ + int ret; + const char *str; + + ret = device_property_read_string(dev, label, &str); + if (!ret) + strncpy(dest, str, LP3952_LABEL_MAX_LEN); + + return ret; +} + +static int lp3952_register_led_classdev(struct lp3952_led_array *priv) +{ + int i, acpi_ret, ret = -ENODEV; + static const char *led_name_hdl[LP3952_LED_ALL] = { + "blue2", + "green2", + "red2", + "blue1", + "green1", + "red1" + }; + + for (i = 0; i < LP3952_LED_ALL; i++) { + acpi_ret = lp3952_get_label(&priv->client->dev, led_name_hdl[i], + priv->leds[i].name); + if (acpi_ret) + continue; + + priv->leds[i].cdev.name = priv->leds[i].name; + priv->leds[i].cdev.brightness = LED_OFF; + priv->leds[i].cdev.max_brightness = LP3952_BRIGHT_MAX; + priv->leds[i].cdev.brightness_set_blocking = + lp3952_set_brightness; + priv->leds[i].channel = i; + priv->leds[i].priv = priv; + + ret = devm_led_classdev_register(&priv->client->dev, + &priv->leds[i].cdev); + if (ret < 0) { + dev_err(&priv->client->dev, + "couldn't register LED %s\n", + priv->leds[i].cdev.name); + break; + } + } + return ret; +} + +static int lp3952_set_pattern_gen_cmd(struct lp3952_led_array *priv, + u8 cmd_index, u8 r, u8 g, u8 b, + enum lp3952_tt tt, enum lp3952_cet cet) +{ + int ret; + struct ptrn_gen_cmd line = { + { + { + .r = r, + .g = g, + .b = b, + .cet = cet, + .tt = tt + } + } + }; + + if (cmd_index >= LP3952_CMD_REG_COUNT) + return -EINVAL; + + ret = lp3952_register_write(priv->client, + LP3952_REG_CMD_0 + cmd_index * 2, + line.bytes.msb); + if (ret) + return ret; + + return lp3952_register_write(priv->client, + LP3952_REG_CMD_0 + cmd_index * 2 + 1, + line.bytes.lsb); +} + +static int lp3952_configure(struct lp3952_led_array *priv) +{ + int ret; + + /* Disable any LEDs on from any previous conf. */ + ret = lp3952_register_write(priv->client, LP3952_REG_LED_CTRL, 0); + if (ret) + return ret; + + /* enable rgb patter, loop */ + ret = lp3952_register_write(priv->client, LP3952_REG_PAT_GEN_CTRL, + LP3952_PATRN_LOOP | LP3952_PATRN_GEN_EN); + if (ret) + return ret; + + /* Update Bit 6 (Active mode), Select both Led sets, Bit [1:0] */ + ret = lp3952_register_write(priv->client, LP3952_REG_ENABLES, + LP3952_ACTIVE_MODE | LP3952_INT_B00ST_LDR); + if (ret) + return ret; + + /* Set Cmd1 for RGB intensity,cmd and transition time */ + return lp3952_set_pattern_gen_cmd(priv, 0, I46, I71, I100, TT0, + CET197); +} + +static const struct regmap_config lp3952_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_MAX, + .cache_type = REGCACHE_RBTREE, +}; + +static int lp3952_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int status; + struct lp3952_led_array *priv; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->client = client; + + priv->enable_gpio = devm_gpiod_get(&client->dev, "nrst", + GPIOD_OUT_HIGH); + if (IS_ERR(priv->enable_gpio)) { + status = PTR_ERR(priv->enable_gpio); + dev_err(&client->dev, "Failed to enable gpio: %d\n", status); + return status; + } + + priv->regmap = devm_regmap_init_i2c(client, &lp3952_regmap); + if (IS_ERR(priv->regmap)) { + int err = PTR_ERR(priv->regmap); + + dev_err(&client->dev, "Failed to allocate register map: %d\n", + err); + return err; + } + + i2c_set_clientdata(client, priv); + + status = lp3952_configure(priv); + if (status) { + dev_err(&client->dev, "Probe failed. Device not found (%d)\n", + status); + return status; + } + + status = lp3952_register_led_classdev(priv); + if (status) { + dev_err(&client->dev, "Unable to register led_classdev: %d\n", + status); + return status; + } + + return 0; +} + +static int lp3952_remove(struct i2c_client *client) +{ + struct lp3952_led_array *priv; + + priv = i2c_get_clientdata(client); + lp3952_on_off(priv, LP3952_LED_ALL, false); + gpiod_set_value(priv->enable_gpio, 0); + + return 0; +} + +static const struct i2c_device_id lp3952_id[] = { + {LP3952_NAME, 0}, + {} +}; + +#ifdef CONFIG_ACPI +static const struct acpi_device_id lp3952_acpi_match[] = { + {"TXNW3952", 0}, + {} +}; + +MODULE_DEVICE_TABLE(acpi, lp3952_acpi_match); +#endif + +static struct i2c_driver lp3952_i2c_driver = { + .driver = { + .name = LP3952_NAME, + .acpi_match_table = ACPI_PTR(lp3952_acpi_match), + }, + .probe = lp3952_probe, + .remove = lp3952_remove, + .id_table = lp3952_id, +}; + +module_i2c_driver(lp3952_i2c_driver); + +MODULE_AUTHOR("Tony Makkiel <tony.makkiel@daqri.com>"); +MODULE_DESCRIPTION("lp3952 I2C LED controller driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index e3d3b1aaa..09a7cffbc 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -21,6 +21,8 @@ #include <linux/workqueue.h> #include <linux/leds-pca9532.h> #include <linux/gpio.h> +#include <linux/of.h> +#include <linux/of_device.h> /* m = num_leds*/ #define PCA9532_REG_INPUT(i) ((i) >> 3) @@ -86,9 +88,22 @@ static const struct pca9532_chip_info pca9532_chip_info_tbl[] = { }, }; +#ifdef CONFIG_OF +static const struct of_device_id of_pca9532_leds_match[] = { + { .compatible = "nxp,pca9530", .data = (void *)pca9530 }, + { .compatible = "nxp,pca9531", .data = (void *)pca9531 }, + { .compatible = "nxp,pca9532", .data = (void *)pca9532 }, + { .compatible = "nxp,pca9533", .data = (void *)pca9533 }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_pca9532_leds_match); +#endif + static struct i2c_driver pca9532_driver = { .driver = { .name = "leds-pca953x", + .of_match_table = of_match_ptr(of_pca9532_leds_match), }, .probe = pca9532_probe, .remove = pca9532_remove, @@ -354,6 +369,7 @@ static int pca9532_configure(struct i2c_client *client, led->state = pled->state; led->name = pled->name; led->ldev.name = led->name; + led->ldev.default_trigger = led->default_trigger; led->ldev.brightness = LED_OFF; led->ldev.brightness_set_blocking = pca9532_set_brightness; @@ -432,15 +448,66 @@ exit: return err; } +static struct pca9532_platform_data * +pca9532_of_populate_pdata(struct device *dev, struct device_node *np) +{ + struct pca9532_platform_data *pdata; + struct device_node *child; + const struct of_device_id *match; + int devid, maxleds; + int i = 0; + + match = of_match_device(of_pca9532_leds_match, dev); + if (!match) + return ERR_PTR(-ENODEV); + + devid = (int)(uintptr_t)match->data; + maxleds = pca9532_chip_info_tbl[devid].num_leds; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + for_each_child_of_node(np, child) { + if (of_property_read_string(child, "label", + &pdata->leds[i].name)) + pdata->leds[i].name = child->name; + of_property_read_u32(child, "type", &pdata->leds[i].type); + of_property_read_string(child, "linux,default-trigger", + &pdata->leds[i].default_trigger); + if (++i >= maxleds) { + of_node_put(child); + break; + } + } + + return pdata; +} + static int pca9532_probe(struct i2c_client *client, const struct i2c_device_id *id) { + int devid; struct pca9532_data *data = i2c_get_clientdata(client); struct pca9532_platform_data *pca9532_pdata = dev_get_platdata(&client->dev); - - if (!pca9532_pdata) - return -EIO; + struct device_node *np = client->dev.of_node; + + if (!pca9532_pdata) { + if (np) { + pca9532_pdata = + pca9532_of_populate_pdata(&client->dev, np); + if (IS_ERR(pca9532_pdata)) + return PTR_ERR(pca9532_pdata); + } else { + dev_err(&client->dev, "no platform data\n"); + return -EINVAL; + } + devid = (int)(uintptr_t)of_match_device( + of_pca9532_leds_match, &client->dev)->data; + } else { + devid = id->driver_data; + } if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -450,7 +517,7 @@ static int pca9532_probe(struct i2c_client *client, if (!data) return -ENOMEM; - data->chip_info = &pca9532_chip_info_tbl[id->driver_data]; + data->chip_info = &pca9532_chip_info_tbl[devid]; dev_info(&client->dev, "setting platform data\n"); i2c_set_clientdata(client, data); diff --git a/drivers/leds/leds-powernv.c b/drivers/leds/leds-powernv.c index dfb8bd390..b2a98c7b5 100644 --- a/drivers/leds/leds-powernv.c +++ b/drivers/leds/leds-powernv.c @@ -118,7 +118,7 @@ static int powernv_led_set(struct powernv_led_data *powernv_led, goto out_token; } - rc = be64_to_cpu(msg.params[1]); + rc = opal_get_async_rc(msg); if (rc != OPAL_SUCCESS) dev_err(dev, "%s : OAPL async call returned failed [rc=%d]\n", __func__, rc); diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 9893d9113..3f9ddb9fa 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -33,12 +33,12 @@ config LEDS_TRIGGER_ONESHOT If unsure, say Y. -config LEDS_TRIGGER_IDE_DISK - bool "LED IDE Disk Trigger" - depends on IDE_GD_ATA +config LEDS_TRIGGER_DISK + bool "LED Disk Trigger" + depends on IDE_GD_ATA || ATA depends on LEDS_TRIGGERS help - This allows LEDs to be controlled by IDE disk activity. + This allows LEDs to be controlled by disk activity. If unsure, say Y. config LEDS_TRIGGER_MTD diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 8cc64a4f4..a72c43cff 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o -obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o +obj-$(CONFIG_LEDS_TRIGGER_DISK) += ledtrig-disk.o obj-$(CONFIG_LEDS_TRIGGER_MTD) += ledtrig-mtd.o obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c index 938467fb8..22f0634dd 100644 --- a/drivers/leds/trigger/ledtrig-cpu.c +++ b/drivers/leds/trigger/ledtrig-cpu.c @@ -92,29 +92,22 @@ static struct syscore_ops ledtrig_cpu_syscore_ops = { .resume = ledtrig_cpu_syscore_resume, }; -static int ledtrig_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int ledtrig_online_cpu(unsigned int cpu) { - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: - ledtrig_cpu(CPU_LED_START); - break; - case CPU_DYING: - ledtrig_cpu(CPU_LED_STOP); - break; - } - - return NOTIFY_OK; + ledtrig_cpu(CPU_LED_START); + return 0; } - -static struct notifier_block ledtrig_cpu_nb = { - .notifier_call = ledtrig_cpu_notify, -}; +static int ledtrig_prepare_down_cpu(unsigned int cpu) +{ + ledtrig_cpu(CPU_LED_STOP); + return 0; +} static int __init ledtrig_cpu_init(void) { int cpu; + int ret; /* Supports up to 9999 cpu cores */ BUILD_BUG_ON(CONFIG_NR_CPUS > 9999); @@ -133,7 +126,12 @@ static int __init ledtrig_cpu_init(void) } register_syscore_ops(&ledtrig_cpu_syscore_ops); - register_cpu_notifier(&ledtrig_cpu_nb); + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "AP_LEDTRIG_STARTING", + ledtrig_online_cpu, ledtrig_prepare_down_cpu); + if (ret < 0) + pr_err("CPU hotplug notifier for ledtrig-cpu could not be registered: %d\n", + ret); pr_info("ledtrig-cpu: registered to indicate activity on CPUs\n"); diff --git a/drivers/leds/trigger/ledtrig-disk.c b/drivers/leds/trigger/ledtrig-disk.c new file mode 100644 index 000000000..cd525b412 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-disk.c @@ -0,0 +1,41 @@ +/* + * LED Disk Activity Trigger + * + * Copyright 2006 Openedhand Ltd. + * + * Author: Richard Purdie <rpurdie@openedhand.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/leds.h> + +#define BLINK_DELAY 30 + +DEFINE_LED_TRIGGER(ledtrig_disk); +DEFINE_LED_TRIGGER(ledtrig_ide); + +void ledtrig_disk_activity(void) +{ + unsigned long blink_delay = BLINK_DELAY; + + led_trigger_blink_oneshot(ledtrig_disk, + &blink_delay, &blink_delay, 0); + led_trigger_blink_oneshot(ledtrig_ide, + &blink_delay, &blink_delay, 0); +} +EXPORT_SYMBOL(ledtrig_disk_activity); + +static int __init ledtrig_disk_init(void) +{ + led_trigger_register_simple("disk-activity", &ledtrig_disk); + led_trigger_register_simple("ide-disk", &ledtrig_ide); + + return 0; +} +device_initcall(ledtrig_disk_init); |