Commit d7f5e3df authored by Linus Torvalds's avatar Linus Torvalds

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
parents 2fe83b3a f8a7c6fe
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/leds.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
#include <asm/arch/at32ap7000.h> #include <asm/arch/at32ap7000.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/init.h> #include <asm/arch/init.h>
#include <asm/arch/portmux.h>
/* Initialized by bootloader-specific startup code. */ /* Initialized by bootloader-specific startup code. */
struct tag *bootloader_tags __initdata; struct tag *bootloader_tags __initdata;
...@@ -100,8 +102,31 @@ void __init setup_board(void) ...@@ -100,8 +102,31 @@ void __init setup_board(void)
at32_setup_serial_console(0); 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) static int __init atngw100_init(void)
{ {
unsigned i;
/* /*
* ATNGW100 uses 16-bit SDRAM interface, so we don't need to * ATNGW100 uses 16-bit SDRAM interface, so we don't need to
* reserve any pins for it. * reserve any pins for it.
...@@ -116,6 +141,12 @@ static int __init atngw100_init(void) ...@@ -116,6 +141,12 @@ static int __init atngw100_init(void)
at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); 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; return 0;
} }
postcore_initcall(atngw100_init); postcore_initcall(atngw100_init);
...@@ -712,7 +712,21 @@ CONFIG_SPI_ATMEL=y ...@@ -712,7 +712,21 @@ CONFIG_SPI_ATMEL=y
# #
# LED devices # 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 # LED drivers
......
menuconfig NEW_LEDS
menu "LED devices"
depends on HAS_IOMEM
config NEW_LEDS
bool "LED Support" bool "LED Support"
depends on HAS_IOMEM
help help
Say Y to enable Linux LED support. This allows control of supported Say Y to enable Linux LED support. This allows control of supported
LEDs from both userspace and optionally, by kernel events (triggers). LEDs from both userspace and optionally, by kernel events (triggers).
...@@ -11,9 +8,10 @@ config NEW_LEDS ...@@ -11,9 +8,10 @@ config NEW_LEDS
This is not related to standard keyboard LEDs which are controlled This is not related to standard keyboard LEDs which are controlled
via the input system. via the input system.
if NEW_LEDS
config LEDS_CLASS config LEDS_CLASS
tristate "LED Class Support" tristate "LED Class Support"
depends on NEW_LEDS
help help
This option enables the led sysfs class in /sys/class/leds. You'll 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. need this to do anything useful with LEDs. If unsure, say N.
...@@ -95,11 +93,18 @@ config LEDS_COBALT ...@@ -95,11 +93,18 @@ config LEDS_COBALT
help help
This option enables support for the front LED on Cobalt Server 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" comment "LED Triggers"
config LEDS_TRIGGERS config LEDS_TRIGGERS
bool "LED Trigger support" bool "LED Trigger support"
depends on NEW_LEDS
help help
This option enables trigger support for the leds class. This option enables trigger support for the leds class.
These triggers allow kernel events to drive the LEDs and can These triggers allow kernel events to drive the LEDs and can
...@@ -128,5 +133,4 @@ config LEDS_TRIGGER_HEARTBEAT ...@@ -128,5 +133,4 @@ config LEDS_TRIGGER_HEARTBEAT
load average. load average.
If unsure, say Y. If unsure, say Y.
endmenu endif # NEW_LEDS
...@@ -16,6 +16,7 @@ obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o ...@@ -16,6 +16,7 @@ obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
# LED Triggers # LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* LED Class Core * LED Class Core
* *
* Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> * 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 * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -24,9 +24,10 @@ ...@@ -24,9 +24,10 @@
static struct class *leds_class; 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; ssize_t ret = 0;
/* no lock needed for this */ /* no lock needed for this */
...@@ -36,10 +37,10 @@ static ssize_t led_brightness_show(struct class_device *dev, char *buf) ...@@ -36,10 +37,10 @@ static ssize_t led_brightness_show(struct class_device *dev, char *buf)
return ret; return ret;
} }
static ssize_t led_brightness_store(struct class_device *dev, static ssize_t led_brightness_store(struct device *dev,
const char *buf, size_t size) 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; ssize_t ret = -EINVAL;
char *after; char *after;
unsigned long state = simple_strtoul(buf, &after, 10); unsigned long state = simple_strtoul(buf, &after, 10);
...@@ -56,10 +57,9 @@ static ssize_t led_brightness_store(struct class_device *dev, ...@@ -56,10 +57,9 @@ static ssize_t led_brightness_store(struct class_device *dev,
return ret; return ret;
} }
static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show, static DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store);
led_brightness_store);
#ifdef CONFIG_LEDS_TRIGGERS #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 #endif
/** /**
...@@ -93,16 +93,15 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) ...@@ -93,16 +93,15 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{ {
int rc; int rc;
led_cdev->class_dev = class_device_create(leds_class, NULL, 0, led_cdev->dev = device_create(leds_class, parent, 0, "%s",
parent, "%s", led_cdev->name); led_cdev->name);
if (unlikely(IS_ERR(led_cdev->class_dev))) if (unlikely(IS_ERR(led_cdev->dev)))
return PTR_ERR(led_cdev->class_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 */ /* register the attributes */
rc = class_device_create_file(led_cdev->class_dev, rc = device_create_file(led_cdev->dev, &dev_attr_brightness);
&class_device_attr_brightness);
if (rc) if (rc)
goto err_out; goto err_out;
...@@ -114,8 +113,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) ...@@ -114,8 +113,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
#ifdef CONFIG_LEDS_TRIGGERS #ifdef CONFIG_LEDS_TRIGGERS
rwlock_init(&led_cdev->trigger_lock); rwlock_init(&led_cdev->trigger_lock);
rc = class_device_create_file(led_cdev->class_dev, rc = device_create_file(led_cdev->dev, &dev_attr_trigger);
&class_device_attr_trigger);
if (rc) if (rc)
goto err_out_led_list; goto err_out_led_list;
...@@ -123,18 +121,17 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) ...@@ -123,18 +121,17 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
#endif #endif
printk(KERN_INFO "Registered led device: %s\n", printk(KERN_INFO "Registered led device: %s\n",
led_cdev->class_dev->class_id); led_cdev->name);
return 0; return 0;
#ifdef CONFIG_LEDS_TRIGGERS #ifdef CONFIG_LEDS_TRIGGERS
err_out_led_list: err_out_led_list:
class_device_remove_file(led_cdev->class_dev, device_remove_file(led_cdev->dev, &dev_attr_brightness);
&class_device_attr_brightness);
list_del(&led_cdev->node); list_del(&led_cdev->node);
#endif #endif
err_out: err_out:
class_device_unregister(led_cdev->class_dev); device_unregister(led_cdev->dev);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(led_classdev_register); EXPORT_SYMBOL_GPL(led_classdev_register);
...@@ -147,18 +144,16 @@ EXPORT_SYMBOL_GPL(led_classdev_register); ...@@ -147,18 +144,16 @@ EXPORT_SYMBOL_GPL(led_classdev_register);
*/ */
void led_classdev_unregister(struct led_classdev *led_cdev) void led_classdev_unregister(struct led_classdev *led_cdev)
{ {
class_device_remove_file(led_cdev->class_dev, device_remove_file(led_cdev->dev, &dev_attr_brightness);
&class_device_attr_brightness);
#ifdef CONFIG_LEDS_TRIGGERS #ifdef CONFIG_LEDS_TRIGGERS
class_device_remove_file(led_cdev->class_dev, device_remove_file(led_cdev->dev, &dev_attr_trigger);
&class_device_attr_trigger);
write_lock(&led_cdev->trigger_lock); write_lock(&led_cdev->trigger_lock);
if (led_cdev->trigger) if (led_cdev->trigger)
led_trigger_set(led_cdev, NULL); led_trigger_set(led_cdev, NULL);
write_unlock(&led_cdev->trigger_lock); write_unlock(&led_cdev->trigger_lock);
#endif #endif
class_device_unregister(led_cdev->class_dev); device_unregister(led_cdev->dev);
write_lock(&leds_list_lock); write_lock(&leds_list_lock);
list_del(&led_cdev->node); list_del(&led_cdev->node);
......
/* /*
* LED Triggers Core * LED Triggers Core
* *
* Copyright 2005-2006 Openedhand Ltd. * Copyright 2005-2007 Openedhand Ltd.
* *
* Author: Richard Purdie <rpurdie@openedhand.com> * Author: Richard Purdie <rpurdie@openedhand.com>
* *
...@@ -28,10 +28,10 @@ ...@@ -28,10 +28,10 @@
static DEFINE_RWLOCK(triggers_list_lock); static DEFINE_RWLOCK(triggers_list_lock);
static LIST_HEAD(trigger_list); static LIST_HEAD(trigger_list);
ssize_t led_trigger_store(struct class_device *dev, const char *buf, ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
size_t count) 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]; char trigger_name[TRIG_NAME_MAX];
struct led_trigger *trig; struct led_trigger *trig;
size_t len; size_t len;
...@@ -67,9 +67,10 @@ ssize_t led_trigger_store(struct class_device *dev, const char *buf, ...@@ -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; struct led_trigger *trig;
int len = 0; int len = 0;
...@@ -183,13 +184,20 @@ int led_trigger_register(struct led_trigger *trigger) ...@@ -183,13 +184,20 @@ int led_trigger_register(struct led_trigger *trigger)
void led_trigger_register_simple(const char *name, struct led_trigger **tp) void led_trigger_register_simple(const char *name, struct led_trigger **tp)
{ {
struct led_trigger *trigger; struct led_trigger *trigger;
int err;
trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
if (trigger) { if (trigger) {
trigger->name = name; 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; *tp = trigger;
} }
...@@ -215,7 +223,8 @@ void led_trigger_unregister(struct led_trigger *trigger) ...@@ -215,7 +223,8 @@ void led_trigger_unregister(struct led_trigger *trigger)
void led_trigger_unregister_simple(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); kfree(trigger);
} }
......
/*
* LEDs driver for GPIOs
*
* Copyright (C) 2007 8D Technologies inc.
* Raphael Assenat <raph@8d.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/platform_device.h>
#include <linux/leds.h>
#include <linux/workqueue.h>
#include <asm/gpio.h>
struct gpio_led_data {
struct led_classdev cdev;
unsigned gpio;
struct work_struct work;
u8 new_level;
u8 can_sleep;
u8 active_low;
};
static void gpio_led_work(struct work_struct *work)
{
struct gpio_led_data *led_dat =
container_of(work, struct gpio_led_data, work);
gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
}
static void gpio_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct gpio_led_data *led_dat =
container_of(led_cdev, struct gpio_led_data, cdev);
int level;
if (value == LED_OFF)
level = 0;
else
level = 1;
if (led_dat->active_low)
level = !level;
/* setting GPIOs with I2C/etc requires a preemptible task context */
if (led_dat->can_sleep) {
if (preempt_count()) {
led_dat->new_level = level;
schedule_work(&led_dat->work);
} else
gpio_set_value_cansleep(led_dat->gpio, level);
} else
gpio_set_value(led_dat->gpio, level);
}
static int __init gpio_led_probe(struct platform_device *pdev)
{
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
struct gpio_led *cur_led;
struct gpio_led_data *leds_data, *led_dat;
int i, ret = 0;
if (!pdata)
return -EBUSY;
leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds,
GFP_KERNEL);
if (!leds_data)
return -ENOMEM;
for (i = 0; i < pdata->num_leds; i++) {
cur_led = &pdata->leds[i];
led_dat = &leds_data[i];
led_dat->cdev.name = cur_led->name;
led_dat->cdev.default_trigger = cur_led->default_trigger;
led_dat->gpio = cur_led->gpio;
led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
led_dat->active_low = cur_led->active_low;
led_dat->cdev.brightness_set = gpio_led_set;
led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF;
ret = gpio_request(led_dat->gpio, led_dat->cdev.name);
if (ret < 0)
goto err;
gpio_direction_output(led_dat->gpio, led_dat->active_low);
ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
if (ret < 0) {
gpio_free(led_dat->gpio);
goto err;
}
INIT_WORK(&led_dat->work, gpio_led_work);
}
platform_set_drvdata(pdev, leds_data);
return 0;
err:
if (i > 0) {
for (i = i - 1; i >= 0; i--) {
led_classdev_unregister(&leds_data[i].cdev);
gpio_free(leds_data[i].gpio);
}
}
flush_scheduled_work();
kfree(leds_data);
return ret;
}
static int __exit gpio_led_remove(struct platform_device *pdev)
{
int i;
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
struct gpio_led_data *leds_data;
leds_data = platform_get_drvdata(pdev);
for (i = 0; i < pdata->num_leds; i++) {
led_classdev_unregister(&leds_data[i].cdev);
gpio_free(leds_data[i].gpio);
}
kfree(leds_data);
return 0;
}
#ifdef CONFIG_PM
static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state)
{
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
struct gpio_led_data *leds_data;
int i;
leds_data = platform_get_drvdata(pdev);
for (i = 0; i < pdata->num_leds; i++)
led_classdev_suspend(&leds_data[i].cdev);
return 0;
}
static int gpio_led_resume(struct platform_device *pdev)
{
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
struct gpio_led_data *leds_data;
int i;
leds_data = platform_get_drvdata(pdev);
for (i = 0; i < pdata->num_leds; i++)
led_classdev_resume(&leds_data[i].cdev);
return 0;
}
#else
#define gpio_led_suspend NULL
#define gpio_led_resume NULL
#endif
static struct platform_driver gpio_led_driver = {
.remove = __exit_p(gpio_led_remove),
.suspend = gpio_led_suspend,
.resume = gpio_led_resume,
.driver = {
.name = "leds-gpio",
.owner = THIS_MODULE,
},
};
static int __init gpio_led_init(void)
{
return platform_driver_probe(&gpio_led_driver, gpio_led_probe);
}
static void __exit gpio_led_exit(void)
{
platform_driver_unregister(&gpio_led_driver);
}
module_init(gpio_led_init);
module_exit(gpio_led_exit);
MODULE_AUTHOR("Raphael Assenat <raph@8d.com>");
MODULE_DESCRIPTION("GPIO LED driver");
MODULE_LICENSE("GPL");
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
static void locomoled_brightness_set(struct led_classdev *led_cdev, static void locomoled_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value, int offset) enum led_brightness value, int offset)
{ {
struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev); struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->dev);
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#ifndef __LEDS_H_INCLUDED #ifndef __LEDS_H_INCLUDED
#define __LEDS_H_INCLUDED #define __LEDS_H_INCLUDED
#include <linux/device.h>
#include <linux/leds.h> #include <linux/leds.h>
static inline void led_set_brightness(struct led_classdev *led_cdev, static inline void led_set_brightness(struct led_classdev *led_cdev,
...@@ -37,8 +38,9 @@ void led_trigger_set(struct led_classdev *led_cdev, ...@@ -37,8 +38,9 @@ void led_trigger_set(struct led_classdev *led_cdev,
#define led_trigger_set(x, y) do {} while(0) #define led_trigger_set(x, y) do {} while(0)
#endif #endif
ssize_t led_trigger_store(struct class_device *dev, const char *buf, ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
size_t count); const char *buf, size_t count);
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);
#endif /* __LEDS_H_INCLUDED */ #endif /* __LEDS_H_INCLUDED */
...@@ -52,9 +52,10 @@ static void led_timer_function(unsigned long data) ...@@ -52,9 +52,10 @@ static void led_timer_function(unsigned long data)
mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay));
} }
static ssize_t led_delay_on_show(struct class_device *dev, char *buf) static ssize_t led_delay_on_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 timer_trig_data *timer_data = led_cdev->trigger_data; struct timer_trig_data *timer_data = led_cdev->trigger_data;
sprintf(buf, "%lu\n", timer_data->delay_on); sprintf(buf, "%lu\n", timer_data->delay_on);
...@@ -62,10 +63,10 @@ static ssize_t led_delay_on_show(struct class_device *dev, char *buf) ...@@ -62,10 +63,10 @@ static ssize_t led_delay_on_show(struct class_device *dev, char *buf)
return strlen(buf) + 1; return strlen(buf) + 1;
} }
static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, static ssize_t led_delay_on_store(struct device *dev,
size_t size) 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);
struct timer_trig_data *timer_data = led_cdev->trigger_data; struct timer_trig_data *timer_data = led_cdev->trigger_data;
int ret = -EINVAL; int ret = -EINVAL;
char *after; char *after;
...@@ -84,9 +85,10 @@ static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, ...@@ -84,9 +85,10 @@ static ssize_t led_delay_on_store(struct class_device *dev, const char *buf,
return ret; return ret;
} }
static ssize_t led_delay_off_show(struct class_device *dev, char *buf) static ssize_t led_delay_off_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 timer_trig_data *timer_data = led_cdev->trigger_data; struct timer_trig_data *timer_data = led_cdev->trigger_data;
sprintf(buf, "%lu\n", timer_data->delay_off); sprintf(buf, "%lu\n", timer_data->delay_off);
...@@ -94,10 +96,10 @@ static ssize_t led_delay_off_show(struct class_device *dev, char *buf) ...@@ -94,10 +96,10 @@ static ssize_t led_delay_off_show(struct class_device *dev, char *buf)
return strlen(buf) + 1; return strlen(buf) + 1;
} }
static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, static ssize_t led_delay_off_store(struct device *dev,
size_t size) 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);
struct timer_trig_data *timer_data = led_cdev->trigger_data; struct timer_trig_data *timer_data = led_cdev->trigger_data;
int ret = -EINVAL; int ret = -EINVAL;
char *after; char *after;
...@@ -116,10 +118,8 @@ static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, ...@@ -116,10 +118,8 @@ static ssize_t led_delay_off_store(struct class_device *dev, const char *buf,
return ret; return ret;
} }
static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show, static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
led_delay_on_store); static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show,
led_delay_off_store);
static void timer_trig_activate(struct led_classdev *led_cdev) static void timer_trig_activate(struct led_classdev *led_cdev)
{ {
...@@ -136,18 +136,17 @@ static void timer_trig_activate(struct led_classdev *led_cdev) ...@@ -136,18 +136,17 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
timer_data->timer.function = led_timer_function; timer_data->timer.function = led_timer_function;
timer_data->timer.data = (unsigned long) led_cdev; timer_data->timer.data = (unsigned long) led_cdev;
rc = class_device_create_file(led_cdev->class_dev, rc = device_create_file(led_cdev->dev, &dev_attr_delay_on);
&class_device_attr_delay_on); if (rc)
if (rc) goto err_out; goto err_out;
rc = class_device_create_file(led_cdev->class_dev, rc = device_create_file(led_cdev->dev, &dev_attr_delay_off);
&class_device_attr_delay_off); if (rc)
if (rc) goto err_out_delayon; goto err_out_delayon;
return; return;
err_out_delayon: err_out_delayon:
class_device_remove_file(led_cdev->class_dev, device_remove_file(led_cdev->dev, &dev_attr_delay_on);
&class_device_attr_delay_on);
err_out: err_out:
led_cdev->trigger_data = NULL; led_cdev->trigger_data = NULL;
kfree(timer_data); kfree(timer_data);
...@@ -158,10 +157,8 @@ static void timer_trig_deactivate(struct led_classdev *led_cdev) ...@@ -158,10 +157,8 @@ static void timer_trig_deactivate(struct led_classdev *led_cdev)
struct timer_trig_data *timer_data = led_cdev->trigger_data; struct timer_trig_data *timer_data = led_cdev->trigger_data;
if (timer_data) { if (timer_data) {
class_device_remove_file(led_cdev->class_dev, device_remove_file(led_cdev->dev, &dev_attr_delay_on);
&class_device_attr_delay_on); device_remove_file(led_cdev->dev, &dev_attr_delay_off);
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_delay_off);
del_timer_sync(&timer_data->timer); del_timer_sync(&timer_data->timer);
kfree(timer_data); kfree(timer_data);
} }
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/list.h> #include <linux/list.h>
struct device; struct device;
struct class_device;
/* /*
* LED Core * LED Core
*/ */
...@@ -37,7 +36,7 @@ struct led_classdev { ...@@ -37,7 +36,7 @@ struct led_classdev {
void (*brightness_set)(struct led_classdev *led_cdev, void (*brightness_set)(struct led_classdev *led_cdev,
enum led_brightness brightness); enum led_brightness brightness);
struct class_device *class_dev; struct device *dev;
struct list_head node; /* LED Device list */ struct list_head node; /* LED Device list */
char *default_trigger; /* Trigger to use */ char *default_trigger; /* Trigger to use */
...@@ -109,4 +108,18 @@ extern void ledtrig_ide_activity(void); ...@@ -109,4 +108,18 @@ extern void ledtrig_ide_activity(void);
#define ledtrig_ide_activity() do {} while(0) #define ledtrig_ide_activity() do {} while(0)
#endif #endif
/* For the leds-gpio driver */
struct gpio_led {
const char *name;
char *default_trigger;
unsigned gpio;
u8 active_low;
};
struct gpio_led_platform_data {
int num_leds;
struct gpio_led *leds;
};
#endif /* __LINUX_LEDS_H_INCLUDED */ #endif /* __LINUX_LEDS_H_INCLUDED */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment