Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds
Browse files Browse the repository at this point in the history
* '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
  • Loading branch information
Linus Torvalds committed Jul 22, 2007
2 parents 2fe83b3 + f8a7c6f commit d7f5e3d
Show file tree
Hide file tree
Showing 11 changed files with 343 additions and 78 deletions.
31 changes: 31 additions & 0 deletions arch/avr32/boards/atngw100/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/linkage.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/leds.h>
#include <linux/spi/spi.h>

#include <asm/io.h>
Expand All @@ -21,6 +22,7 @@
#include <asm/arch/at32ap7000.h>
#include <asm/arch/board.h>
#include <asm/arch/init.h>
#include <asm/arch/portmux.h>

/* Initialized by bootloader-specific startup code. */
struct tag *bootloader_tags __initdata;
Expand Down Expand Up @@ -100,8 +102,31 @@ void __init setup_board(void)
at32_setup_serial_console(0);
}

static const struct gpio_led ngw_leds[] = {
{ .name = "sys", .gpio = GPIO_PIN_PA(16), .active_low = 1,
.default_trigger = "heartbeat",
},
{ .name = "a", .gpio = GPIO_PIN_PA(19), .active_low = 1, },
{ .name = "b", .gpio = GPIO_PIN_PE(19), .active_low = 1, },
};

static const struct gpio_led_platform_data ngw_led_data = {
.num_leds = ARRAY_SIZE(ngw_leds),
.leds = (void *) ngw_leds,
};

static struct platform_device ngw_gpio_leds = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = (void *) &ngw_led_data,
}
};

static int __init atngw100_init(void)
{
unsigned i;

/*
* ATNGW100 uses 16-bit SDRAM interface, so we don't need to
* reserve any pins for it.
Expand All @@ -116,6 +141,12 @@ static int __init atngw100_init(void)

at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));

for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) {
at32_select_gpio(ngw_leds[i].gpio,
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
}
platform_device_register(&ngw_gpio_leds);

return 0;
}
postcore_initcall(atngw100_init);
16 changes: 15 additions & 1 deletion arch/avr32/configs/atngw100_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,21 @@ CONFIG_SPI_ATMEL=y
#
# LED devices
#
# CONFIG_NEW_LEDS is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y

#
# LED drivers
#
CONFIG_LEDS_GPIO=y

#
# LED Triggers
#
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y


#
# LED drivers
Expand Down
22 changes: 13 additions & 9 deletions drivers/leds/Kconfig
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@

menu "LED devices"
depends on HAS_IOMEM

config NEW_LEDS
menuconfig NEW_LEDS
bool "LED Support"
depends on HAS_IOMEM
help
Say Y to enable Linux LED support. This allows control of supported
LEDs from both userspace and optionally, by kernel events (triggers).

This is not related to standard keyboard LEDs which are controlled
via the input system.

if NEW_LEDS

config LEDS_CLASS
tristate "LED Class Support"
depends on NEW_LEDS
help
This option enables the led sysfs class in /sys/class/leds. You'll
need this to do anything useful with LEDs. If unsure, say N.
Expand Down Expand Up @@ -95,11 +93,18 @@ config LEDS_COBALT
help
This option enables support for the front LED on Cobalt Server

config LEDS_GPIO
tristate "LED Support for GPIO connected LEDs"
depends on LEDS_CLASS && GENERIC_GPIO
help
This option enables support for the LEDs connected to GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines.

comment "LED Triggers"

config LEDS_TRIGGERS
bool "LED Trigger support"
depends on NEW_LEDS
help
This option enables trigger support for the leds class.
These triggers allow kernel events to drive the LEDs and can
Expand Down Expand Up @@ -128,5 +133,4 @@ config LEDS_TRIGGER_HEARTBEAT
load average.
If unsure, say Y.

endmenu

endif # NEW_LEDS
1 change: 1 addition & 0 deletions drivers/leds/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o

# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
Expand Down
49 changes: 22 additions & 27 deletions drivers/leds/led-class.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* LED Class Core
*
* Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu>
* Copyright (C) 2005-2006 Richard Purdie <rpurdie@openedhand.com>
* Copyright (C) 2005-2007 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
Expand All @@ -24,9 +24,10 @@

static struct class *leds_class;

static ssize_t led_brightness_show(struct class_device *dev, char *buf)
static ssize_t led_brightness_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
struct led_classdev *led_cdev = dev_get_drvdata(dev);
ssize_t ret = 0;

/* no lock needed for this */
Expand All @@ -36,10 +37,10 @@ static ssize_t led_brightness_show(struct class_device *dev, char *buf)
return ret;
}

static ssize_t led_brightness_store(struct class_device *dev,
const char *buf, size_t size)
static ssize_t led_brightness_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
struct led_classdev *led_cdev = dev_get_drvdata(dev);
ssize_t ret = -EINVAL;
char *after;
unsigned long state = simple_strtoul(buf, &after, 10);
Expand All @@ -56,10 +57,9 @@ static ssize_t led_brightness_store(struct class_device *dev,
return ret;
}

static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show,
led_brightness_store);
static DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store);
#ifdef CONFIG_LEDS_TRIGGERS
static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
#endif

/**
Expand Down Expand Up @@ -93,16 +93,15 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{
int rc;

led_cdev->class_dev = class_device_create(leds_class, NULL, 0,
parent, "%s", led_cdev->name);
if (unlikely(IS_ERR(led_cdev->class_dev)))
return PTR_ERR(led_cdev->class_dev);
led_cdev->dev = device_create(leds_class, parent, 0, "%s",
led_cdev->name);
if (unlikely(IS_ERR(led_cdev->dev)))
return PTR_ERR(led_cdev->dev);

class_set_devdata(led_cdev->class_dev, led_cdev);
dev_set_drvdata(led_cdev->dev, led_cdev);

/* register the attributes */
rc = class_device_create_file(led_cdev->class_dev,
&class_device_attr_brightness);
rc = device_create_file(led_cdev->dev, &dev_attr_brightness);
if (rc)
goto err_out;

Expand All @@ -114,27 +113,25 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
#ifdef CONFIG_LEDS_TRIGGERS
rwlock_init(&led_cdev->trigger_lock);

rc = class_device_create_file(led_cdev->class_dev,
&class_device_attr_trigger);
rc = device_create_file(led_cdev->dev, &dev_attr_trigger);
if (rc)
goto err_out_led_list;

led_trigger_set_default(led_cdev);
#endif

printk(KERN_INFO "Registered led device: %s\n",
led_cdev->class_dev->class_id);
led_cdev->name);

return 0;

#ifdef CONFIG_LEDS_TRIGGERS
err_out_led_list:
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_brightness);
device_remove_file(led_cdev->dev, &dev_attr_brightness);
list_del(&led_cdev->node);
#endif
err_out:
class_device_unregister(led_cdev->class_dev);
device_unregister(led_cdev->dev);
return rc;
}
EXPORT_SYMBOL_GPL(led_classdev_register);
Expand All @@ -147,18 +144,16 @@ EXPORT_SYMBOL_GPL(led_classdev_register);
*/
void led_classdev_unregister(struct led_classdev *led_cdev)
{
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_brightness);
device_remove_file(led_cdev->dev, &dev_attr_brightness);
#ifdef CONFIG_LEDS_TRIGGERS
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_trigger);
device_remove_file(led_cdev->dev, &dev_attr_trigger);
write_lock(&led_cdev->trigger_lock);
if (led_cdev->trigger)
led_trigger_set(led_cdev, NULL);
write_unlock(&led_cdev->trigger_lock);
#endif

class_device_unregister(led_cdev->class_dev);
device_unregister(led_cdev->dev);

write_lock(&leds_list_lock);
list_del(&led_cdev->node);
Expand Down
27 changes: 18 additions & 9 deletions drivers/leds/led-triggers.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* LED Triggers Core
*
* Copyright 2005-2006 Openedhand Ltd.
* Copyright 2005-2007 Openedhand Ltd.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
Expand All @@ -28,10 +28,10 @@
static DEFINE_RWLOCK(triggers_list_lock);
static LIST_HEAD(trigger_list);

ssize_t led_trigger_store(struct class_device *dev, const char *buf,
size_t count)
ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
struct led_classdev *led_cdev = dev_get_drvdata(dev);
char trigger_name[TRIG_NAME_MAX];
struct led_trigger *trig;
size_t len;
Expand Down Expand Up @@ -67,9 +67,10 @@ ssize_t led_trigger_store(struct class_device *dev, const char *buf,
}


ssize_t led_trigger_show(struct class_device *dev, char *buf)
ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct led_trigger *trig;
int len = 0;

Expand Down Expand Up @@ -183,13 +184,20 @@ int led_trigger_register(struct led_trigger *trigger)
void led_trigger_register_simple(const char *name, struct led_trigger **tp)
{
struct led_trigger *trigger;
int err;

trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);

if (trigger) {
trigger->name = name;
led_trigger_register(trigger);
}
err = led_trigger_register(trigger);
if (err < 0)
printk(KERN_WARNING "LED trigger %s failed to register"
" (%d)\n", name, err);
} else
printk(KERN_WARNING "LED trigger %s failed to register"
" (no memory)\n", name);

*tp = trigger;
}

Expand All @@ -215,7 +223,8 @@ void led_trigger_unregister(struct led_trigger *trigger)

void led_trigger_unregister_simple(struct led_trigger *trigger)
{
led_trigger_unregister(trigger);
if (trigger)
led_trigger_unregister(trigger);
kfree(trigger);
}

Expand Down
Loading

0 comments on commit d7f5e3d

Please sign in to comment.