Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds

* 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds:
leds: Convert from struct class_device to struct device
leds: leds-gpio for ngw100
leds: Add warning printks in error paths
leds: Fix trigger unregister_simple if register_simple fails
leds: Use menuconfig objects II - LED
leds: Teach leds-gpio to handle timer-unsafe GPIOs
leds: Add generic GPIO LED driver

+343 -78
+31
arch/avr32/boards/atngw100/setup.c
··· 13 #include <linux/linkage.h> 14 #include <linux/platform_device.h> 15 #include <linux/types.h> 16 #include <linux/spi/spi.h> 17 18 #include <asm/io.h> ··· 22 #include <asm/arch/at32ap7000.h> 23 #include <asm/arch/board.h> 24 #include <asm/arch/init.h> 25 26 /* Initialized by bootloader-specific startup code. */ 27 struct tag *bootloader_tags __initdata; ··· 102 at32_setup_serial_console(0); 103 } 104 105 static int __init atngw100_init(void) 106 { 107 /* 108 * ATNGW100 uses 16-bit SDRAM interface, so we don't need to 109 * reserve any pins for it. ··· 140 set_hw_addr(at32_add_device_eth(1, &eth_data[1])); 141 142 at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); 143 144 return 0; 145 }
··· 13 #include <linux/linkage.h> 14 #include <linux/platform_device.h> 15 #include <linux/types.h> 16 + #include <linux/leds.h> 17 #include <linux/spi/spi.h> 18 19 #include <asm/io.h> ··· 21 #include <asm/arch/at32ap7000.h> 22 #include <asm/arch/board.h> 23 #include <asm/arch/init.h> 24 + #include <asm/arch/portmux.h> 25 26 /* Initialized by bootloader-specific startup code. */ 27 struct tag *bootloader_tags __initdata; ··· 100 at32_setup_serial_console(0); 101 } 102 103 + static const struct gpio_led ngw_leds[] = { 104 + { .name = "sys", .gpio = GPIO_PIN_PA(16), .active_low = 1, 105 + .default_trigger = "heartbeat", 106 + }, 107 + { .name = "a", .gpio = GPIO_PIN_PA(19), .active_low = 1, }, 108 + { .name = "b", .gpio = GPIO_PIN_PE(19), .active_low = 1, }, 109 + }; 110 + 111 + static const struct gpio_led_platform_data ngw_led_data = { 112 + .num_leds = ARRAY_SIZE(ngw_leds), 113 + .leds = (void *) ngw_leds, 114 + }; 115 + 116 + static struct platform_device ngw_gpio_leds = { 117 + .name = "leds-gpio", 118 + .id = -1, 119 + .dev = { 120 + .platform_data = (void *) &ngw_led_data, 121 + } 122 + }; 123 + 124 static int __init atngw100_init(void) 125 { 126 + unsigned i; 127 + 128 /* 129 * ATNGW100 uses 16-bit SDRAM interface, so we don't need to 130 * reserve any pins for it. ··· 115 set_hw_addr(at32_add_device_eth(1, &eth_data[1])); 116 117 at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); 118 + 119 + for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) { 120 + at32_select_gpio(ngw_leds[i].gpio, 121 + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); 122 + } 123 + platform_device_register(&ngw_gpio_leds); 124 125 return 0; 126 }
+15 -1
arch/avr32/configs/atngw100_defconfig
··· 712 # 713 # LED devices 714 # 715 - # CONFIG_NEW_LEDS is not set 716 717 # 718 # LED drivers
··· 712 # 713 # LED devices 714 # 715 + CONFIG_NEW_LEDS=y 716 + CONFIG_LEDS_CLASS=y 717 + 718 + # 719 + # LED drivers 720 + # 721 + CONFIG_LEDS_GPIO=y 722 + 723 + # 724 + # LED Triggers 725 + # 726 + CONFIG_LEDS_TRIGGERS=y 727 + CONFIG_LEDS_TRIGGER_TIMER=y 728 + CONFIG_LEDS_TRIGGER_HEARTBEAT=y 729 + 730 731 # 732 # LED drivers
+13 -9
drivers/leds/Kconfig
··· 1 - 2 - menu "LED devices" 3 - depends on HAS_IOMEM 4 - 5 - config NEW_LEDS 6 bool "LED Support" 7 help 8 Say Y to enable Linux LED support. This allows control of supported 9 LEDs from both userspace and optionally, by kernel events (triggers). ··· 8 This is not related to standard keyboard LEDs which are controlled 9 via the input system. 10 11 config LEDS_CLASS 12 tristate "LED Class Support" 13 - depends on NEW_LEDS 14 help 15 This option enables the led sysfs class in /sys/class/leds. You'll 16 need this to do anything useful with LEDs. If unsure, say N. ··· 93 help 94 This option enables support for the front LED on Cobalt Server 95 96 comment "LED Triggers" 97 98 config LEDS_TRIGGERS 99 bool "LED Trigger support" 100 - depends on NEW_LEDS 101 help 102 This option enables trigger support for the leds class. 103 These triggers allow kernel events to drive the LEDs and can ··· 133 load average. 134 If unsure, say Y. 135 136 - endmenu 137 -
··· 1 + menuconfig NEW_LEDS 2 bool "LED Support" 3 + depends on HAS_IOMEM 4 help 5 Say Y to enable Linux LED support. This allows control of supported 6 LEDs from both userspace and optionally, by kernel events (triggers). ··· 11 This is not related to standard keyboard LEDs which are controlled 12 via the input system. 13 14 + if NEW_LEDS 15 + 16 config LEDS_CLASS 17 tristate "LED Class Support" 18 help 19 This option enables the led sysfs class in /sys/class/leds. You'll 20 need this to do anything useful with LEDs. If unsure, say N. ··· 95 help 96 This option enables support for the front LED on Cobalt Server 97 98 + config LEDS_GPIO 99 + tristate "LED Support for GPIO connected LEDs" 100 + depends on LEDS_CLASS && GENERIC_GPIO 101 + help 102 + This option enables support for the LEDs connected to GPIO 103 + outputs. To be useful the particular board must have LEDs 104 + and they must be connected to the GPIO lines. 105 + 106 comment "LED Triggers" 107 108 config LEDS_TRIGGERS 109 bool "LED Trigger support" 110 help 111 This option enables trigger support for the leds class. 112 These triggers allow kernel events to drive the LEDs and can ··· 128 load average. 129 If unsure, say Y. 130 131 + endif # NEW_LEDS
+1
drivers/leds/Makefile
··· 16 obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o 17 obj-$(CONFIG_LEDS_H1940) += leds-h1940.o 18 obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o 19 20 # LED Triggers 21 obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
··· 16 obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o 17 obj-$(CONFIG_LEDS_H1940) += leds-h1940.o 18 obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o 19 + obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o 20 21 # LED Triggers 22 obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
+22 -27
drivers/leds/led-class.c
··· 2 * LED Class Core 3 * 4 * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> 5 - * Copyright (C) 2005-2006 Richard Purdie <rpurdie@openedhand.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as ··· 24 25 static struct class *leds_class; 26 27 - static ssize_t led_brightness_show(struct class_device *dev, char *buf) 28 { 29 - struct led_classdev *led_cdev = class_get_devdata(dev); 30 ssize_t ret = 0; 31 32 /* no lock needed for this */ ··· 37 return ret; 38 } 39 40 - static ssize_t led_brightness_store(struct class_device *dev, 41 - const char *buf, size_t size) 42 { 43 - struct led_classdev *led_cdev = class_get_devdata(dev); 44 ssize_t ret = -EINVAL; 45 char *after; 46 unsigned long state = simple_strtoul(buf, &after, 10); ··· 57 return ret; 58 } 59 60 - static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show, 61 - led_brightness_store); 62 #ifdef CONFIG_LEDS_TRIGGERS 63 - static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); 64 #endif 65 66 /** ··· 93 { 94 int rc; 95 96 - led_cdev->class_dev = class_device_create(leds_class, NULL, 0, 97 - parent, "%s", led_cdev->name); 98 - if (unlikely(IS_ERR(led_cdev->class_dev))) 99 - return PTR_ERR(led_cdev->class_dev); 100 101 - class_set_devdata(led_cdev->class_dev, led_cdev); 102 103 /* register the attributes */ 104 - rc = class_device_create_file(led_cdev->class_dev, 105 - &class_device_attr_brightness); 106 if (rc) 107 goto err_out; 108 ··· 113 #ifdef CONFIG_LEDS_TRIGGERS 114 rwlock_init(&led_cdev->trigger_lock); 115 116 - rc = class_device_create_file(led_cdev->class_dev, 117 - &class_device_attr_trigger); 118 if (rc) 119 goto err_out_led_list; 120 ··· 121 #endif 122 123 printk(KERN_INFO "Registered led device: %s\n", 124 - led_cdev->class_dev->class_id); 125 126 return 0; 127 128 #ifdef CONFIG_LEDS_TRIGGERS 129 err_out_led_list: 130 - class_device_remove_file(led_cdev->class_dev, 131 - &class_device_attr_brightness); 132 list_del(&led_cdev->node); 133 #endif 134 err_out: 135 - class_device_unregister(led_cdev->class_dev); 136 return rc; 137 } 138 EXPORT_SYMBOL_GPL(led_classdev_register); ··· 144 */ 145 void led_classdev_unregister(struct led_classdev *led_cdev) 146 { 147 - class_device_remove_file(led_cdev->class_dev, 148 - &class_device_attr_brightness); 149 #ifdef CONFIG_LEDS_TRIGGERS 150 - class_device_remove_file(led_cdev->class_dev, 151 - &class_device_attr_trigger); 152 write_lock(&led_cdev->trigger_lock); 153 if (led_cdev->trigger) 154 led_trigger_set(led_cdev, NULL); 155 write_unlock(&led_cdev->trigger_lock); 156 #endif 157 158 - class_device_unregister(led_cdev->class_dev); 159 160 write_lock(&leds_list_lock); 161 list_del(&led_cdev->node);
··· 2 * LED Class Core 3 * 4 * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> 5 + * Copyright (C) 2005-2007 Richard Purdie <rpurdie@openedhand.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as ··· 24 25 static struct class *leds_class; 26 27 + static ssize_t led_brightness_show(struct device *dev, 28 + struct device_attribute *attr, char *buf) 29 { 30 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 31 ssize_t ret = 0; 32 33 /* no lock needed for this */ ··· 36 return ret; 37 } 38 39 + static ssize_t led_brightness_store(struct device *dev, 40 + struct device_attribute *attr, const char *buf, size_t size) 41 { 42 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 43 ssize_t ret = -EINVAL; 44 char *after; 45 unsigned long state = simple_strtoul(buf, &after, 10); ··· 56 return ret; 57 } 58 59 + static DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store); 60 #ifdef CONFIG_LEDS_TRIGGERS 61 + static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); 62 #endif 63 64 /** ··· 93 { 94 int rc; 95 96 + led_cdev->dev = device_create(leds_class, parent, 0, "%s", 97 + led_cdev->name); 98 + if (unlikely(IS_ERR(led_cdev->dev))) 99 + return PTR_ERR(led_cdev->dev); 100 101 + dev_set_drvdata(led_cdev->dev, led_cdev); 102 103 /* register the attributes */ 104 + rc = device_create_file(led_cdev->dev, &dev_attr_brightness); 105 if (rc) 106 goto err_out; 107 ··· 114 #ifdef CONFIG_LEDS_TRIGGERS 115 rwlock_init(&led_cdev->trigger_lock); 116 117 + rc = device_create_file(led_cdev->dev, &dev_attr_trigger); 118 if (rc) 119 goto err_out_led_list; 120 ··· 123 #endif 124 125 printk(KERN_INFO "Registered led device: %s\n", 126 + led_cdev->name); 127 128 return 0; 129 130 #ifdef CONFIG_LEDS_TRIGGERS 131 err_out_led_list: 132 + device_remove_file(led_cdev->dev, &dev_attr_brightness); 133 list_del(&led_cdev->node); 134 #endif 135 err_out: 136 + device_unregister(led_cdev->dev); 137 return rc; 138 } 139 EXPORT_SYMBOL_GPL(led_classdev_register); ··· 147 */ 148 void led_classdev_unregister(struct led_classdev *led_cdev) 149 { 150 + device_remove_file(led_cdev->dev, &dev_attr_brightness); 151 #ifdef CONFIG_LEDS_TRIGGERS 152 + device_remove_file(led_cdev->dev, &dev_attr_trigger); 153 write_lock(&led_cdev->trigger_lock); 154 if (led_cdev->trigger) 155 led_trigger_set(led_cdev, NULL); 156 write_unlock(&led_cdev->trigger_lock); 157 #endif 158 159 + device_unregister(led_cdev->dev); 160 161 write_lock(&leds_list_lock); 162 list_del(&led_cdev->node);
+18 -9
drivers/leds/led-triggers.c
··· 1 /* 2 * LED Triggers Core 3 * 4 - * Copyright 2005-2006 Openedhand Ltd. 5 * 6 * Author: Richard Purdie <rpurdie@openedhand.com> 7 * ··· 28 static DEFINE_RWLOCK(triggers_list_lock); 29 static LIST_HEAD(trigger_list); 30 31 - ssize_t led_trigger_store(struct class_device *dev, const char *buf, 32 - size_t count) 33 { 34 - struct led_classdev *led_cdev = class_get_devdata(dev); 35 char trigger_name[TRIG_NAME_MAX]; 36 struct led_trigger *trig; 37 size_t len; ··· 67 } 68 69 70 - ssize_t led_trigger_show(struct class_device *dev, char *buf) 71 { 72 - struct led_classdev *led_cdev = class_get_devdata(dev); 73 struct led_trigger *trig; 74 int len = 0; 75 ··· 184 void led_trigger_register_simple(const char *name, struct led_trigger **tp) 185 { 186 struct led_trigger *trigger; 187 188 trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 189 190 if (trigger) { 191 trigger->name = name; 192 - led_trigger_register(trigger); 193 - } 194 *tp = trigger; 195 } 196 ··· 223 224 void led_trigger_unregister_simple(struct led_trigger *trigger) 225 { 226 - led_trigger_unregister(trigger); 227 kfree(trigger); 228 } 229
··· 1 /* 2 * LED Triggers Core 3 * 4 + * Copyright 2005-2007 Openedhand Ltd. 5 * 6 * Author: Richard Purdie <rpurdie@openedhand.com> 7 * ··· 28 static DEFINE_RWLOCK(triggers_list_lock); 29 static LIST_HEAD(trigger_list); 30 31 + ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, 32 + const char *buf, size_t count) 33 { 34 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 35 char trigger_name[TRIG_NAME_MAX]; 36 struct led_trigger *trig; 37 size_t len; ··· 67 } 68 69 70 + ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, 71 + char *buf) 72 { 73 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 74 struct led_trigger *trig; 75 int len = 0; 76 ··· 183 void led_trigger_register_simple(const char *name, struct led_trigger **tp) 184 { 185 struct led_trigger *trigger; 186 + int err; 187 188 trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 189 190 if (trigger) { 191 trigger->name = name; 192 + err = led_trigger_register(trigger); 193 + if (err < 0) 194 + printk(KERN_WARNING "LED trigger %s failed to register" 195 + " (%d)\n", name, err); 196 + } else 197 + printk(KERN_WARNING "LED trigger %s failed to register" 198 + " (no memory)\n", name); 199 + 200 *tp = trigger; 201 } 202 ··· 215 216 void led_trigger_unregister_simple(struct led_trigger *trigger) 217 { 218 + if (trigger) 219 + led_trigger_unregister(trigger); 220 kfree(trigger); 221 } 222
+199
drivers/leds/leds-gpio.c
···
··· 1 + /* 2 + * LEDs driver for GPIOs 3 + * 4 + * Copyright (C) 2007 8D Technologies inc. 5 + * Raphael Assenat <raph@8d.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + * 11 + */ 12 + #include <linux/kernel.h> 13 + #include <linux/init.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/leds.h> 16 + #include <linux/workqueue.h> 17 + 18 + #include <asm/gpio.h> 19 + 20 + struct gpio_led_data { 21 + struct led_classdev cdev; 22 + unsigned gpio; 23 + struct work_struct work; 24 + u8 new_level; 25 + u8 can_sleep; 26 + u8 active_low; 27 + }; 28 + 29 + static void gpio_led_work(struct work_struct *work) 30 + { 31 + struct gpio_led_data *led_dat = 32 + container_of(work, struct gpio_led_data, work); 33 + 34 + gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); 35 + } 36 + 37 + static void gpio_led_set(struct led_classdev *led_cdev, 38 + enum led_brightness value) 39 + { 40 + struct gpio_led_data *led_dat = 41 + container_of(led_cdev, struct gpio_led_data, cdev); 42 + int level; 43 + 44 + if (value == LED_OFF) 45 + level = 0; 46 + else 47 + level = 1; 48 + 49 + if (led_dat->active_low) 50 + level = !level; 51 + 52 + /* setting GPIOs with I2C/etc requires a preemptible task context */ 53 + if (led_dat->can_sleep) { 54 + if (preempt_count()) { 55 + led_dat->new_level = level; 56 + schedule_work(&led_dat->work); 57 + } else 58 + gpio_set_value_cansleep(led_dat->gpio, level); 59 + } else 60 + gpio_set_value(led_dat->gpio, level); 61 + } 62 + 63 + static int __init gpio_led_probe(struct platform_device *pdev) 64 + { 65 + struct gpio_led_platform_data *pdata = pdev->dev.platform_data; 66 + struct gpio_led *cur_led; 67 + struct gpio_led_data *leds_data, *led_dat; 68 + int i, ret = 0; 69 + 70 + if (!pdata) 71 + return -EBUSY; 72 + 73 + leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds, 74 + GFP_KERNEL); 75 + if (!leds_data) 76 + return -ENOMEM; 77 + 78 + for (i = 0; i < pdata->num_leds; i++) { 79 + cur_led = &pdata->leds[i]; 80 + led_dat = &leds_data[i]; 81 + 82 + led_dat->cdev.name = cur_led->name; 83 + led_dat->cdev.default_trigger = cur_led->default_trigger; 84 + led_dat->gpio = cur_led->gpio; 85 + led_dat->can_sleep = gpio_cansleep(cur_led->gpio); 86 + led_dat->active_low = cur_led->active_low; 87 + led_dat->cdev.brightness_set = gpio_led_set; 88 + led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF; 89 + 90 + ret = gpio_request(led_dat->gpio, led_dat->cdev.name); 91 + if (ret < 0) 92 + goto err; 93 + 94 + gpio_direction_output(led_dat->gpio, led_dat->active_low); 95 + 96 + ret = led_classdev_register(&pdev->dev, &led_dat->cdev); 97 + if (ret < 0) { 98 + gpio_free(led_dat->gpio); 99 + goto err; 100 + } 101 + 102 + INIT_WORK(&led_dat->work, gpio_led_work); 103 + } 104 + 105 + platform_set_drvdata(pdev, leds_data); 106 + 107 + return 0; 108 + 109 + err: 110 + if (i > 0) { 111 + for (i = i - 1; i >= 0; i--) { 112 + led_classdev_unregister(&leds_data[i].cdev); 113 + gpio_free(leds_data[i].gpio); 114 + } 115 + } 116 + 117 + flush_scheduled_work(); 118 + kfree(leds_data); 119 + 120 + return ret; 121 + } 122 + 123 + static int __exit gpio_led_remove(struct platform_device *pdev) 124 + { 125 + int i; 126 + struct gpio_led_platform_data *pdata = pdev->dev.platform_data; 127 + struct gpio_led_data *leds_data; 128 + 129 + leds_data = platform_get_drvdata(pdev); 130 + 131 + for (i = 0; i < pdata->num_leds; i++) { 132 + led_classdev_unregister(&leds_data[i].cdev); 133 + gpio_free(leds_data[i].gpio); 134 + } 135 + 136 + kfree(leds_data); 137 + 138 + return 0; 139 + } 140 + 141 + #ifdef CONFIG_PM 142 + static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state) 143 + { 144 + struct gpio_led_platform_data *pdata = pdev->dev.platform_data; 145 + struct gpio_led_data *leds_data; 146 + int i; 147 + 148 + leds_data = platform_get_drvdata(pdev); 149 + 150 + for (i = 0; i < pdata->num_leds; i++) 151 + led_classdev_suspend(&leds_data[i].cdev); 152 + 153 + return 0; 154 + } 155 + 156 + static int gpio_led_resume(struct platform_device *pdev) 157 + { 158 + struct gpio_led_platform_data *pdata = pdev->dev.platform_data; 159 + struct gpio_led_data *leds_data; 160 + int i; 161 + 162 + leds_data = platform_get_drvdata(pdev); 163 + 164 + for (i = 0; i < pdata->num_leds; i++) 165 + led_classdev_resume(&leds_data[i].cdev); 166 + 167 + return 0; 168 + } 169 + #else 170 + #define gpio_led_suspend NULL 171 + #define gpio_led_resume NULL 172 + #endif 173 + 174 + static struct platform_driver gpio_led_driver = { 175 + .remove = __exit_p(gpio_led_remove), 176 + .suspend = gpio_led_suspend, 177 + .resume = gpio_led_resume, 178 + .driver = { 179 + .name = "leds-gpio", 180 + .owner = THIS_MODULE, 181 + }, 182 + }; 183 + 184 + static int __init gpio_led_init(void) 185 + { 186 + return platform_driver_probe(&gpio_led_driver, gpio_led_probe); 187 + } 188 + 189 + static void __exit gpio_led_exit(void) 190 + { 191 + platform_driver_unregister(&gpio_led_driver); 192 + } 193 + 194 + module_init(gpio_led_init); 195 + module_exit(gpio_led_exit); 196 + 197 + MODULE_AUTHOR("Raphael Assenat <raph@8d.com>"); 198 + MODULE_DESCRIPTION("GPIO LED driver"); 199 + MODULE_LICENSE("GPL");
+1 -1
drivers/leds/leds-locomo.c
··· 19 static void locomoled_brightness_set(struct led_classdev *led_cdev, 20 enum led_brightness value, int offset) 21 { 22 - struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev); 23 unsigned long flags; 24 25 local_irq_save(flags);
··· 19 static void locomoled_brightness_set(struct led_classdev *led_cdev, 20 enum led_brightness value, int offset) 21 { 22 + struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->dev); 23 unsigned long flags; 24 25 local_irq_save(flags);
+5 -3
drivers/leds/leds.h
··· 13 #ifndef __LEDS_H_INCLUDED 14 #define __LEDS_H_INCLUDED 15 16 #include <linux/leds.h> 17 18 static inline void led_set_brightness(struct led_classdev *led_cdev, ··· 38 #define led_trigger_set(x, y) do {} while(0) 39 #endif 40 41 - ssize_t led_trigger_store(struct class_device *dev, const char *buf, 42 - size_t count); 43 - ssize_t led_trigger_show(struct class_device *dev, char *buf); 44 45 #endif /* __LEDS_H_INCLUDED */
··· 13 #ifndef __LEDS_H_INCLUDED 14 #define __LEDS_H_INCLUDED 15 16 + #include <linux/device.h> 17 #include <linux/leds.h> 18 19 static inline void led_set_brightness(struct led_classdev *led_cdev, ··· 37 #define led_trigger_set(x, y) do {} while(0) 38 #endif 39 40 + ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, 41 + const char *buf, size_t count); 42 + ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, 43 + char *buf); 44 45 #endif /* __LEDS_H_INCLUDED */
+23 -26
drivers/leds/ledtrig-timer.c
··· 52 mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); 53 } 54 55 - static ssize_t led_delay_on_show(struct class_device *dev, char *buf) 56 { 57 - struct led_classdev *led_cdev = class_get_devdata(dev); 58 struct timer_trig_data *timer_data = led_cdev->trigger_data; 59 60 sprintf(buf, "%lu\n", timer_data->delay_on); ··· 63 return strlen(buf) + 1; 64 } 65 66 - static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, 67 - size_t size) 68 { 69 - struct led_classdev *led_cdev = class_get_devdata(dev); 70 struct timer_trig_data *timer_data = led_cdev->trigger_data; 71 int ret = -EINVAL; 72 char *after; ··· 85 return ret; 86 } 87 88 - static ssize_t led_delay_off_show(struct class_device *dev, char *buf) 89 { 90 - struct led_classdev *led_cdev = class_get_devdata(dev); 91 struct timer_trig_data *timer_data = led_cdev->trigger_data; 92 93 sprintf(buf, "%lu\n", timer_data->delay_off); ··· 96 return strlen(buf) + 1; 97 } 98 99 - static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, 100 - size_t size) 101 { 102 - struct led_classdev *led_cdev = class_get_devdata(dev); 103 struct timer_trig_data *timer_data = led_cdev->trigger_data; 104 int ret = -EINVAL; 105 char *after; ··· 118 return ret; 119 } 120 121 - static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show, 122 - led_delay_on_store); 123 - static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show, 124 - led_delay_off_store); 125 126 static void timer_trig_activate(struct led_classdev *led_cdev) 127 { ··· 136 timer_data->timer.function = led_timer_function; 137 timer_data->timer.data = (unsigned long) led_cdev; 138 139 - rc = class_device_create_file(led_cdev->class_dev, 140 - &class_device_attr_delay_on); 141 - if (rc) goto err_out; 142 - rc = class_device_create_file(led_cdev->class_dev, 143 - &class_device_attr_delay_off); 144 - if (rc) goto err_out_delayon; 145 146 return; 147 148 err_out_delayon: 149 - class_device_remove_file(led_cdev->class_dev, 150 - &class_device_attr_delay_on); 151 err_out: 152 led_cdev->trigger_data = NULL; 153 kfree(timer_data); ··· 157 struct timer_trig_data *timer_data = led_cdev->trigger_data; 158 159 if (timer_data) { 160 - class_device_remove_file(led_cdev->class_dev, 161 - &class_device_attr_delay_on); 162 - class_device_remove_file(led_cdev->class_dev, 163 - &class_device_attr_delay_off); 164 del_timer_sync(&timer_data->timer); 165 kfree(timer_data); 166 }
··· 52 mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); 53 } 54 55 + static ssize_t led_delay_on_show(struct device *dev, 56 + struct device_attribute *attr, char *buf) 57 { 58 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 59 struct timer_trig_data *timer_data = led_cdev->trigger_data; 60 61 sprintf(buf, "%lu\n", timer_data->delay_on); ··· 62 return strlen(buf) + 1; 63 } 64 65 + static ssize_t led_delay_on_store(struct device *dev, 66 + struct device_attribute *attr, const char *buf, size_t size) 67 { 68 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 69 struct timer_trig_data *timer_data = led_cdev->trigger_data; 70 int ret = -EINVAL; 71 char *after; ··· 84 return ret; 85 } 86 87 + static ssize_t led_delay_off_show(struct device *dev, 88 + struct device_attribute *attr, char *buf) 89 { 90 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 91 struct timer_trig_data *timer_data = led_cdev->trigger_data; 92 93 sprintf(buf, "%lu\n", timer_data->delay_off); ··· 94 return strlen(buf) + 1; 95 } 96 97 + static ssize_t led_delay_off_store(struct device *dev, 98 + struct device_attribute *attr, const char *buf, size_t size) 99 { 100 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 101 struct timer_trig_data *timer_data = led_cdev->trigger_data; 102 int ret = -EINVAL; 103 char *after; ··· 116 return ret; 117 } 118 119 + static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); 120 + static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); 121 122 static void timer_trig_activate(struct led_classdev *led_cdev) 123 { ··· 136 timer_data->timer.function = led_timer_function; 137 timer_data->timer.data = (unsigned long) led_cdev; 138 139 + rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); 140 + if (rc) 141 + goto err_out; 142 + rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); 143 + if (rc) 144 + goto err_out_delayon; 145 146 return; 147 148 err_out_delayon: 149 + device_remove_file(led_cdev->dev, &dev_attr_delay_on); 150 err_out: 151 led_cdev->trigger_data = NULL; 152 kfree(timer_data); ··· 158 struct timer_trig_data *timer_data = led_cdev->trigger_data; 159 160 if (timer_data) { 161 + device_remove_file(led_cdev->dev, &dev_attr_delay_on); 162 + device_remove_file(led_cdev->dev, &dev_attr_delay_off); 163 del_timer_sync(&timer_data->timer); 164 kfree(timer_data); 165 }
+15 -2
include/linux/leds.h
··· 15 #include <linux/list.h> 16 17 struct device; 18 - struct class_device; 19 /* 20 * LED Core 21 */ ··· 36 void (*brightness_set)(struct led_classdev *led_cdev, 37 enum led_brightness brightness); 38 39 - struct class_device *class_dev; 40 struct list_head node; /* LED Device list */ 41 char *default_trigger; /* Trigger to use */ 42 ··· 107 #else 108 #define ledtrig_ide_activity() do {} while(0) 109 #endif 110 111 #endif /* __LINUX_LEDS_H_INCLUDED */
··· 15 #include <linux/list.h> 16 17 struct device; 18 /* 19 * LED Core 20 */ ··· 37 void (*brightness_set)(struct led_classdev *led_cdev, 38 enum led_brightness brightness); 39 40 + struct device *dev; 41 struct list_head node; /* LED Device list */ 42 char *default_trigger; /* Trigger to use */ 43 ··· 108 #else 109 #define ledtrig_ide_activity() do {} while(0) 110 #endif 111 + 112 + /* For the leds-gpio driver */ 113 + struct gpio_led { 114 + const char *name; 115 + char *default_trigger; 116 + unsigned gpio; 117 + u8 active_low; 118 + }; 119 + 120 + struct gpio_led_platform_data { 121 + int num_leds; 122 + struct gpio_led *leds; 123 + }; 124 + 125 126 #endif /* __LINUX_LEDS_H_INCLUDED */