diff options
97 files changed, 1438 insertions, 2980 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e91c7cdc6fe..ac353cf0180 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1787,59 +1787,6 @@ config FORCE_MAX_ZONEORDER  	  This config option is actually maximum order plus one. For example,  	  a value of 11 means that the largest free memory block is 2^10 pages. -config LEDS -	bool "Timer and CPU usage LEDs" -	depends on ARCH_CDB89712 || ARCH_EBSA110 || \ -		   ARCH_EBSA285 || ARCH_INTEGRATOR || \ -		   ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \ -		   ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ -		   ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ -		   ARCH_AT91 || ARCH_DAVINCI || \ -		   ARCH_KS8695 || MACH_RD88F5182 || ARCH_REALVIEW -	help -	  If you say Y here, the LEDs on your machine will be used -	  to provide useful information about your current system status. - -	  If you are compiling a kernel for a NetWinder or EBSA-285, you will -	  be able to select which LEDs are active using the options below. If -	  you are compiling a kernel for the EBSA-110 or the LART however, the -	  red LED will simply flash regularly to indicate that the system is -	  still functional. It is safe to say Y here if you have a CATS -	  system, but the driver will do nothing. - -config LEDS_TIMER -	bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \ -			    OMAP_OSK_MISTRAL || MACH_OMAP_H2 \ -			    || MACH_OMAP_PERSEUS2 -	depends on LEDS -	depends on !GENERIC_CLOCKEVENTS -	default y if ARCH_EBSA110 -	help -	  If you say Y here, one of the system LEDs (the green one on the -	  NetWinder, the amber one on the EBSA285, or the red one on the LART) -	  will flash regularly to indicate that the system is still -	  operational. This is mainly useful to kernel hackers who are -	  debugging unstable kernels. - -	  The LART uses the same LED for both Timer LED and CPU usage LED -	  functions. You may choose to use both, but the Timer LED function -	  will overrule the CPU usage LED. - -config LEDS_CPU -	bool "CPU usage LED" if (!ARCH_CDB89712 && !ARCH_EBSA110 && \ -			!ARCH_OMAP) \ -			|| OMAP_OSK_MISTRAL || MACH_OMAP_H2 \ -			|| MACH_OMAP_PERSEUS2 -	depends on LEDS -	help -	  If you say Y here, the red LED will be used to give a good real -	  time indication of CPU usage, by lighting whenever the idle task -	  is not currently executing. - -	  The LART uses the same LED for both Timer LED and CPU usage LED -	  functions. You may choose to use both, but the Timer LED function -	  will overrule the CPU usage LED. -  config ALIGNMENT_TRAP  	bool  	depends on CPU_CP15_MMU diff --git a/arch/arm/include/asm/leds.h b/arch/arm/include/asm/leds.h deleted file mode 100644 index c545739f39b..00000000000 --- a/arch/arm/include/asm/leds.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - *  arch/arm/include/asm/leds.h - * - *  Copyright (C) 1998 Russell King - * - * 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. - * - *  Event-driven interface for LEDs on machines - *  Added led_start and led_stop- Alex Holden, 28th Dec 1998. - */ -#ifndef ASM_ARM_LEDS_H -#define ASM_ARM_LEDS_H - - -typedef enum { -	led_idle_start, -	led_idle_end, -	led_timer, -	led_start, -	led_stop, -	led_claim,		/* override idle & timer leds */ -	led_release,		/* restore idle & timer leds */ -	led_start_timer_mode, -	led_stop_timer_mode, -	led_green_on, -	led_green_off, -	led_amber_on, -	led_amber_off, -	led_red_on, -	led_red_off, -	led_blue_on, -	led_blue_off, -	/* -	 * I want this between led_timer and led_start, but -	 * someone has decided to export this to user space -	 */ -	led_halted -} led_event_t; - -/* Use this routine to handle LEDs */ - -#ifdef CONFIG_LEDS -extern void (*leds_event)(led_event_t); -#else -#define leds_event(e) -#endif - -#endif diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7ad2d5cf700..8951577c4ce 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -21,7 +21,6 @@ obj-y		:= elf.o entry-armv.o entry-common.o irq.o opcodes.o \  obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o -obj-$(CONFIG_LEDS)		+= leds.o  obj-$(CONFIG_OC_ETM)		+= etm.o  obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o  obj-$(CONFIG_ISA_DMA_API)	+= dma.o diff --git a/arch/arm/kernel/leds.c b/arch/arm/kernel/leds.c deleted file mode 100644 index 1911dae19e4..00000000000 --- a/arch/arm/kernel/leds.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * LED support code, ripped out of arch/arm/kernel/time.c - * - *  Copyright (C) 1994-2001 Russell King - * - * 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/export.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/syscore_ops.h> -#include <linux/string.h> - -#include <asm/leds.h> - -static void dummy_leds_event(led_event_t evt) -{ -} - -void (*leds_event)(led_event_t) = dummy_leds_event; - -struct leds_evt_name { -	const char	name[8]; -	int		on; -	int		off; -}; - -static const struct leds_evt_name evt_names[] = { -	{ "amber", led_amber_on, led_amber_off }, -	{ "blue",  led_blue_on,  led_blue_off  }, -	{ "green", led_green_on, led_green_off }, -	{ "red",   led_red_on,   led_red_off   }, -}; - -static ssize_t leds_store(struct device *dev, -			struct device_attribute *attr, -			const char *buf, size_t size) -{ -	int ret = -EINVAL, len = strcspn(buf, " "); - -	if (len > 0 && buf[len] == '\0') -		len--; - -	if (strncmp(buf, "claim", len) == 0) { -		leds_event(led_claim); -		ret = size; -	} else if (strncmp(buf, "release", len) == 0) { -		leds_event(led_release); -		ret = size; -	} else { -		int i; - -		for (i = 0; i < ARRAY_SIZE(evt_names); i++) { -			if (strlen(evt_names[i].name) != len || -			    strncmp(buf, evt_names[i].name, len) != 0) -				continue; -			if (strncmp(buf+len, " on", 3) == 0) { -				leds_event(evt_names[i].on); -				ret = size; -			} else if (strncmp(buf+len, " off", 4) == 0) { -				leds_event(evt_names[i].off); -				ret = size; -			} -			break; -		} -	} -	return ret; -} - -static DEVICE_ATTR(event, 0200, NULL, leds_store); - -static struct bus_type leds_subsys = { -	.name		= "leds", -	.dev_name	= "leds", -}; - -static struct device leds_device = { -	.id		= 0, -	.bus		= &leds_subsys, -}; - -static int leds_suspend(void) -{ -	leds_event(led_stop); -	return 0; -} - -static void leds_resume(void) -{ -	leds_event(led_start); -} - -static void leds_shutdown(void) -{ -	leds_event(led_halted); -} - -static struct syscore_ops leds_syscore_ops = { -	.shutdown	= leds_shutdown, -	.suspend	= leds_suspend, -	.resume		= leds_resume, -}; - -static int __init leds_init(void) -{ -	int ret; -	ret = subsys_system_register(&leds_subsys, NULL); -	if (ret == 0) -		ret = device_register(&leds_device); -	if (ret == 0) -		ret = device_create_file(&leds_device, &dev_attr_event); -	if (ret == 0) -		register_syscore_ops(&leds_syscore_ops); -	return ret; -} - -device_initcall(leds_init); - -EXPORT_SYMBOL(leds_event); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 693b744fd57..04eea22d795 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -31,9 +31,9 @@  #include <linux/random.h>  #include <linux/hw_breakpoint.h>  #include <linux/cpuidle.h> +#include <linux/leds.h>  #include <asm/cacheflush.h> -#include <asm/leds.h>  #include <asm/processor.h>  #include <asm/thread_notify.h>  #include <asm/stacktrace.h> @@ -189,7 +189,7 @@ void cpu_idle(void)  	while (1) {  		tick_nohz_idle_enter();  		rcu_idle_enter(); -		leds_event(led_idle_start); +		ledtrig_cpu(CPU_LED_IDLE_START);  		while (!need_resched()) {  #ifdef CONFIG_HOTPLUG_CPU  			if (cpu_is_offline(smp_processor_id())) @@ -220,7 +220,7 @@ void cpu_idle(void)  			} else  				local_irq_enable();  		} -		leds_event(led_idle_end); +		ledtrig_cpu(CPU_LED_IDLE_END);  		rcu_idle_exit();  		tick_nohz_idle_exit();  		schedule_preempt_disabled(); diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index af2afb01967..09be0c3c906 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -25,7 +25,6 @@  #include <linux/timer.h>  #include <linux/irq.h> -#include <asm/leds.h>  #include <asm/thread_info.h>  #include <asm/sched_clock.h>  #include <asm/stacktrace.h> @@ -80,21 +79,6 @@ u32 arch_gettimeoffset(void)  }  #endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ -#ifdef CONFIG_LEDS_TIMER -static inline void do_leds(void) -{ -	static unsigned int count = HZ/2; - -	if (--count == 0) { -		count = HZ/2; -		leds_event(led_timer); -	} -} -#else -#define	do_leds() -#endif - -  #ifndef CONFIG_GENERIC_CLOCKEVENTS  /*   * Kernel system timer support. @@ -102,7 +86,6 @@ static inline void do_leds(void)  void timer_tick(void)  {  	profile_tick(CPU_PROFILING); -	do_leds();  	xtime_update(1);  #ifndef CONFIG_SMP  	update_process_times(user_mode(get_irq_regs())); diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c index 462bc319cbc..32396bb4a4c 100644 --- a/arch/arm/mach-at91/board-csb337.c +++ b/arch/arm/mach-at91/board-csb337.c @@ -220,8 +220,6 @@ static struct gpio_led csb_leds[] = {  static void __init csb337_board_init(void)  { -	/* Setup the LEDs */ -	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);  	/* Serial */  	/* DBGU on ttyS0 */  	at91_register_uart(0, 0, 0); diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c index 9c24cb25707..192ec76579c 100644 --- a/arch/arm/mach-at91/board-ecbat91.c +++ b/arch/arm/mach-at91/board-ecbat91.c @@ -138,11 +138,20 @@ static struct spi_board_info __initdata ecb_at91spi_devices[] = {  	},  }; +/* + * LEDs + */ +static struct gpio_led ecb_leds[] = { +	{	/* D1 */ +		.name			= "led1", +		.gpio			= AT91_PIN_PC7, +		.active_low		= 1, +		.default_trigger	= "heartbeat", +	} +}; +  static void __init ecb_at91board_init(void)  { -	/* Setup the LEDs */ -	at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7); -  	/* Serial */  	/* DBGU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); @@ -165,6 +174,9 @@ static void __init ecb_at91board_init(void)  	/* SPI */  	at91_add_device_spi(ecb_at91spi_devices, ARRAY_SIZE(ecb_at91spi_devices)); + +	/* LEDs */ +	at91_gpio_leds(ecb_leds, ARRAY_SIZE(ecb_leds));  }  MACHINE_START(ECBAT91, "emQbit's ECB_AT91") diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c index 82bdfde3405..d2d4580df48 100644 --- a/arch/arm/mach-at91/board-eco920.c +++ b/arch/arm/mach-at91/board-eco920.c @@ -93,10 +93,26 @@ static struct spi_board_info eco920_spi_devices[] = {  	},  }; +/* + * LEDs + */ +static struct gpio_led eco920_leds[] = { +	{       /* D1 */ +		.name                   = "led1", +		.gpio                   = AT91_PIN_PB0, +		.active_low             = 1, +		.default_trigger        = "heartbeat", +	}, +	{       /* D2 */ +		.name                   = "led2", +		.gpio                   = AT91_PIN_PB1, +		.active_low             = 1, +		.default_trigger        = "timer", +	} +}; +  static void __init eco920_board_init(void)  { -	/* Setup the LEDs */ -	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);  	/* DBGU on ttyS0. (Rx & Tx only */  	at91_register_uart(0, 0, 0);  	at91_add_device_serial(); @@ -127,6 +143,8 @@ static void __init eco920_board_init(void)  	);  	at91_add_device_spi(eco920_spi_devices, ARRAY_SIZE(eco920_spi_devices)); +	/* LEDs */ +	at91_gpio_leds(eco920_leds, ARRAY_SIZE(eco920_leds));  }  MACHINE_START(ECO920, "eco920") diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c index 64c1dbf88a0..86050da3ba5 100644 --- a/arch/arm/mach-at91/board-kafa.c +++ b/arch/arm/mach-at91/board-kafa.c @@ -66,11 +66,20 @@ static struct at91_udc_data __initdata kafa_udc_data = {  	.pullup_pin	= AT91_PIN_PB7,  }; +/* + * LEDs + */ +static struct gpio_led kafa_leds[] = { +	{	/* D1 */ +		.name			= "led1", +		.gpio			= AT91_PIN_PB4, +		.active_low		= 1, +		.default_trigger	= "heartbeat", +	}, +}; +  static void __init kafa_board_init(void)  { -	/* Set up the LEDs */ -	at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4); -  	/* Serial */  	/* DBGU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); @@ -88,6 +97,8 @@ static void __init kafa_board_init(void)  	at91_add_device_i2c(NULL, 0);  	/* SPI */  	at91_add_device_spi(NULL, 0); +	/* LEDs */ +	at91_gpio_leds(kafa_leds, ARRAY_SIZE(kafa_leds));  }  MACHINE_START(KAFA, "Sperry-Sun KAFA") diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c index 5d96cb85175..00d60071770 100644 --- a/arch/arm/mach-at91/board-kb9202.c +++ b/arch/arm/mach-at91/board-kb9202.c @@ -96,11 +96,26 @@ static struct atmel_nand_data __initdata kb9202_nand_data = {  	.num_parts	= ARRAY_SIZE(kb9202_nand_partition),  }; +/* + * LEDs + */ +static struct gpio_led kb9202_leds[] = { +	{	/* D1 */ +		.name			= "led1", +		.gpio			= AT91_PIN_PC19, +		.active_low		= 1, +		.default_trigger	= "heartbeat", +	}, +	{	/* D2 */ +		.name			= "led2", +		.gpio			= AT91_PIN_PC18, +		.active_low		= 1, +		.default_trigger	= "timer", +	} +}; +  static void __init kb9202_board_init(void)  { -	/* Set up the LEDs */ -	at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18); -  	/* Serial */  	/* DBGU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); @@ -128,6 +143,8 @@ static void __init kb9202_board_init(void)  	at91_add_device_spi(NULL, 0);  	/* NAND */  	at91_add_device_nand(&kb9202_nand_data); +	/* LEDs */ +	at91_gpio_leds(kb9202_leds, ARRAY_SIZE(kb9202_leds));  }  MACHINE_START(KB9200, "KB920x") diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c index cc2bf979607..2526ad759b5 100644 --- a/arch/arm/mach-at91/board-rm9200dk.c +++ b/arch/arm/mach-at91/board-rm9200dk.c @@ -177,9 +177,6 @@ static struct gpio_led dk_leds[] = {  static void __init dk_board_init(void)  { -	/* Setup the LEDs */ -	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); -  	/* Serial */  	/* DBGU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c index 62e19e64c9d..06f2ce543e2 100644 --- a/arch/arm/mach-at91/board-rm9200ek.c +++ b/arch/arm/mach-at91/board-rm9200ek.c @@ -148,9 +148,6 @@ static struct gpio_led ek_leds[] = {  static void __init ek_board_init(void)  { -	/* Setup the LEDs */ -	at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2); -  	/* Serial */  	/* DBGU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c index c3b43aefdb7..93b8e3a45e2 100644 --- a/arch/arm/mach-at91/board-rsi-ews.c +++ b/arch/arm/mach-at91/board-rsi-ews.c @@ -185,9 +185,6 @@ static struct platform_device rsiews_nor_flash = {   */  static void __init rsi_ews_board_init(void)  { -	/* Setup the LEDs */ -	at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9); -  	/* Serial */  	/* DBGU on ttyS0. (Rx & Tx only) */  	/* This one is for debugging */ diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c index 7bf6da70d7d..46e1eb55053 100644 --- a/arch/arm/mach-at91/board-sam9-l9260.c +++ b/arch/arm/mach-at91/board-sam9-l9260.c @@ -166,11 +166,26 @@ static struct at91_mmc_data __initdata ek_mmc_data = {  	.vcc_pin	= -EINVAL,  }; +/* + * LEDs + */ +static struct gpio_led ek_leds[] = { +	{	/* D1 */ +		.name			= "led1", +		.gpio			= AT91_PIN_PA9, +		.active_low		= 1, +		.default_trigger	= "heartbeat", +	}, +	{	/* D2 */ +		.name			= "led2", +		.gpio			= AT91_PIN_PA6, +		.active_low		= 1, +		.default_trigger	= "timer", +	} +}; +  static void __init ek_board_init(void)  { -	/* Setup the LEDs */ -	at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6); -  	/* Serial */  	/* DBGU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); @@ -197,6 +212,8 @@ static void __init ek_board_init(void)  	at91_add_device_mmc(0, &ek_mmc_data);  	/* I2C */  	at91_add_device_i2c(NULL, 0); +	/* LEDs */ +	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));  }  MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260") diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 2269be5fa38..802d4946bb3 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -569,9 +569,6 @@ static struct gpio_led ek_leds[] = {  static void __init ek_board_init(void)  { -	/* Setup the LEDs */ -	at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14); -  	/* Serial */  	/* DBGU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c index 516d340549d..9fd57bcac69 100644 --- a/arch/arm/mach-at91/board-yl-9200.c +++ b/arch/arm/mach-at91/board-yl-9200.c @@ -541,9 +541,6 @@ void __init yl9200_add_device_video(void) {}  static void __init yl9200_board_init(void)  { -	/* Setup the LEDs D2=PB17 (timer), D3=PB16 (cpu) */ -	at91_init_leds(AT91_PIN_PB16, AT91_PIN_PB17); -  	/* Serial */  	/* DBGU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 369afc2ffc5..c55a4364ffb 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -187,7 +187,6 @@ struct at91_can_data {  extern void __init at91_add_device_can(struct at91_can_data *data);   /* LEDs */ -extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);  extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);  extern void __init at91_pwm_leds(struct gpio_led *leds, int nr); diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c index 8dfafe76ffe..1b1e62b5f41 100644 --- a/arch/arm/mach-at91/leds.c +++ b/arch/arm/mach-at91/leds.c @@ -90,108 +90,3 @@ void __init at91_pwm_leds(struct gpio_led *leds, int nr)  #else  void __init at91_pwm_leds(struct gpio_led *leds, int nr){}  #endif - - -/* ------------------------------------------------------------------------- */ - -#if defined(CONFIG_LEDS) - -#include <asm/leds.h> - -/* - * Old ARM-specific LED framework; not fully functional when generic time is - * in use. - */ - -static u8 at91_leds_cpu; -static u8 at91_leds_timer; - -static inline void at91_led_on(unsigned int led) -{ -	at91_set_gpio_value(led, 0); -} - -static inline void at91_led_off(unsigned int led) -{ -	at91_set_gpio_value(led, 1); -} - -static inline void at91_led_toggle(unsigned int led) -{ -	unsigned long is_off = at91_get_gpio_value(led); -	if (is_off) -		at91_led_on(led); -	else -		at91_led_off(led); -} - - -/* - * Handle LED events. - */ -static void at91_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	switch(evt) { -	case led_start:		/* System startup */ -		at91_led_on(at91_leds_cpu); -		break; - -	case led_stop:		/* System stop / suspend */ -		at91_led_off(at91_leds_cpu); -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer:		/* Every 50 timer ticks */ -		at91_led_toggle(at91_leds_timer); -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start:	/* Entering idle state */ -		at91_led_off(at91_leds_cpu); -		break; - -	case led_idle_end:	/* Exit idle state */ -		at91_led_on(at91_leds_cpu); -		break; -#endif - -	default: -		break; -	} - -	local_irq_restore(flags); -} - - -static int __init leds_init(void) -{ -	if (!at91_leds_timer || !at91_leds_cpu) -		return -ENODEV; - -	leds_event = at91_leds_event; - -	leds_event(led_start); -	return 0; -} - -__initcall(leds_init); - - -void __init at91_init_leds(u8 cpu_led, u8 timer_led) -{ -	/* Enable GPIO to access the LEDs */ -	at91_set_gpio_output(cpu_led, 1); -	at91_set_gpio_output(timer_led, 1); - -	at91_leds_cpu	= cpu_led; -	at91_leds_timer	= timer_led; -} - -#else -void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} -#endif diff --git a/arch/arm/mach-clps711x/Makefile b/arch/arm/mach-clps711x/Makefile index f2f0256232e..5872b49bfae 100644 --- a/arch/arm/mach-clps711x/Makefile +++ b/arch/arm/mach-clps711x/Makefile @@ -16,5 +16,3 @@ obj-$(CONFIG_ARCH_CLEP7312) += clep7312.o  obj-$(CONFIG_ARCH_EDB7211)  += edb7211-arch.o edb7211-mm.o  obj-$(CONFIG_ARCH_FORTUNET) += fortunet.o  obj-$(CONFIG_ARCH_P720T)    += p720t.o -leds-$(CONFIG_ARCH_P720T)   += p720t-leds.o -obj-$(CONFIG_LEDS)          += $(leds-y) diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c index f15293bd797..3a4af00db9e 100644 --- a/arch/arm/mach-clps711x/common.c +++ b/arch/arm/mach-clps711x/common.c @@ -30,7 +30,6 @@  #include <asm/sizes.h>  #include <mach/hardware.h>  #include <asm/irq.h> -#include <asm/leds.h>  #include <asm/pgtable.h>  #include <asm/page.h>  #include <asm/mach/map.h> diff --git a/arch/arm/mach-clps711x/p720t-leds.c b/arch/arm/mach-clps711x/p720t-leds.c deleted file mode 100644 index bbc449fbe14..00000000000 --- a/arch/arm/mach-clps711x/p720t-leds.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - *  linux/arch/arm/mach-clps711x/leds.c - * - *  Integrator LED control routines - * - *  Copyright (C) 2000 Deep Blue Solutions Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <asm/leds.h> -#include <asm/mach-types.h> - -static void p720t_leds_event(led_event_t ledevt) -{ -	unsigned long flags; -	u32 pddr; - -	local_irq_save(flags); -	switch(ledevt) { -	case led_idle_start: -		break; - -	case led_idle_end: -		break; - -	case led_timer: -		pddr = clps_readb(PDDR); -		clps_writeb(pddr ^ 1, PDDR); -		break; - -	default: -		break; -	} - -	local_irq_restore(flags); -} - -static int __init leds_init(void) -{ -	if (machine_is_p720t()) -		leds_event = p720t_leds_event; - -	return 0; -} - -arch_initcall(leds_init); diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c index f266d90b9ef..b752b586fc2 100644 --- a/arch/arm/mach-clps711x/p720t.c +++ b/arch/arm/mach-clps711x/p720t.c @@ -23,6 +23,8 @@  #include <linux/string.h>  #include <linux/mm.h>  #include <linux/io.h> +#include <linux/slab.h> +#include <linux/leds.h>  #include <mach/hardware.h>  #include <asm/pgtable.h> @@ -34,6 +36,8 @@  #include <asm/mach/map.h>  #include <mach/syspld.h> +#include <asm/hardware/clps7111.h> +  #include "common.h"  /* @@ -107,6 +111,64 @@ static void __init p720t_init_early(void)  	}  } +/* + * LED controled by CPLD + */ +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +static void p720t_led_set(struct led_classdev *cdev, +			      enum led_brightness b) +{ +	u8 reg = clps_readb(PDDR); + +	if (b != LED_OFF) +		reg |= 0x1; +	else +		reg &= ~0x1; + +	clps_writeb(reg, PDDR); +} + +static enum led_brightness p720t_led_get(struct led_classdev *cdev) +{ +	u8 reg = clps_readb(PDDR); + +	return (reg & 0x1) ? LED_FULL : LED_OFF; +} + +static int __init p720t_leds_init(void) +{ + +	struct led_classdev *cdev; +	int ret; + +	if (!machine_is_p720t()) +		return -ENODEV; + +	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); +	if (!cdev) +		return -ENOMEM; + +	cdev->name = "p720t:0"; +	cdev->brightness_set = p720t_led_set; +	cdev->brightness_get = p720t_led_get; +	cdev->default_trigger = "heartbeat"; + +	ret = led_classdev_register(NULL, cdev); +	if (ret	< 0) { +		kfree(cdev); +		return ret; +	} + +	return 0; +} + +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(p720t_leds_init); +#endif +  MACHINE_START(P720T, "ARM-Prospector720T")  	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */  	.atag_offset	= 0x100, diff --git a/arch/arm/mach-ebsa110/Makefile b/arch/arm/mach-ebsa110/Makefile index 6520ac83580..935e4af01a2 100644 --- a/arch/arm/mach-ebsa110/Makefile +++ b/arch/arm/mach-ebsa110/Makefile @@ -4,9 +4,7 @@  # Object file lists. -obj-y			:= core.o io.o +obj-y			:= core.o io.o leds.o  obj-m			:=  obj-n			:=  obj-			:= - -obj-$(CONFIG_LEDS)	+= leds.o diff --git a/arch/arm/mach-ebsa110/leds.c b/arch/arm/mach-ebsa110/leds.c index 99e14e36250..0398258c20c 100644 --- a/arch/arm/mach-ebsa110/leds.c +++ b/arch/arm/mach-ebsa110/leds.c @@ -1,52 +1,71 @@  /* - *  linux/arch/arm/mach-ebsa110/leds.c + * Driver for the LED found on the EBSA110 machine + * Based on Versatile and RealView machine LED code   * - *  Copyright (C) 1998 Russell King - * - * 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. - * - *  EBSA-110 LED control routines.  We use the led as follows: - * - *   - Red - toggles state every 50 timer interrupts + * License terms: GNU General Public License (GPL) version 2 + * Author: Bryan Wu <bryan.wu@canonical.com>   */ -#include <linux/module.h> -#include <linux/spinlock.h> +#include <linux/kernel.h>  #include <linux/init.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/leds.h> -#include <mach/hardware.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include "core.h" -static spinlock_t leds_lock; - -static void ebsa110_leds_event(led_event_t ledevt) +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +static void ebsa110_led_set(struct led_classdev *cdev, +			      enum led_brightness b)  { -	unsigned long flags; +	u8 reg = __raw_readb(SOFT_BASE); -	spin_lock_irqsave(&leds_lock, flags); +	if (b != LED_OFF) +		reg |= 0x80; +	else +		reg &= ~0x80; -	switch(ledevt) { -	case led_timer: -		*(volatile unsigned char *)SOFT_BASE ^= 128; -		break; +	__raw_writeb(reg, SOFT_BASE); +} -	default: -		break; -	} +static enum led_brightness ebsa110_led_get(struct led_classdev *cdev) +{ +	u8 reg = __raw_readb(SOFT_BASE); -	spin_unlock_irqrestore(&leds_lock, flags); +	return (reg & 0x80) ? LED_FULL : LED_OFF;  } -static int __init leds_init(void) +static int __init ebsa110_leds_init(void)  { -	if (machine_is_ebsa110()) -		leds_event = ebsa110_leds_event; + +	struct led_classdev *cdev; +	int ret; + +	if (!machine_is_ebsa110()) +		return -ENODEV; + +	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); +	if (!cdev) +		return -ENOMEM; + +	cdev->name = "ebsa110:0"; +	cdev->brightness_set = ebsa110_led_set; +	cdev->brightness_get = ebsa110_led_get; +	cdev->default_trigger = "heartbeat"; + +	ret = led_classdev_register(NULL, cdev); +	if (ret	< 0) { +		kfree(cdev); +		return ret; +	}  	return 0;  } -__initcall(leds_init); +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(ebsa110_leds_init); +#endif diff --git a/arch/arm/mach-footbridge/Makefile b/arch/arm/mach-footbridge/Makefile index 3afb1b25946..0b64dd430d6 100644 --- a/arch/arm/mach-footbridge/Makefile +++ b/arch/arm/mach-footbridge/Makefile @@ -14,15 +14,11 @@ pci-$(CONFIG_ARCH_EBSA285_HOST) += ebsa285-pci.o  pci-$(CONFIG_ARCH_NETWINDER) += netwinder-pci.o  pci-$(CONFIG_ARCH_PERSONAL_SERVER) += personal-pci.o -leds-$(CONFIG_ARCH_EBSA285) += ebsa285-leds.o -leds-$(CONFIG_ARCH_NETWINDER) += netwinder-leds.o -  obj-$(CONFIG_ARCH_CATS) += cats-hw.o isa-timer.o  obj-$(CONFIG_ARCH_EBSA285) += ebsa285.o dc21285-timer.o  obj-$(CONFIG_ARCH_NETWINDER) += netwinder-hw.o isa-timer.o  obj-$(CONFIG_ARCH_PERSONAL_SERVER) += personal.o dc21285-timer.o  obj-$(CONFIG_PCI)	+=$(pci-y) -obj-$(CONFIG_LEDS)	+=$(leds-y)  obj-$(CONFIG_ISA)	+= isa.o isa-rtc.o diff --git a/arch/arm/mach-footbridge/ebsa285-leds.c b/arch/arm/mach-footbridge/ebsa285-leds.c deleted file mode 100644 index 5bd266754b9..00000000000 --- a/arch/arm/mach-footbridge/ebsa285-leds.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - *  linux/arch/arm/mach-footbridge/ebsa285-leds.c - * - *  Copyright (C) 1998-1999 Russell King - * - * 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. - * EBSA-285 control routines. - * - * The EBSA-285 uses the leds as follows: - *  - Green - toggles state every 50 timer interrupts - *  - Amber - On if system is not idle - *  - Red   - currently unused - * - * Changelog: - *   02-05-1999	RMK	Various cleanups - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/spinlock.h> - -#include <mach/hardware.h> -#include <asm/leds.h> -#include <asm/mach-types.h> - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 -static char led_state; -static char hw_led_state; - -static DEFINE_SPINLOCK(leds_lock); - -static void ebsa285_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	spin_lock_irqsave(&leds_lock, flags); - -	switch (evt) { -	case led_start: -		hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN; -#ifndef CONFIG_LEDS_CPU -		hw_led_state |= XBUS_LED_AMBER; -#endif -		led_state |= LED_STATE_ENABLED; -		break; - -	case led_stop: -		led_state &= ~LED_STATE_ENABLED; -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state ^= XBUS_LED_GREEN; -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state |= XBUS_LED_AMBER; -		break; - -	case led_idle_end: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state &= ~XBUS_LED_AMBER; -		break; -#endif - -	case led_halted: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state &= ~XBUS_LED_RED; -		break; - -	case led_green_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~XBUS_LED_GREEN; -		break; - -	case led_green_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= XBUS_LED_GREEN; -		break; - -	case led_amber_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~XBUS_LED_AMBER; -		break; - -	case led_amber_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= XBUS_LED_AMBER; -		break; - -	case led_red_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~XBUS_LED_RED; -		break; - -	case led_red_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= XBUS_LED_RED; -		break; - -	default: -		break; -	} - -	if  (led_state & LED_STATE_ENABLED) -		*XBUS_LEDS = hw_led_state; - -	spin_unlock_irqrestore(&leds_lock, flags); -} - -static int __init leds_init(void) -{ -	if (machine_is_ebsa285()) -		leds_event = ebsa285_leds_event; - -	leds_event(led_start); - -	return 0; -} - -__initcall(leds_init); diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c index 27716a7e5fc..b09551ef89c 100644 --- a/arch/arm/mach-footbridge/ebsa285.c +++ b/arch/arm/mach-footbridge/ebsa285.c @@ -5,6 +5,8 @@   */  #include <linux/init.h>  #include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/leds.h>  #include <asm/hardware/dec21285.h>  #include <asm/mach-types.h> @@ -13,6 +15,85 @@  #include "common.h" +/* LEDs */ +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +struct ebsa285_led { +	struct led_classdev     cdev; +	u8                      mask; +}; + +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static const struct { +	const char *name; +	const char *trigger; +} ebsa285_leds[] = { +	{ "ebsa285:amber", "heartbeat", }, +	{ "ebsa285:green", "cpu0", }, +	{ "ebsa285:red",}, +}; + +static void ebsa285_led_set(struct led_classdev *cdev, +		enum led_brightness b) +{ +	struct ebsa285_led *led = container_of(cdev, +			struct ebsa285_led, cdev); + +	if (b != LED_OFF) +		*XBUS_LEDS |= led->mask; +	else +		*XBUS_LEDS &= ~led->mask; +} + +static enum led_brightness ebsa285_led_get(struct led_classdev *cdev) +{ +	struct ebsa285_led *led = container_of(cdev, +			struct ebsa285_led, cdev); + +	return (*XBUS_LEDS & led->mask) ? LED_FULL : LED_OFF; +} + +static int __init ebsa285_leds_init(void) +{ +	int i; + +	if (machine_is_ebsa285()) +		return -ENODEV; + +	/* 3 LEDS All ON */ +	*XBUS_LEDS |= XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED; + +	for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) { +		struct ebsa285_led *led; + +		led = kzalloc(sizeof(*led), GFP_KERNEL); +		if (!led) +			break; + +		led->cdev.name = ebsa285_leds[i].name; +		led->cdev.brightness_set = ebsa285_led_set; +		led->cdev.brightness_get = ebsa285_led_get; +		led->cdev.default_trigger = ebsa285_leds[i].trigger; +		led->mask = BIT(i); + +		if (led_classdev_register(NULL, &led->cdev) < 0) { +			kfree(led); +			break; +		} +	} + +	return 0; +} + +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(ebsa285_leds_init); +#endif +  MACHINE_START(EBSA285, "EBSA285")  	/* Maintainer: Russell King */  	.atag_offset	= 0x100, diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index cac9f67e7da..d2d14339c6c 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c @@ -12,9 +12,10 @@  #include <linux/init.h>  #include <linux/io.h>  #include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/leds.h>  #include <asm/hardware/dec21285.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/setup.h>  #include <asm/system_misc.h> @@ -27,13 +28,6 @@  #define GP1_IO_BASE		0x338  #define GP2_IO_BASE		0x33a - -#ifdef CONFIG_LEDS -#define DEFAULT_LEDS	0 -#else -#define DEFAULT_LEDS	GPIO_GREEN_LED -#endif -  /*   * Winbond WB83977F accessibility stuff   */ @@ -611,15 +605,9 @@ static void __init rwa010_init(void)  static int __init nw_hw_init(void)  {  	if (machine_is_netwinder()) { -		unsigned long flags; -  		wb977_init();  		cpld_init();  		rwa010_init(); - -		raw_spin_lock_irqsave(&nw_gpio_lock, flags); -		nw_gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS); -		raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);  	}  	return 0;  } @@ -672,6 +660,102 @@ static void netwinder_restart(char mode, const char *cmd)  	}  } +/* LEDs */ +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +struct netwinder_led { +	struct led_classdev     cdev; +	u8                      mask; +}; + +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static const struct { +	const char *name; +	const char *trigger; +} netwinder_leds[] = { +	{ "netwinder:green", "heartbeat", }, +	{ "netwinder:red", "cpu0", }, +}; + +/* + * The LED control in Netwinder is reversed: + *  - setting bit means turn off LED + *  - clearing bit means turn on LED + */ +static void netwinder_led_set(struct led_classdev *cdev, +		enum led_brightness b) +{ +	struct netwinder_led *led = container_of(cdev, +			struct netwinder_led, cdev); +	unsigned long flags; +	u32 reg; + +	spin_lock_irqsave(&nw_gpio_lock, flags); +	reg = nw_gpio_read(); +	if (b != LED_OFF) +		reg &= ~led->mask; +	else +		reg |= led->mask; +	nw_gpio_modify_op(led->mask, reg); +	spin_unlock_irqrestore(&nw_gpio_lock, flags); +} + +static enum led_brightness netwinder_led_get(struct led_classdev *cdev) +{ +	struct netwinder_led *led = container_of(cdev, +			struct netwinder_led, cdev); +	unsigned long flags; +	u32 reg; + +	spin_lock_irqsave(&nw_gpio_lock, flags); +	reg = nw_gpio_read(); +	spin_unlock_irqrestore(&nw_gpio_lock, flags); + +	return (reg & led->mask) ? LED_OFF : LED_FULL; +} + +static int __init netwinder_leds_init(void) +{ +	int i; + +	if (!machine_is_netwinder()) +		return -ENODEV; + +	for (i = 0; i < ARRAY_SIZE(netwinder_leds); i++) { +		struct netwinder_led *led; + +		led = kzalloc(sizeof(*led), GFP_KERNEL); +		if (!led) +			break; + +		led->cdev.name = netwinder_leds[i].name; +		led->cdev.brightness_set = netwinder_led_set; +		led->cdev.brightness_get = netwinder_led_get; +		led->cdev.default_trigger = netwinder_leds[i].trigger; + +		if (i == 0) +			led->mask = GPIO_GREEN_LED; +		else +			led->mask = GPIO_RED_LED; + +		if (led_classdev_register(NULL, &led->cdev) < 0) { +			kfree(led); +			break; +		} +	} + +	return 0; +} + +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(netwinder_leds_init); +#endif +  MACHINE_START(NETWINDER, "Rebel-NetWinder")  	/* Maintainer: Russell King/Rebel.com */  	.atag_offset	= 0x100, diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c deleted file mode 100644 index 5a2bd89cbdc..00000000000 --- a/arch/arm/mach-footbridge/netwinder-leds.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - *  linux/arch/arm/mach-footbridge/netwinder-leds.c - * - *  Copyright (C) 1998-1999 Russell King - * - * 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. - * - * NetWinder LED control routines. - * - * The Netwinder uses the leds as follows: - *  - Green - toggles state every 50 timer interrupts - *  - Red   - On if the system is not idle - * - * Changelog: - *   02-05-1999	RMK	Various cleanups - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/spinlock.h> - -#include <mach/hardware.h> -#include <asm/leds.h> -#include <asm/mach-types.h> - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 -static char led_state; -static char hw_led_state; - -static DEFINE_RAW_SPINLOCK(leds_lock); - -static void netwinder_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	raw_spin_lock_irqsave(&leds_lock, flags); - -	switch (evt) { -	case led_start: -		led_state |= LED_STATE_ENABLED; -		hw_led_state = GPIO_GREEN_LED; -		break; - -	case led_stop: -		led_state &= ~LED_STATE_ENABLED; -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state ^= GPIO_GREEN_LED; -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state &= ~GPIO_RED_LED; -		break; - -	case led_idle_end: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state |= GPIO_RED_LED; -		break; -#endif - -	case led_halted: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state |= GPIO_RED_LED; -		break; - -	case led_green_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= GPIO_GREEN_LED; -		break; - -	case led_green_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~GPIO_GREEN_LED; -		break; - -	case led_amber_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= GPIO_GREEN_LED | GPIO_RED_LED; -		break; - -	case led_amber_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~(GPIO_GREEN_LED | GPIO_RED_LED); -		break; - -	case led_red_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= GPIO_RED_LED; -		break; - -	case led_red_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~GPIO_RED_LED; -		break; - -	default: -		break; -	} - -	raw_spin_unlock_irqrestore(&leds_lock, flags); - -	if  (led_state & LED_STATE_ENABLED) { -		raw_spin_lock_irqsave(&nw_gpio_lock, flags); -		nw_gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state); -		raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); -	} -} - -static int __init leds_init(void) -{ -	if (machine_is_netwinder()) -		leds_event = netwinder_leds_event; - -	leds_event(led_start); - -	return 0; -} - -__initcall(leds_init); diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile index ebeef966e1f..5521d18bf19 100644 --- a/arch/arm/mach-integrator/Makefile +++ b/arch/arm/mach-integrator/Makefile @@ -4,11 +4,10 @@  # Object file lists. -obj-y					:= core.o lm.o +obj-y					:= core.o lm.o leds.o  obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+= integrator_ap.o  obj-$(CONFIG_ARCH_INTEGRATOR_CP)	+= integrator_cp.o -obj-$(CONFIG_LEDS)			+= leds.o  obj-$(CONFIG_PCI)			+= pci_v3.o pci.o  obj-$(CONFIG_CPU_FREQ_INTEGRATOR)	+= cpu.o  obj-$(CONFIG_INTEGRATOR_IMPD1)		+= impd1.o diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index ebf680bebdf..208c05d9e68 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -27,7 +27,6 @@  #include <mach/cm.h>  #include <mach/irqs.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/mach/time.h>  #include <asm/pgtable.h> @@ -127,8 +126,6 @@ static struct amba_pl010_data integrator_uart_data = {  	.set_mctrl = integrator_uart_set_mctrl,  }; -#define CM_CTRL	IO_ADDRESS(INTEGRATOR_HDR_CTRL) -  static DEFINE_RAW_SPINLOCK(cm_lock);  /** diff --git a/arch/arm/mach-integrator/include/mach/cm.h b/arch/arm/mach-integrator/include/mach/cm.h index 445d57adb04..1a78692e32a 100644 --- a/arch/arm/mach-integrator/include/mach/cm.h +++ b/arch/arm/mach-integrator/include/mach/cm.h @@ -3,6 +3,8 @@   */  void cm_control(u32, u32); +#define CM_CTRL	IO_ADDRESS(INTEGRATOR_HDR_CTRL) +  #define CM_CTRL_LED			(1 << 0)  #define CM_CTRL_nMBDET			(1 << 1)  #define CM_CTRL_REMAP			(1 << 2) diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c index 466defa9784..7a7f6d3273b 100644 --- a/arch/arm/mach-integrator/leds.c +++ b/arch/arm/mach-integrator/leds.c @@ -1,90 +1,125 @@  /* - *  linux/arch/arm/mach-integrator/leds.c + * Driver for the 4 user LEDs found on the Integrator AP/CP baseboard + * Based on Versatile and RealView machine LED code   * - *  Integrator/AP and Integrator/CP LED control routines - * - *  Copyright (C) 1999 ARM Limited - *  Copyright (C) 2000 Deep Blue Solutions Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * License terms: GNU General Public License (GPL) version 2 + * Author: Bryan Wu <bryan.wu@canonical.com>   */  #include <linux/kernel.h>  #include <linux/init.h> -#include <linux/smp.h> -#include <linux/spinlock.h>  #include <linux/io.h> +#include <linux/slab.h> +#include <linux/leds.h> +#include <mach/cm.h>  #include <mach/hardware.h>  #include <mach/platform.h> -#include <asm/leds.h> -#include <asm/mach-types.h> -#include <mach/cm.h> -static int saved_leds; +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) + +#define ALPHA_REG __io_address(INTEGRATOR_DBG_BASE) +#define LEDREG	(__io_address(INTEGRATOR_DBG_BASE) + INTEGRATOR_DBG_LEDS_OFFSET) -static void integrator_leds_event(led_event_t ledevt) +struct integrator_led { +	struct led_classdev	cdev; +	u8			mask; +}; + +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static const struct { +	const char *name; +	const char *trigger; +} integrator_leds[] = { +	{ "integrator:green0", "heartbeat", }, +	{ "integrator:yellow", }, +	{ "integrator:red", }, +	{ "integrator:green1", }, +	{ "integrator:core_module", "cpu0", }, +}; + +static void integrator_led_set(struct led_classdev *cdev, +			      enum led_brightness b)  { -	unsigned long flags; -	const unsigned int dbg_base = IO_ADDRESS(INTEGRATOR_DBG_BASE); -	unsigned int update_alpha_leds; +	struct integrator_led *led = container_of(cdev, +						 struct integrator_led, cdev); +	u32 reg = __raw_readl(LEDREG); -	// yup, change the LEDs -	local_irq_save(flags); -	update_alpha_leds = 0; +	if (b != LED_OFF) +		reg |= led->mask; +	else +		reg &= ~led->mask; -	switch(ledevt) { -	case led_idle_start: -		cm_control(CM_CTRL_LED, 0); -		break; +	while (__raw_readl(ALPHA_REG) & 1) +		cpu_relax(); -	case led_idle_end: -		cm_control(CM_CTRL_LED, CM_CTRL_LED); -		break; +	__raw_writel(reg, LEDREG); +} -	case led_timer: -		saved_leds ^= GREEN_LED; -		update_alpha_leds = 1; -		break; +static enum led_brightness integrator_led_get(struct led_classdev *cdev) +{ +	struct integrator_led *led = container_of(cdev, +						 struct integrator_led, cdev); +	u32 reg = __raw_readl(LEDREG); -	case led_red_on: -		saved_leds |= RED_LED; -		update_alpha_leds = 1; -		break; +	return (reg & led->mask) ? LED_FULL : LED_OFF; +} -	case led_red_off: -		saved_leds &= ~RED_LED; -		update_alpha_leds = 1; -		break; +static void cm_led_set(struct led_classdev *cdev, +			      enum led_brightness b) +{ +	if (b != LED_OFF) +		cm_control(CM_CTRL_LED, CM_CTRL_LED); +	else +		cm_control(CM_CTRL_LED, 0); +} -	default: -		break; -	} +static enum led_brightness cm_led_get(struct led_classdev *cdev) +{ +	u32 reg = readl(CM_CTRL); -	if (update_alpha_leds) { -		while (__raw_readl(dbg_base + INTEGRATOR_DBG_ALPHA_OFFSET) & 1); -		__raw_writel(saved_leds, dbg_base + INTEGRATOR_DBG_LEDS_OFFSET); -	} -	local_irq_restore(flags); +	return (reg & CM_CTRL_LED) ? LED_FULL : LED_OFF;  } -static int __init leds_init(void) +static int __init integrator_leds_init(void)  { -	if (machine_is_integrator() || machine_is_cintegrator()) -		leds_event = integrator_leds_event; +	int i; + +	for (i = 0; i < ARRAY_SIZE(integrator_leds); i++) { +		struct integrator_led *led; + +		led = kzalloc(sizeof(*led), GFP_KERNEL); +		if (!led) +			break; + + +		led->cdev.name = integrator_leds[i].name; + +		if (i == 4) { /* Setting for LED in core module */ +			led->cdev.brightness_set = cm_led_set; +			led->cdev.brightness_get = cm_led_get; +		} else { +			led->cdev.brightness_set = integrator_led_set; +			led->cdev.brightness_get = integrator_led_get; +		} + +		led->cdev.default_trigger = integrator_leds[i].trigger; +		led->mask = BIT(i); + +		if (led_classdev_register(NULL, &led->cdev) < 0) { +			kfree(led); +			break; +		} +	}  	return 0;  } -core_initcall(leds_init); +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(integrator_leds_init); +#endif diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile index 853efd9133c..9324ef965c2 100644 --- a/arch/arm/mach-ks8695/Makefile +++ b/arch/arm/mach-ks8695/Makefile @@ -11,9 +11,6 @@ obj-				:=  # PCI support is optional  obj-$(CONFIG_PCI)		+= pci.o -# LEDs -obj-$(CONFIG_LEDS)		+= leds.o -  # Board-specific support  obj-$(CONFIG_MACH_KS8695)	+= board-micrel.o  obj-$(CONFIG_MACH_DSM320)	+= board-dsm320.o diff --git a/arch/arm/mach-ks8695/devices.c b/arch/arm/mach-ks8695/devices.c index 73bd6381287..47399bc3c02 100644 --- a/arch/arm/mach-ks8695/devices.c +++ b/arch/arm/mach-ks8695/devices.c @@ -182,27 +182,6 @@ static void __init ks8695_add_device_watchdog(void)  } -/* -------------------------------------------------------------------- - *  LEDs - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_LEDS) -short ks8695_leds_cpu = -1; -short ks8695_leds_timer = -1; - -void __init ks8695_init_leds(u8 cpu_led, u8 timer_led) -{ -	/* Enable GPIO to access the LEDs */ -	gpio_direction_output(cpu_led, 1); -	gpio_direction_output(timer_led, 1); - -	ks8695_leds_cpu	  = cpu_led; -	ks8695_leds_timer = timer_led; -} -#else -void __init ks8695_init_leds(u8 cpu_led, u8 timer_led) {} -#endif -  /* -------------------------------------------------------------------- */  /* diff --git a/arch/arm/mach-ks8695/include/mach/devices.h b/arch/arm/mach-ks8695/include/mach/devices.h index 85a3c9aa7d1..1e6594a0f29 100644 --- a/arch/arm/mach-ks8695/include/mach/devices.h +++ b/arch/arm/mach-ks8695/include/mach/devices.h @@ -18,11 +18,6 @@ extern void __init ks8695_add_device_wan(void);  extern void __init ks8695_add_device_lan(void);  extern void __init ks8695_add_device_hpna(void); - /* LEDs */ -extern short ks8695_leds_cpu; -extern short ks8695_leds_timer; -extern void __init ks8695_init_leds(u8 cpu_led, u8 timer_led); -   /* PCI */  #define KS8695_MODE_PCI		0  #define KS8695_MODE_MINIPCI	1 diff --git a/arch/arm/mach-ks8695/leds.c b/arch/arm/mach-ks8695/leds.c deleted file mode 100644 index 4bd70754729..00000000000 --- a/arch/arm/mach-ks8695/leds.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * LED driver for KS8695-based boards. - * - * Copyright (C) Andrew Victor - * - * 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/gpio.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> - -#include <asm/leds.h> -#include <mach/devices.h> - - -static inline void ks8695_led_on(unsigned int led) -{ -	gpio_set_value(led, 0); -} - -static inline void ks8695_led_off(unsigned int led) -{ -	gpio_set_value(led, 1); -} - -static inline void ks8695_led_toggle(unsigned int led) -{ -	unsigned long is_off = gpio_get_value(led); -	if (is_off) -		ks8695_led_on(led); -	else -		ks8695_led_off(led); -} - - -/* - * Handle LED events. - */ -static void ks8695_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	switch(evt) { -	case led_start:		/* System startup */ -		ks8695_led_on(ks8695_leds_cpu); -		break; - -	case led_stop:		/* System stop / suspend */ -		ks8695_led_off(ks8695_leds_cpu); -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer:		/* Every 50 timer ticks */ -		ks8695_led_toggle(ks8695_leds_timer); -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start:	/* Entering idle state */ -		ks8695_led_off(ks8695_leds_cpu); -		break; - -	case led_idle_end:	/* Exit idle state */ -		ks8695_led_on(ks8695_leds_cpu); -		break; -#endif - -	default: -		break; -	} - -	local_irq_restore(flags); -} - - -static int __init leds_init(void) -{ -	if ((ks8695_leds_timer == -1) || (ks8695_leds_cpu == -1)) -		return -ENODEV; - -	leds_event = ks8695_leds_event; - -	leds_event(led_start); -	return 0; -} - -__initcall(leds_init); diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 398e9e53e18..cd169c38616 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -61,14 +61,6 @@ obj-$(CONFIG_ARCH_OMAP850)		+= gpio7xx.o  obj-$(CONFIG_ARCH_OMAP15XX)		+= gpio15xx.o  obj-$(CONFIG_ARCH_OMAP16XX)		+= gpio16xx.o -# LEDs support -led-$(CONFIG_MACH_OMAP_H2)		+= leds-h2p2-debug.o -led-$(CONFIG_MACH_OMAP_H3)		+= leds-h2p2-debug.o -led-$(CONFIG_MACH_OMAP_INNOVATOR)	+= leds-innovator.o -led-$(CONFIG_MACH_OMAP_PERSEUS2)	+= leds-h2p2-debug.o -led-$(CONFIG_MACH_OMAP_OSK)		+= leds-osk.o -obj-$(CONFIG_LEDS)			+= $(led-y) -  ifneq ($(CONFIG_FB_OMAP),)  obj-y += lcd_dma.o  endif diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 44a4ab195fb..cd8836f43f0 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -31,6 +31,7 @@  #include <linux/i2c/tps65010.h>  #include <linux/smc91x.h>  #include <linux/omapfb.h> +#include <linux/leds.h>  #include <asm/mach-types.h>  #include <asm/mach/arch.h> @@ -306,12 +307,39 @@ static struct platform_device h2_irda_device = {  	.resource	= h2_irda_resources,  }; +static struct gpio_led h2_gpio_led_pins[] = { +	{ +		.name		= "h2:red", +		.default_trigger = "heartbeat", +		.gpio		= 3, +	}, +	{ +		.name		= "h2:green", +		.default_trigger = "cpu0", +		.gpio		= OMAP_MPUIO(4), +	}, +}; + +static struct gpio_led_platform_data h2_gpio_led_data = { +	.leds		= h2_gpio_led_pins, +	.num_leds	= ARRAY_SIZE(h2_gpio_led_pins), +}; + +static struct platform_device h2_gpio_leds = { +	.name	= "leds-gpio", +	.id	= -1, +	.dev	= { +		.platform_data = &h2_gpio_led_data, +	}, +}; +  static struct platform_device *h2_devices[] __initdata = {  	&h2_nor_device,  	&h2_nand_device,  	&h2_smc91x_device,  	&h2_irda_device,  	&h2_kp_device, +	&h2_gpio_leds,  };  static void __init h2_init_smc91x(void) @@ -406,6 +434,10 @@ static void __init h2_init(void)  	omap_cfg_reg(E19_1610_KBR4);  	omap_cfg_reg(N19_1610_KBR5); +	/* GPIO based LEDs */ +	omap_cfg_reg(P18_1610_GPIO3); +	omap_cfg_reg(MPUIO4); +  	h2_smc91x_resources[1].start = gpio_to_irq(0);  	h2_smc91x_resources[1].end = gpio_to_irq(0);  	platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 86cb5a04a40..1fa9c45c1ae 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -31,6 +31,7 @@  #include <linux/i2c/tps65010.h>  #include <linux/smc91x.h>  #include <linux/omapfb.h> +#include <linux/leds.h>  #include <asm/setup.h>  #include <asm/page.h> @@ -324,6 +325,32 @@ static struct spi_board_info h3_spi_board_info[] __initdata = {  	},  }; +static struct gpio_led h3_gpio_led_pins[] = { +	{ +		.name		= "h3:red", +		.default_trigger = "heartbeat", +		.gpio		= 3, +	}, +	{ +		.name		= "h3:green", +		.default_trigger = "cpu0", +		.gpio		= OMAP_MPUIO(4), +	}, +}; + +static struct gpio_led_platform_data h3_gpio_led_data = { +	.leds		= h3_gpio_led_pins, +	.num_leds	= ARRAY_SIZE(h3_gpio_led_pins), +}; + +static struct platform_device h3_gpio_leds = { +	.name	= "leds-gpio", +	.id	= -1, +	.dev	= { +		.platform_data = &h3_gpio_led_data, +	}, +}; +  static struct platform_device *devices[] __initdata = {  	&nor_device,  	&nand_device, @@ -331,6 +358,7 @@ static struct platform_device *devices[] __initdata = {  	&intlat_device,  	&h3_kp_device,  	&h3_lcd_device, +	&h3_gpio_leds,  };  static struct omap_usb_config h3_usb_config __initdata = { @@ -398,6 +426,10 @@ static void __init h3_init(void)  	omap_cfg_reg(E19_1610_KBR4);  	omap_cfg_reg(N19_1610_KBR5); +	/* GPIO based LEDs */ +	omap_cfg_reg(P18_1610_GPIO3); +	omap_cfg_reg(MPUIO4); +  	smc91x_resources[1].start = gpio_to_irq(40);  	smc91x_resources[1].end = gpio_to_irq(40);  	platform_add_devices(devices, ARRAY_SIZE(devices)); diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 8784705edb6..7ee1c1eac35 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -380,10 +380,37 @@ static struct platform_device osk5912_lcd_device = {  	.id		= -1,  }; +static struct gpio_led mistral_gpio_led_pins[] = { +	{ +		.name		= "mistral:red", +		.default_trigger = "heartbeat", +		.gpio		= 3, +	}, +	{ +		.name		= "mistral:green", +		.default_trigger = "cpu0", +		.gpio		= OMAP_MPUIO(4), +	}, +}; + +static struct gpio_led_platform_data mistral_gpio_led_data = { +	.leds		= mistral_gpio_led_pins, +	.num_leds	= ARRAY_SIZE(mistral_gpio_led_pins), +}; + +static struct platform_device mistral_gpio_leds = { +	.name	= "leds-gpio", +	.id	= -1, +	.dev	= { +		.platform_data = &mistral_gpio_led_data, +	}, +}; +  static struct platform_device *mistral_devices[] __initdata = {  	&osk5912_kp_device,  	&mistral_bl_device,  	&osk5912_lcd_device, +	&mistral_gpio_leds,  };  static int mistral_get_pendown_state(void) @@ -508,6 +535,12 @@ static void __init osk_mistral_init(void)  	if (gpio_request(2, "lcd_pwr") == 0)  		gpio_direction_output(2, 1); +	/* +	 * GPIO based LEDs +	 */ +	omap_cfg_reg(P18_1610_GPIO3); +	omap_cfg_reg(MPUIO4); +  	i2c_register_board_info(1, mistral_i2c_board_info,  			ARRAY_SIZE(mistral_i2c_board_info)); diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c deleted file mode 100644 index f6b14a14a95..00000000000 --- a/arch/arm/mach-omap1/leds-h2p2-debug.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * linux/arch/arm/mach-omap1/leds-h2p2-debug.c - * - * Copyright 2003 by Texas Instruments Incorporated - * - * There are 16 LEDs on the debug board (all green); four may be used - * for logical 'green', 'amber', 'red', and 'blue' (after "claiming"). - * - * The "surfer" expansion board and H2 sample board also have two-color - * green+red LEDs (in parallel), used here for timer and idle indicators. - */ -#include <linux/gpio.h> -#include <linux/init.h> -#include <linux/kernel_stat.h> -#include <linux/sched.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <asm/leds.h> -#include <asm/mach-types.h> - -#include <plat/fpga.h> - -#include "leds.h" - - -#define GPIO_LED_RED		3 -#define GPIO_LED_GREEN		OMAP_MPUIO(4) - - -#define LED_STATE_ENABLED	0x01 -#define LED_STATE_CLAIMED	0x02 -#define LED_TIMER_ON		0x04 - -#define GPIO_IDLE		GPIO_LED_GREEN -#define GPIO_TIMER		GPIO_LED_RED - - -void h2p2_dbg_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	static struct h2p2_dbg_fpga __iomem *fpga; -	static u16 led_state, hw_led_state; - -	local_irq_save(flags); - -	if (!(led_state & LED_STATE_ENABLED) && evt != led_start) -		goto done; - -	switch (evt) { -	case led_start: -		if (!fpga) -			fpga = ioremap(H2P2_DBG_FPGA_START, -						H2P2_DBG_FPGA_SIZE); -		if (fpga) { -			led_state |= LED_STATE_ENABLED; -			__raw_writew(~0, &fpga->leds); -		} -		break; - -	case led_stop: -	case led_halted: -		/* all leds off during suspend or shutdown */ - -		if (! machine_is_omap_perseus2()) { -			gpio_set_value(GPIO_TIMER, 0); -			gpio_set_value(GPIO_IDLE, 0); -		} - -		__raw_writew(~0, &fpga->leds); -		led_state &= ~LED_STATE_ENABLED; -		if (evt == led_halted) { -			iounmap(fpga); -			fpga = NULL; -		} - -		goto done; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		led_state ^= LED_TIMER_ON; - -		if (machine_is_omap_perseus2()) -			hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; -		else { -			gpio_set_value(GPIO_TIMER, led_state & LED_TIMER_ON); -			goto done; -		} - -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		if (machine_is_omap_perseus2()) -			hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; -		else { -			gpio_set_value(GPIO_IDLE, 1); -			goto done; -		} - -		break; - -	case led_idle_end: -		if (machine_is_omap_perseus2()) -			hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; -		else { -			gpio_set_value(GPIO_IDLE, 0); -			goto done; -		} - -		break; -#endif - -	case led_green_on: -		hw_led_state |= H2P2_DBG_FPGA_LED_GREEN; -		break; -	case led_green_off: -		hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN; -		break; - -	case led_amber_on: -		hw_led_state |= H2P2_DBG_FPGA_LED_AMBER; -		break; -	case led_amber_off: -		hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER; -		break; - -	case led_red_on: -		hw_led_state |= H2P2_DBG_FPGA_LED_RED; -		break; -	case led_red_off: -		hw_led_state &= ~H2P2_DBG_FPGA_LED_RED; -		break; - -	case led_blue_on: -		hw_led_state |= H2P2_DBG_FPGA_LED_BLUE; -		break; -	case led_blue_off: -		hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE; -		break; - -	default: -		break; -	} - - -	/* -	 *  Actually burn the LEDs -	 */ -	if (led_state & LED_STATE_ENABLED) -		__raw_writew(~hw_led_state, &fpga->leds); - -done: -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-omap1/leds-innovator.c b/arch/arm/mach-omap1/leds-innovator.c deleted file mode 100644 index 3a066ee8d02..00000000000 --- a/arch/arm/mach-omap1/leds-innovator.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * linux/arch/arm/mach-omap1/leds-innovator.c - */ -#include <linux/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> - -#include "leds.h" - - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -void innovator_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	switch (evt) { -	case led_start: -		hw_led_state = 0; -		led_state = LED_STATE_ENABLED; -		break; - -	case led_stop: -		led_state &= ~LED_STATE_ENABLED; -		hw_led_state = 0; -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state ^= 0; -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state |= 0; -		break; - -	case led_idle_end: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state &= ~0; -		break; -#endif - -	case led_halted: -		break; - -	case led_green_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~0; -		break; - -	case led_green_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= 0; -		break; - -	case led_amber_on: -		break; - -	case led_amber_off: -		break; - -	case led_red_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~0; -		break; - -	case led_red_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= 0; -		break; - -	default: -		break; -	} - -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c deleted file mode 100644 index 936ed426b84..00000000000 --- a/arch/arm/mach-omap1/leds-osk.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * linux/arch/arm/mach-omap1/leds-osk.c - * - * LED driver for OSK with optional Mistral QVGA board - */ -#include <linux/gpio.h> -#include <linux/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> - -#include "leds.h" - - -#define LED_STATE_ENABLED	(1 << 0) -#define LED_STATE_CLAIMED	(1 << 1) -static u8 led_state; - -#define	TIMER_LED		(1 << 3)	/* Mistral board */ -#define	IDLE_LED		(1 << 4)	/* Mistral board */ -static u8 hw_led_state; - - -#ifdef	CONFIG_OMAP_OSK_MISTRAL - -/* For now, all system indicators require the Mistral board, since that - * LED can be manipulated without a task context.  This LED is either red, - * or green, but not both; it can't give the full "disco led" effect. - */ - -#define GPIO_LED_RED		3 -#define GPIO_LED_GREEN		OMAP_MPUIO(4) - -static void mistral_setled(void) -{ -	int	red = 0; -	int	green = 0; - -	if (hw_led_state & TIMER_LED) -		red = 1; -	else if (hw_led_state & IDLE_LED) -		green = 1; -	/* else both sides are disabled */ - -	gpio_set_value(GPIO_LED_GREEN, green); -	gpio_set_value(GPIO_LED_RED, red); -} - -#endif - -void osk_leds_event(led_event_t evt) -{ -	unsigned long	flags; -	u16		leds; - -	local_irq_save(flags); - -	if (!(led_state & LED_STATE_ENABLED) && evt != led_start) -		goto done; - -	leds = hw_led_state; -	switch (evt) { -	case led_start: -		led_state |= LED_STATE_ENABLED; -		hw_led_state = 0; -		leds = ~0; -		break; - -	case led_halted: -	case led_stop: -		led_state &= ~LED_STATE_ENABLED; -		hw_led_state = 0; -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = 0; -		leds = ~0; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -#ifdef	CONFIG_OMAP_OSK_MISTRAL - -	case led_timer: -		hw_led_state ^= TIMER_LED; -		mistral_setled(); -		break; - -	case led_idle_start:	/* idle == off */ -		hw_led_state &= ~IDLE_LED; -		mistral_setled(); -		break; - -	case led_idle_end: -		hw_led_state |= IDLE_LED; -		mistral_setled(); -		break; - -#endif	/* CONFIG_OMAP_OSK_MISTRAL */ - -	default: -		break; -	} - -	leds ^= hw_led_state; - -done: -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c deleted file mode 100644 index ae6dd93b8dd..00000000000 --- a/arch/arm/mach-omap1/leds.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * linux/arch/arm/mach-omap1/leds.c - * - * OMAP LEDs dispatcher - */ -#include <linux/gpio.h> -#include <linux/kernel.h> -#include <linux/init.h> - -#include <asm/leds.h> -#include <asm/mach-types.h> - -#include <plat/mux.h> - -#include "leds.h" - -static int __init -omap_leds_init(void) -{ -	if (!cpu_class_is_omap1()) -		return -ENODEV; - -	if (machine_is_omap_innovator()) -		leds_event = innovator_leds_event; - -	else if (machine_is_omap_h2() -			|| machine_is_omap_h3() -			|| machine_is_omap_perseus2()) -		leds_event = h2p2_dbg_leds_event; - -	else if (machine_is_omap_osk()) -		leds_event = osk_leds_event; - -	else -		return -1; - -	if (machine_is_omap_h2() -			|| machine_is_omap_h3() -#ifdef	CONFIG_OMAP_OSK_MISTRAL -			|| machine_is_omap_osk() -#endif -			) { - -		/* LED1/LED2 pins can be used as GPIO (as done here), or by -		 * the LPG (works even in deep sleep!), to drive a bicolor -		 * LED on the H2 sample board, and another on the H2/P2 -		 * "surfer" expansion board. -		 * -		 * The same pins drive a LED on the OSK Mistral board, but -		 * that's a different kind of LED (just one color at a time). -		 */ -		omap_cfg_reg(P18_1610_GPIO3); -		if (gpio_request(3, "LED red") == 0) -			gpio_direction_output(3, 1); -		else -			printk(KERN_WARNING "LED: can't get GPIO3/red?\n"); - -		omap_cfg_reg(MPUIO4); -		if (gpio_request(OMAP_MPUIO(4), "LED green") == 0) -			gpio_direction_output(OMAP_MPUIO(4), 1); -		else -			printk(KERN_WARNING "LED: can't get MPUIO4/green?\n"); -	} - -	leds_event(led_start); -	return 0; -} - -__initcall(omap_leds_init); diff --git a/arch/arm/mach-omap1/leds.h b/arch/arm/mach-omap1/leds.h deleted file mode 100644 index a1e9fedc376..00000000000 --- a/arch/arm/mach-omap1/leds.h +++ /dev/null @@ -1,3 +0,0 @@ -extern void innovator_leds_event(led_event_t evt); -extern void h2p2_dbg_leds_event(led_event_t evt); -extern void osk_leds_event(led_event_t evt); diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 4062480bfec..4d4816fd6fc 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -44,7 +44,6 @@  #include <linux/clockchips.h>  #include <linux/io.h> -#include <asm/leds.h>  #include <asm/irq.h>  #include <asm/sched_clock.h> diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c index eae49c3980c..74529549130 100644 --- a/arch/arm/mach-omap1/timer32k.c +++ b/arch/arm/mach-omap1/timer32k.c @@ -46,7 +46,6 @@  #include <linux/clockchips.h>  #include <linux/io.h> -#include <asm/leds.h>  #include <asm/irq.h>  #include <asm/mach/irq.h>  #include <asm/mach/time.h> diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c index 78a6a11d821..9b1c9531029 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c @@ -18,7 +18,6 @@  #include <linux/ethtool.h>  #include <net/dsa.h>  #include <asm/mach-types.h> -#include <asm/leds.h>  #include <asm/mach/arch.h>  #include <asm/mach/pci.h>  #include <mach/orion5x.h> diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c index 2f5dc54cd4c..51ba2b81a10 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c @@ -19,7 +19,6 @@  #include <linux/i2c.h>  #include <net/dsa.h>  #include <asm/mach-types.h> -#include <asm/leds.h>  #include <asm/mach/arch.h>  #include <asm/mach/pci.h>  #include <mach/orion5x.h> diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c index 399130fac0b..0a56b9444f1 100644 --- a/arch/arm/mach-orion5x/rd88f5182-setup.c +++ b/arch/arm/mach-orion5x/rd88f5182-setup.c @@ -19,8 +19,8 @@  #include <linux/mv643xx_eth.h>  #include <linux/ata_platform.h>  #include <linux/i2c.h> +#include <linux/leds.h>  #include <asm/mach-types.h> -#include <asm/leds.h>  #include <asm/mach/arch.h>  #include <asm/mach/pci.h>  #include <mach/orion5x.h> @@ -53,12 +53,6 @@  #define RD88F5182_PCI_SLOT0_IRQ_A_PIN	7  #define RD88F5182_PCI_SLOT0_IRQ_B_PIN	6 -/* - * GPIO Debug LED - */ - -#define RD88F5182_GPIO_DBG_LED		0 -  /*****************************************************************************   * 16M NOR Flash on Device bus CS1   ****************************************************************************/ @@ -83,55 +77,32 @@ static struct platform_device rd88f5182_nor_flash = {  	.resource		= &rd88f5182_nor_flash_resource,  }; -#ifdef CONFIG_LEDS -  /***************************************************************************** - * Use GPIO debug led as CPU active indication + * Use GPIO LED as CPU active indication   ****************************************************************************/ -static void rd88f5182_dbgled_event(led_event_t evt) -{ -	int val; - -	if (evt == led_idle_end) -		val = 1; -	else if (evt == led_idle_start) -		val = 0; -	else -		return; - -	gpio_set_value(RD88F5182_GPIO_DBG_LED, val); -} - -static int __init rd88f5182_dbgled_init(void) -{ -	int pin; - -	if (machine_is_rd88f5182()) { -		pin = RD88F5182_GPIO_DBG_LED; +#define RD88F5182_GPIO_LED		0 -		if (gpio_request(pin, "DBGLED") == 0) { -			if (gpio_direction_output(pin, 0) != 0) { -				printk(KERN_ERR "rd88f5182_dbgled_init failed " -						"to set output pin %d\n", pin); -				gpio_free(pin); -				return 0; -			} -		} else { -			printk(KERN_ERR "rd88f5182_dbgled_init failed " -					"to request gpio %d\n", pin); -			return 0; -		} - -		leds_event = rd88f5182_dbgled_event; -	} - -	return 0; -} +static struct gpio_led rd88f5182_gpio_led_pins[] = { +	{ +		.name		= "rd88f5182:cpu", +		.default_trigger = "cpu0", +		.gpio		= RD88F5182_GPIO_LED, +	}, +}; -__initcall(rd88f5182_dbgled_init); +static struct gpio_led_platform_data rd88f5182_gpio_led_data = { +	.leds		= rd88f5182_gpio_led_pins, +	.num_leds	= ARRAY_SIZE(rd88f5182_gpio_led_pins), +}; -#endif +static struct platform_device rd88f5182_gpio_leds = { +	.name	= "leds-gpio", +	.id	= -1, +	.dev	= { +		.platform_data = &rd88f5182_gpio_led_data, +	}, +};  /*****************************************************************************   * PCI @@ -298,6 +269,7 @@ static void __init rd88f5182_init(void)  	orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);  	platform_device_register(&rd88f5182_nor_flash); +	platform_device_register(&rd88f5182_gpio_leds);  	i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);  } diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c index 92df49c1b62..ed50910b08a 100644 --- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c @@ -20,7 +20,6 @@  #include <linux/ethtool.h>  #include <net/dsa.h>  #include <asm/mach-types.h> -#include <asm/leds.h>  #include <asm/mach/arch.h>  #include <asm/mach/pci.h>  #include <mach/orion5x.h> diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c index 0cfe8af3d3b..47a7ae96156 100644 --- a/arch/arm/mach-pnx4008/time.c +++ b/arch/arm/mach-pnx4008/time.c @@ -25,7 +25,6 @@  #include <linux/io.h>  #include <mach/hardware.h> -#include <asm/leds.h>  #include <asm/mach/time.h>  #include <asm/errno.h> diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index be0f7df8685..d4337e300ad 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -95,12 +95,4 @@ obj-$(CONFIG_MACH_RAUMFELD_CONNECTOR)	+= raumfeld.o  obj-$(CONFIG_MACH_RAUMFELD_SPEAKER)	+= raumfeld.o  obj-$(CONFIG_MACH_ZIPIT2)	+= z2.o -# Support for blinky lights -led-y := leds.o -led-$(CONFIG_ARCH_LUBBOCK)	+= leds-lubbock.o -led-$(CONFIG_MACH_MAINSTONE)	+= leds-mainstone.o -led-$(CONFIG_ARCH_PXA_IDP)	+= leds-idp.o - -obj-$(CONFIG_LEDS)		+= $(led-y) -  obj-$(CONFIG_TOSA_BT)		+= tosa-bt.o diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index 6ff466bd43e..ae1e9977603 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -191,6 +191,87 @@ static void __init idp_map_io(void)  	iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));  } +/* LEDs */ +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +struct idp_led { +	struct led_classdev     cdev; +	u8                      mask; +}; + +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static const struct { +	const char *name; +	const char *trigger; +} idp_leds[] = { +	{ "idp:green", "heartbeat", }, +	{ "idp:red", "cpu0", }, +}; + +static void idp_led_set(struct led_classdev *cdev, +		enum led_brightness b) +{ +	struct idp_led *led = container_of(cdev, +			struct idp_led, cdev); +	u32 reg = IDP_CPLD_LED_CONTROL; + +	if (b != LED_OFF) +		reg &= ~led->mask; +	else +		reg |= led->mask; + +	IDP_CPLD_LED_CONTROL = reg; +} + +static enum led_brightness idp_led_get(struct led_classdev *cdev) +{ +	struct idp_led *led = container_of(cdev, +			struct idp_led, cdev); + +	return (IDP_CPLD_LED_CONTROL & led->mask) ? LED_OFF : LED_FULL; +} + +static int __init idp_leds_init(void) +{ +	int i; + +	if (!machine_is_pxa_idp()) +		return -ENODEV; + +	for (i = 0; i < ARRAY_SIZE(idp_leds); i++) { +		struct idp_led *led; + +		led = kzalloc(sizeof(*led), GFP_KERNEL); +		if (!led) +			break; + +		led->cdev.name = idp_leds[i].name; +		led->cdev.brightness_set = idp_led_set; +		led->cdev.brightness_get = idp_led_get; +		led->cdev.default_trigger = idp_leds[i].trigger; + +		if (i == 0) +			led->mask = IDP_HB_LED; +		else +			led->mask = IDP_BUSY_LED; + +		if (led_classdev_register(NULL, &led->cdev) < 0) { +			kfree(led); +			break; +		} +	} + +	return 0; +} + +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(idp_leds_init); +#endif  MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")  	/* Maintainer: Vibren Technologies */ diff --git a/arch/arm/mach-pxa/leds-idp.c b/arch/arm/mach-pxa/leds-idp.c deleted file mode 100644 index 06b060025d1..00000000000 --- a/arch/arm/mach-pxa/leds-idp.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/leds-idp.c - * - * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu> - * - * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com> - * - * Original (leds-footbridge.c) by Russell King - * - * Macros for actual LED manipulation should be in machine specific - * files in this 'mach' directory. - */ - - -#include <linux/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> - -#include <mach/pxa25x.h> -#include <mach/idp.h> - -#include "leds.h" - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -void idp_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	switch (evt) { -	case led_start: -		hw_led_state = IDP_HB_LED | IDP_BUSY_LED; -		led_state = LED_STATE_ENABLED; -		break; - -	case led_stop: -		led_state &= ~LED_STATE_ENABLED; -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = IDP_HB_LED | IDP_BUSY_LED; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = IDP_HB_LED | IDP_BUSY_LED; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state ^= IDP_HB_LED; -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state &= ~IDP_BUSY_LED; -		break; - -	case led_idle_end: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state |= IDP_BUSY_LED; -		break; -#endif - -	case led_halted: -		break; - -	case led_green_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= IDP_HB_LED; -		break; - -	case led_green_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~IDP_HB_LED; -		break; - -	case led_amber_on: -		break; - -	case led_amber_off: -		break; - -	case led_red_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= IDP_BUSY_LED; -		break; - -	case led_red_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~IDP_BUSY_LED; -		break; - -	default: -		break; -	} - -	if  (led_state & LED_STATE_ENABLED) -		IDP_CPLD_LED_CONTROL = ( (IDP_CPLD_LED_CONTROL | IDP_LEDS_MASK) & ~hw_led_state); -	else -		IDP_CPLD_LED_CONTROL |= IDP_LEDS_MASK; - -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-pxa/leds-lubbock.c b/arch/arm/mach-pxa/leds-lubbock.c deleted file mode 100644 index 0bd85c884a7..00000000000 --- a/arch/arm/mach-pxa/leds-lubbock.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/leds-lubbock.c - * - * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu> - * - * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com> - * - * Original (leds-footbridge.c) by Russell King - * - * Major surgery on April 2004 by Nicolas Pitre for less global - * namespace collision.  Mostly adapted the Mainstone version. - */ - -#include <linux/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> -#include <mach/pxa25x.h> -#include <mach/lubbock.h> - -#include "leds.h" - -/* - * 8 discrete leds available for general use: - * - * Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays - * so be sure to not monkey with them here. - */ - -#define D28			(1 << 0) -#define D27			(1 << 1) -#define D26			(1 << 2) -#define D25			(1 << 3) -#define D24			(1 << 4) -#define D23			(1 << 5) -#define D22			(1 << 6) -#define D21			(1 << 7) - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -void lubbock_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	switch (evt) { -	case led_start: -		hw_led_state = 0; -		led_state = LED_STATE_ENABLED; -		break; - -	case led_stop: -		led_state &= ~LED_STATE_ENABLED; -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		hw_led_state ^= D26; -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		hw_led_state &= ~D27; -		break; - -	case led_idle_end: -		hw_led_state |= D27; -		break; -#endif - -	case led_halted: -		break; - -	case led_green_on: -		hw_led_state |= D21; -		break; - -	case led_green_off: -		hw_led_state &= ~D21; -		break; - -	case led_amber_on: -		hw_led_state |= D22; -		break; - -	case led_amber_off: -		hw_led_state &= ~D22; -		break; - -	case led_red_on: -		hw_led_state |= D23; -		break; - -	case led_red_off: -		hw_led_state &= ~D23; -		break; - -	default: -		break; -	} - -	if  (led_state & LED_STATE_ENABLED) -		LUB_DISC_BLNK_LED = (LUB_DISC_BLNK_LED | 0xff) & ~hw_led_state; -	else -		LUB_DISC_BLNK_LED |= 0xff; - -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-pxa/leds-mainstone.c b/arch/arm/mach-pxa/leds-mainstone.c deleted file mode 100644 index 4058ab340fe..00000000000 --- a/arch/arm/mach-pxa/leds-mainstone.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/leds-mainstone.c - * - * Author:     Nicolas Pitre - * Created:    Nov 05, 2002 - * Copyright:  MontaVista Software Inc. - * - * 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/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> - -#include <mach/pxa27x.h> -#include <mach/mainstone.h> - -#include "leds.h" - - -/* 8 discrete leds available for general use: */ -#define D28			(1 << 0) -#define D27			(1 << 1) -#define D26			(1 << 2) -#define D25			(1 << 3) -#define D24			(1 << 4) -#define D23			(1 << 5) -#define D22			(1 << 6) -#define D21			(1 << 7) - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -void mainstone_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	switch (evt) { -	case led_start: -		hw_led_state = 0; -		led_state = LED_STATE_ENABLED; -		break; - -	case led_stop: -		led_state &= ~LED_STATE_ENABLED; -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		hw_led_state ^= D26; -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		hw_led_state &= ~D27; -		break; - -	case led_idle_end: -		hw_led_state |= D27; -		break; -#endif - -	case led_halted: -		break; - -	case led_green_on: -		hw_led_state |= D21; -		break; - -	case led_green_off: -		hw_led_state &= ~D21; -		break; - -	case led_amber_on: -		hw_led_state |= D22; -		break; - -	case led_amber_off: -		hw_led_state &= ~D22; -		break; - -	case led_red_on: -		hw_led_state |= D23; -		break; - -	case led_red_off: -		hw_led_state &= ~D23; -		break; - -	default: -		break; -	} - -	if  (led_state & LED_STATE_ENABLED) -		MST_LEDCTRL = (MST_LEDCTRL | 0xff) & ~hw_led_state; -	else -		MST_LEDCTRL |= 0xff; - -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-pxa/leds.c b/arch/arm/mach-pxa/leds.c deleted file mode 100644 index bbe4d5f6afa..00000000000 --- a/arch/arm/mach-pxa/leds.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/leds.c - * - * xscale LEDs dispatcher - * - * Copyright (C) 2001 Nicolas Pitre - * - * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc. - */ -#include <linux/compiler.h> -#include <linux/init.h> - -#include <asm/leds.h> -#include <asm/mach-types.h> - -#include "leds.h" - -static int __init -pxa_leds_init(void) -{ -	if (machine_is_lubbock()) -		leds_event = lubbock_leds_event; -	if (machine_is_mainstone()) -		leds_event = mainstone_leds_event; -	if (machine_is_pxa_idp()) -		leds_event = idp_leds_event; - -	leds_event(led_start); -	return 0; -} - -core_initcall(pxa_leds_init); diff --git a/arch/arm/mach-pxa/leds.h b/arch/arm/mach-pxa/leds.h deleted file mode 100644 index 7f0dfe01345..00000000000 --- a/arch/arm/mach-pxa/leds.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * arch/arm/mach-pxa/leds.h - * - * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc. - * - * blinky lights for various PXA-based systems: - * - */ - -extern void idp_leds_event(led_event_t evt); -extern void lubbock_leds_event(led_event_t evt); -extern void mainstone_leds_event(led_event_t evt); -extern void trizeps4_leds_event(led_event_t evt); diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 0ca0db78790..3c48035afd6 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -15,6 +15,7 @@  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/init.h> +#include <linux/io.h>  #include <linux/platform_device.h>  #include <linux/syscore_ops.h>  #include <linux/major.h> @@ -23,6 +24,8 @@  #include <linux/mtd/mtd.h>  #include <linux/mtd/partitions.h>  #include <linux/smc91x.h> +#include <linux/slab.h> +#include <linux/leds.h>  #include <linux/spi/spi.h>  #include <linux/spi/ads7846.h> @@ -549,6 +552,98 @@ static void __init lubbock_map_io(void)  	PCFR |= PCFR_OPDE;  } +/* + * Driver for the 8 discrete LEDs available for general use: + * Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays + * so be sure to not monkey with them here. + */ + +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +struct lubbock_led { +	struct led_classdev	cdev; +	u8			mask; +}; + +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static const struct { +	const char *name; +	const char *trigger; +} lubbock_leds[] = { +	{ "lubbock:D28", "default-on", }, +	{ "lubbock:D27", "cpu0", }, +	{ "lubbock:D26", "heartbeat" }, +	{ "lubbock:D25", }, +	{ "lubbock:D24", }, +	{ "lubbock:D23", }, +	{ "lubbock:D22", }, +	{ "lubbock:D21", }, +}; + +static void lubbock_led_set(struct led_classdev *cdev, +			      enum led_brightness b) +{ +	struct lubbock_led *led = container_of(cdev, +					 struct lubbock_led, cdev); +	u32 reg = LUB_DISC_BLNK_LED; + +	if (b != LED_OFF) +		reg |= led->mask; +	else +		reg &= ~led->mask; + +	LUB_DISC_BLNK_LED = reg; +} + +static enum led_brightness lubbock_led_get(struct led_classdev *cdev) +{ +	struct lubbock_led *led = container_of(cdev, +					 struct lubbock_led, cdev); +	u32 reg = LUB_DISC_BLNK_LED; + +	return (reg & led->mask) ? LED_FULL : LED_OFF; +} + +static int __init lubbock_leds_init(void) +{ +	int i; + +	if (!machine_is_lubbock()) +		return -ENODEV; + +	/* All ON */ +	LUB_DISC_BLNK_LED |= 0xff; +	for (i = 0; i < ARRAY_SIZE(lubbock_leds); i++) { +		struct lubbock_led *led; + +		led = kzalloc(sizeof(*led), GFP_KERNEL); +		if (!led) +			break; + +		led->cdev.name = lubbock_leds[i].name; +		led->cdev.brightness_set = lubbock_led_set; +		led->cdev.brightness_get = lubbock_led_get; +		led->cdev.default_trigger = lubbock_leds[i].trigger; +		led->mask = BIT(i); + +		if (led_classdev_register(NULL, &led->cdev) < 0) { +			kfree(led); +			break; +		} +	} + +	return 0; +} + +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(lubbock_leds_init); +#endif +  MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")  	/* Maintainer: MontaVista Software Inc. */  	.map_io		= lubbock_map_io, diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 1aebaf71946..bdc6c335830 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -28,6 +28,8 @@  #include <linux/pwm_backlight.h>  #include <linux/smc91x.h>  #include <linux/i2c/pxa-i2c.h> +#include <linux/slab.h> +#include <linux/leds.h>  #include <asm/types.h>  #include <asm/setup.h> @@ -613,6 +615,98 @@ static void __init mainstone_map_io(void)   	PCFR = 0x66;  } +/* + * Driver for the 8 discrete LEDs available for general use: + * Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays + * so be sure to not monkey with them here. + */ + +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +struct mainstone_led { +	struct led_classdev	cdev; +	u8			mask; +}; + +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static const struct { +	const char *name; +	const char *trigger; +} mainstone_leds[] = { +	{ "mainstone:D28", "default-on", }, +	{ "mainstone:D27", "cpu0", }, +	{ "mainstone:D26", "heartbeat" }, +	{ "mainstone:D25", }, +	{ "mainstone:D24", }, +	{ "mainstone:D23", }, +	{ "mainstone:D22", }, +	{ "mainstone:D21", }, +}; + +static void mainstone_led_set(struct led_classdev *cdev, +			      enum led_brightness b) +{ +	struct mainstone_led *led = container_of(cdev, +					 struct mainstone_led, cdev); +	u32 reg = MST_LEDCTRL; + +	if (b != LED_OFF) +		reg |= led->mask; +	else +		reg &= ~led->mask; + +	MST_LEDCTRL = reg; +} + +static enum led_brightness mainstone_led_get(struct led_classdev *cdev) +{ +	struct mainstone_led *led = container_of(cdev, +					 struct mainstone_led, cdev); +	u32 reg = MST_LEDCTRL; + +	return (reg & led->mask) ? LED_FULL : LED_OFF; +} + +static int __init mainstone_leds_init(void) +{ +	int i; + +	if (!machine_is_mainstone()) +		return -ENODEV; + +	/* All ON */ +	MST_LEDCTRL |= 0xff; +	for (i = 0; i < ARRAY_SIZE(mainstone_leds); i++) { +		struct mainstone_led *led; + +		led = kzalloc(sizeof(*led), GFP_KERNEL); +		if (!led) +			break; + +		led->cdev.name = mainstone_leds[i].name; +		led->cdev.brightness_set = mainstone_led_set; +		led->cdev.brightness_get = mainstone_led_get; +		led->cdev.default_trigger = mainstone_leds[i].trigger; +		led->mask = BIT(i); + +		if (led_classdev_register(NULL, &led->cdev) < 0) { +			kfree(led); +			break; +		} +	} + +	return 0; +} + +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(mainstone_leds_init); +#endif +  MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")  	/* Maintainer: MontaVista Software Inc. */  	.atag_offset	= 0x100,	/* BLOB boot parameter setting */ diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 45868bb43cb..d22dee96484 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -35,7 +35,6 @@  #include <mach/hardware.h>  #include <asm/irq.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/hardware/arm_timer.h>  #include <asm/hardware/icst.h> @@ -436,44 +435,6 @@ struct clcd_board clcd_plat_data = {  	.remove		= versatile_clcd_remove_dma,  }; -#ifdef CONFIG_LEDS -#define VA_LEDS_BASE (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET) - -void realview_leds_event(led_event_t ledevt) -{ -	unsigned long flags; -	u32 val; -	u32 led = 1 << smp_processor_id(); - -	local_irq_save(flags); -	val = readl(VA_LEDS_BASE); - -	switch (ledevt) { -	case led_idle_start: -		val = val & ~led; -		break; - -	case led_idle_end: -		val = val | led; -		break; - -	case led_timer: -		val = val ^ REALVIEW_SYS_LED7; -		break; - -	case led_halted: -		val = 0; -		break; - -	default: -		break; -	} - -	writel(val, VA_LEDS_BASE); -	local_irq_restore(flags); -} -#endif	/* CONFIG_LEDS */ -  /*   * Where is the timer (VA)?   */ diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index f8f2c0ac4c0..f2141ae5a7d 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h @@ -26,7 +26,6 @@  #include <linux/io.h>  #include <asm/setup.h> -#include <asm/leds.h>  #define APB_DEVICE(name, busid, base, plat)			\  static AMBA_APB_DEVICE(name, busid, 0, REALVIEW_##base##_BASE, base##_IRQ, plat) @@ -47,7 +46,6 @@ extern void __iomem *timer1_va_base;  extern void __iomem *timer2_va_base;  extern void __iomem *timer3_va_base; -extern void realview_leds_event(led_event_t ledevt);  extern void realview_timer_init(unsigned int timer_irq);  extern int realview_flash_register(struct resource *res, u32 num);  extern int realview_eth_register(const char *name, struct resource *res); diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index baf382c5e77..21661ade885 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -30,7 +30,6 @@  #include <mach/hardware.h>  #include <asm/irq.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/pmu.h>  #include <asm/pgtable.h> @@ -462,10 +461,6 @@ static void __init realview_eb_init(void)  		struct amba_device *d = amba_devs[i];  		amba_device_register(d, &iomem_resource);  	} - -#ifdef CONFIG_LEDS -	leds_event = realview_leds_event; -#endif  }  MACHINE_START(REALVIEW_EB, "ARM-RealView EB") diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index b1d7cafa1a6..c0ff882c5cb 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -32,7 +32,6 @@  #include <mach/hardware.h>  #include <asm/irq.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/pmu.h>  #include <asm/pgtable.h> @@ -375,10 +374,6 @@ static void __init realview_pb1176_init(void)  		struct amba_device *d = amba_devs[i];  		amba_device_register(d, &iomem_resource);  	} - -#ifdef CONFIG_LEDS -	leds_event = realview_leds_event; -#endif  }  MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176") diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index a98c536e332..30779ae40c0 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -30,7 +30,6 @@  #include <mach/hardware.h>  #include <asm/irq.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/pmu.h>  #include <asm/pgtable.h> @@ -357,10 +356,6 @@ static void __init realview_pb11mp_init(void)  		struct amba_device *d = amba_devs[i];  		amba_device_register(d, &iomem_resource);  	} - -#ifdef CONFIG_LEDS -	leds_event = realview_leds_event; -#endif  }  MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore") diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 59650174e6e..081cd72c090 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -29,7 +29,6 @@  #include <linux/io.h>  #include <asm/irq.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/pmu.h>  #include <asm/pgtable.h> @@ -299,10 +298,6 @@ static void __init realview_pba8_init(void)  		struct amba_device *d = amba_devs[i];  		amba_device_register(d, &iomem_resource);  	} - -#ifdef CONFIG_LEDS -	leds_event = realview_leds_event; -#endif  }  MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8") diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 3f2f605624e..1ce62b9f846 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -28,7 +28,6 @@  #include <linux/io.h>  #include <asm/irq.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/pmu.h>  #include <asm/smp_twd.h> @@ -394,10 +393,6 @@ static void __init realview_pbx_init(void)  		struct amba_device *d = amba_devs[i];  		amba_device_register(d, &iomem_resource);  	} - -#ifdef CONFIG_LEDS -	leds_event = realview_leds_event; -#endif  }  MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX") diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index 60b97ec0167..1aed9e70465 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -7,21 +7,17 @@ obj-y := clock.o generic.o irq.o time.o #nmi-oopser.o  obj-m :=  obj-n :=  obj-  := -led-y := leds.o  obj-$(CONFIG_CPU_FREQ_SA1100)		+= cpu-sa1100.o  obj-$(CONFIG_CPU_FREQ_SA1110)		+= cpu-sa1110.o  # Specific board support  obj-$(CONFIG_SA1100_ASSABET)		+= assabet.o -led-$(CONFIG_SA1100_ASSABET)		+= leds-assabet.o  obj-$(CONFIG_ASSABET_NEPONSET)		+= neponset.o  obj-$(CONFIG_SA1100_BADGE4)		+= badge4.o -led-$(CONFIG_SA1100_BADGE4)		+= leds-badge4.o  obj-$(CONFIG_SA1100_CERF)		+= cerf.o -led-$(CONFIG_SA1100_CERF)		+= leds-cerf.o  obj-$(CONFIG_SA1100_COLLIE)		+= collie.o @@ -29,13 +25,11 @@ obj-$(CONFIG_SA1100_H3100)		+= h3100.o h3xxx.o  obj-$(CONFIG_SA1100_H3600)		+= h3600.o h3xxx.o  obj-$(CONFIG_SA1100_HACKKIT)		+= hackkit.o -led-$(CONFIG_SA1100_HACKKIT)		+= leds-hackkit.o  obj-$(CONFIG_SA1100_JORNADA720)		+= jornada720.o  obj-$(CONFIG_SA1100_JORNADA720_SSP)	+= jornada720_ssp.o  obj-$(CONFIG_SA1100_LART)		+= lart.o -led-$(CONFIG_SA1100_LART)		+= leds-lart.o  obj-$(CONFIG_SA1100_NANOENGINE)		+= nanoengine.o  obj-$(CONFIG_PCI_NANOENGINE)		+= pci-nanoengine.o @@ -46,9 +40,6 @@ obj-$(CONFIG_SA1100_SHANNON)		+= shannon.o  obj-$(CONFIG_SA1100_SIMPAD)		+= simpad.o -# LEDs support -obj-$(CONFIG_LEDS) += $(led-y) -  # Miscellaneous functions  obj-$(CONFIG_PM)			+= pm.o sleep.o  obj-$(CONFIG_SA1100_SSP)		+= ssp.o diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index d673211f121..1710ed1a0ac 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -20,6 +20,8 @@  #include <linux/mtd/partitions.h>  #include <linux/delay.h>  #include <linux/mm.h> +#include <linux/leds.h> +#include <linux/slab.h>  #include <video/sa1100fb.h> @@ -529,6 +531,89 @@ static void __init assabet_map_io(void)  	sa1100_register_uart(2, 3);  } +/* LEDs */ +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +struct assabet_led { +	struct led_classdev cdev; +	u32 mask; +}; + +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static const struct { +	const char *name; +	const char *trigger; +} assabet_leds[] = { +	{ "assabet:red", "cpu0",}, +	{ "assabet:green", "heartbeat", }, +}; + +/* + * The LED control in Assabet is reversed: + *  - setting bit means turn off LED + *  - clearing bit means turn on LED + */ +static void assabet_led_set(struct led_classdev *cdev, +		enum led_brightness b) +{ +	struct assabet_led *led = container_of(cdev, +			struct assabet_led, cdev); + +	if (b != LED_OFF) +		ASSABET_BCR_clear(led->mask); +	else +		ASSABET_BCR_set(led->mask); +} + +static enum led_brightness assabet_led_get(struct led_classdev *cdev) +{ +	struct assabet_led *led = container_of(cdev, +			struct assabet_led, cdev); + +	return (ASSABET_BCR & led->mask) ? LED_OFF : LED_FULL; +} + +static int __init assabet_leds_init(void) +{ +	int i; + +	if (!machine_is_assabet()) +		return -ENODEV; + +	for (i = 0; i < ARRAY_SIZE(assabet_leds); i++) { +		struct assabet_led *led; + +		led = kzalloc(sizeof(*led), GFP_KERNEL); +		if (!led) +			break; + +		led->cdev.name = assabet_leds[i].name; +		led->cdev.brightness_set = assabet_led_set; +		led->cdev.brightness_get = assabet_led_get; +		led->cdev.default_trigger = assabet_leds[i].trigger; + +		if (!i) +			led->mask = ASSABET_BCR_LED_RED; +		else +			led->mask = ASSABET_BCR_LED_GREEN; + +		if (led_classdev_register(NULL, &led->cdev) < 0) { +			kfree(led); +			break; +		} +	} + +	return 0; +} + +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(assabet_leds_init); +#endif  MACHINE_START(ASSABET, "Intel-Assabet")  	.atag_offset	= 0x100, diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c index b30fb99b587..038df4894b0 100644 --- a/arch/arm/mach-sa1100/badge4.c +++ b/arch/arm/mach-sa1100/badge4.c @@ -22,6 +22,8 @@  #include <linux/mtd/mtd.h>  #include <linux/mtd/partitions.h>  #include <linux/errno.h> +#include <linux/gpio.h> +#include <linux/leds.h>  #include <mach/hardware.h>  #include <asm/mach-types.h> @@ -76,8 +78,36 @@ static struct platform_device sa1111_device = {  	.resource	= sa1111_resources,  }; +/* LEDs */ +struct gpio_led badge4_gpio_leds[] = { +	{ +		.name			= "badge4:red", +		.default_trigger	= "heartbeat", +		.gpio			= 7, +	}, +	{ +		.name			= "badge4:green", +		.default_trigger	= "cpu0", +		.gpio			= 9, +	}, +}; + +static struct gpio_led_platform_data badge4_gpio_led_info = { +	.leds		= badge4_gpio_leds, +	.num_leds	= ARRAY_SIZE(badge4_gpio_leds), +}; + +static struct platform_device badge4_leds = { +	.name	= "leds-gpio", +	.id	= -1, +	.dev	= { +		.platform_data	= &badge4_gpio_led_info, +	} +}; +  static struct platform_device *devices[] __initdata = {  	&sa1111_device, +	&badge4_leds,  };  static int __init badge4_sa1111_init(void) diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index 09d7f4b4b35..5240f104a3c 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -17,6 +17,8 @@  #include <linux/irq.h>  #include <linux/mtd/mtd.h>  #include <linux/mtd/partitions.h> +#include <linux/gpio.h> +#include <linux/leds.h>  #include <mach/hardware.h>  #include <asm/setup.h> @@ -43,8 +45,48 @@ static struct platform_device cerfuart2_device = {  	.resource	= cerfuart2_resources,  }; +/* LEDs */ +struct gpio_led cerf_gpio_leds[] = { +	{ +		.name			= "cerf:d0", +		.default_trigger	= "heartbeat", +		.gpio			= 0, +	}, +	{ +		.name			= "cerf:d1", +		.default_trigger	= "cpu0", +		.gpio			= 1, +	}, +	{ +		.name			= "cerf:d2", +		.default_trigger	= "default-on", +		.gpio			= 2, +	}, +	{ +		.name			= "cerf:d3", +		.default_trigger	= "default-on", +		.gpio			= 3, +	}, + +}; + +static struct gpio_led_platform_data cerf_gpio_led_info = { +	.leds		= cerf_gpio_leds, +	.num_leds	= ARRAY_SIZE(cerf_gpio_leds), +}; + +static struct platform_device cerf_leds = { +	.name	= "leds-gpio", +	.id	= -1, +	.dev	= { +		.platform_data	= &cerf_gpio_led_info, +	} +}; + +  static struct platform_device *cerf_devices[] __initdata = {  	&cerfuart2_device, +	&cerf_leds,  };  #ifdef CONFIG_SA1100_CERF_FLASH_32MB diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c index 7f86bd91182..fc106aab7c7 100644 --- a/arch/arm/mach-sa1100/hackkit.c +++ b/arch/arm/mach-sa1100/hackkit.c @@ -21,6 +21,10 @@  #include <linux/serial_core.h>  #include <linux/mtd/mtd.h>  #include <linux/mtd/partitions.h> +#include <linux/tty.h> +#include <linux/gpio.h> +#include <linux/leds.h> +#include <linux/platform_device.h>  #include <asm/mach-types.h>  #include <asm/setup.h> @@ -183,9 +187,37 @@ static struct flash_platform_data hackkit_flash_data = {  static struct resource hackkit_flash_resource =  	DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M); +/* LEDs */ +struct gpio_led hackkit_gpio_leds[] = { +	{ +		.name			= "hackkit:red", +		.default_trigger	= "cpu0", +		.gpio			= 22, +	}, +	{ +		.name			= "hackkit:green", +		.default_trigger	= "heartbeat", +		.gpio			= 23, +	}, +}; + +static struct gpio_led_platform_data hackkit_gpio_led_info = { +	.leds		= hackkit_gpio_leds, +	.num_leds	= ARRAY_SIZE(hackkit_gpio_leds), +}; + +static struct platform_device hackkit_leds = { +	.name	= "leds-gpio", +	.id	= -1, +	.dev	= { +		.platform_data	= &hackkit_gpio_led_info, +	} +}; +  static void __init hackkit_init(void)  {  	sa11x0_register_mtd(&hackkit_flash_data, &hackkit_flash_resource, 1); +	platform_device_register(&hackkit_leds);  }  /********************************************************************** diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index b775a0abec0..b2ce04bf4c9 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -5,6 +5,9 @@  #include <linux/init.h>  #include <linux/kernel.h>  #include <linux/tty.h> +#include <linux/gpio.h> +#include <linux/leds.h> +#include <linux/platform_device.h>  #include <video/sa1100fb.h> @@ -126,6 +129,27 @@ static struct map_desc lart_io_desc[] __initdata = {  	}  }; +/* LEDs */ +struct gpio_led lart_gpio_leds[] = { +	{ +		.name			= "lart:red", +		.default_trigger	= "cpu0", +		.gpio			= 23, +	}, +}; + +static struct gpio_led_platform_data lart_gpio_led_info = { +	.leds		= lart_gpio_leds, +	.num_leds	= ARRAY_SIZE(lart_gpio_leds), +}; + +static struct platform_device lart_leds = { +	.name	= "leds-gpio", +	.id	= -1, +	.dev	= { +		.platform_data	= &lart_gpio_led_info, +	} +};  static void __init lart_map_io(void)  {  	sa1100_map_io(); @@ -139,6 +163,8 @@ static void __init lart_map_io(void)  	GPDR |= GPIO_UART_TXD;  	GPDR &= ~GPIO_UART_RXD;  	PPAR |= PPAR_UPR; + +	platform_device_register(&lart_leds);  }  MACHINE_START(LART, "LART") diff --git a/arch/arm/mach-sa1100/leds-assabet.c b/arch/arm/mach-sa1100/leds-assabet.c deleted file mode 100644 index 3699176bca9..00000000000 --- a/arch/arm/mach-sa1100/leds-assabet.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/leds-assabet.c - * - * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu> - * - * Original (leds-footbridge.c) by Russell King - * - * Assabet uses the LEDs as follows: - *   - Green - toggles state every 50 timer interrupts - *   - Red   - on if system is not idle - */ -#include <linux/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> -#include <mach/assabet.h> - -#include "leds.h" - - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -#define ASSABET_BCR_LED_MASK	(ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED) - -void assabet_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	switch (evt) { -	case led_start: -		hw_led_state = ASSABET_BCR_LED_RED | ASSABET_BCR_LED_GREEN; -		led_state = LED_STATE_ENABLED; -		break; - -	case led_stop: -		led_state &= ~LED_STATE_ENABLED; -		hw_led_state = ASSABET_BCR_LED_RED | ASSABET_BCR_LED_GREEN; -		ASSABET_BCR_frob(ASSABET_BCR_LED_MASK, hw_led_state); -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = ASSABET_BCR_LED_RED | ASSABET_BCR_LED_GREEN; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = ASSABET_BCR_LED_RED | ASSABET_BCR_LED_GREEN; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state ^= ASSABET_BCR_LED_GREEN; -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state |= ASSABET_BCR_LED_RED; -		break; - -	case led_idle_end: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state &= ~ASSABET_BCR_LED_RED; -		break; -#endif - -	case led_halted: -		break; - -	case led_green_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~ASSABET_BCR_LED_GREEN; -		break; - -	case led_green_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= ASSABET_BCR_LED_GREEN; -		break; - -	case led_amber_on: -		break; - -	case led_amber_off: -		break; - -	case led_red_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~ASSABET_BCR_LED_RED; -		break; - -	case led_red_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= ASSABET_BCR_LED_RED; -		break; - -	default: -		break; -	} - -	if  (led_state & LED_STATE_ENABLED) -		ASSABET_BCR_frob(ASSABET_BCR_LED_MASK, hw_led_state); - -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-sa1100/leds-badge4.c b/arch/arm/mach-sa1100/leds-badge4.c deleted file mode 100644 index f99fac3eedb..00000000000 --- a/arch/arm/mach-sa1100/leds-badge4.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/leds-badge4.c - * - * Author: Christopher Hoover <ch@hpl.hp.com> - * Copyright (C) 2002 Hewlett-Packard Company - * - * 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/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> - -#include "leds.h" - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -#define LED_RED		GPIO_GPIO(7) -#define LED_GREEN       GPIO_GPIO(9) -#define LED_MASK	(LED_RED|LED_GREEN) - -#define LED_IDLE	LED_GREEN -#define LED_TIMER	LED_RED - -void badge4_leds_event(led_event_t evt) -{ -        unsigned long flags; - -	local_irq_save(flags); - -        switch (evt) { -        case led_start: -		GPDR |= LED_MASK; -                hw_led_state = LED_MASK; -                led_state = LED_STATE_ENABLED; -                break; - -        case led_stop: -                led_state &= ~LED_STATE_ENABLED; -                break; - -        case led_claim: -                led_state |= LED_STATE_CLAIMED; -                hw_led_state = LED_MASK; -                break; - -        case led_release: -                led_state &= ~LED_STATE_CLAIMED; -                hw_led_state = LED_MASK; -                break; - -#ifdef CONFIG_LEDS_TIMER -        case led_timer: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state ^= LED_TIMER; -                break; -#endif - -#ifdef CONFIG_LEDS_CPU -        case led_idle_start: -		/* LED off when system is idle */ -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state &= ~LED_IDLE; -                break; - -        case led_idle_end: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state |= LED_IDLE; -                break; -#endif - -        case led_red_on: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state &= ~LED_RED; -                break; - -        case led_red_off: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state |= LED_RED; -                break; - -        case led_green_on: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state &= ~LED_GREEN; -                break; - -        case led_green_off: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state |= LED_GREEN; -                break; - -	default: -		break; -        } - -        if  (led_state & LED_STATE_ENABLED) { -                GPSR = hw_led_state; -                GPCR = hw_led_state ^ LED_MASK; -        } - -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-sa1100/leds-cerf.c b/arch/arm/mach-sa1100/leds-cerf.c deleted file mode 100644 index 30fc3b2bf55..00000000000 --- a/arch/arm/mach-sa1100/leds-cerf.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/leds-cerf.c - * - * Author: ??? - */ -#include <linux/init.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <asm/leds.h> - -#include "leds.h" - - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -#define LED_D0          GPIO_GPIO(0) -#define LED_D1          GPIO_GPIO(1) -#define LED_D2          GPIO_GPIO(2) -#define LED_D3          GPIO_GPIO(3) -#define LED_MASK        (LED_D0|LED_D1|LED_D2|LED_D3) - -void cerf_leds_event(led_event_t evt) -{ -        unsigned long flags; - -	local_irq_save(flags); - -        switch (evt) { -        case led_start: -                hw_led_state = LED_MASK; -                led_state = LED_STATE_ENABLED; -                break; - -        case led_stop: -                led_state &= ~LED_STATE_ENABLED; -                break; - -        case led_claim: -                led_state |= LED_STATE_CLAIMED; -                hw_led_state = LED_MASK; -                break; -        case led_release: -                led_state &= ~LED_STATE_CLAIMED; -                hw_led_state = LED_MASK; -                break; - -#ifdef CONFIG_LEDS_TIMER -        case led_timer: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state ^= LED_D0; -                break; -#endif - -#ifdef CONFIG_LEDS_CPU -        case led_idle_start: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state &= ~LED_D1; -                break; - -        case led_idle_end: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state |= LED_D1; -                break; -#endif -        case led_green_on: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state &= ~LED_D2; -                break; - -        case led_green_off: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state |= LED_D2; -                break; - -        case led_amber_on: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state &= ~LED_D3; -                break; - -        case led_amber_off: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state |= LED_D3; -                break; - -        case led_red_on: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state &= ~LED_D1; -                break; - -        case led_red_off: -                if (!(led_state & LED_STATE_CLAIMED)) -                        hw_led_state |= LED_D1; -                break; - -        default: -                break; -        } - -        if  (led_state & LED_STATE_ENABLED) { -                GPSR = hw_led_state; -                GPCR = hw_led_state ^ LED_MASK; -        } - -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-sa1100/leds-hackkit.c b/arch/arm/mach-sa1100/leds-hackkit.c deleted file mode 100644 index 6a2352436e6..00000000000 --- a/arch/arm/mach-sa1100/leds-hackkit.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/leds-hackkit.c - * - * based on leds-lart.c - * - * (C) Erik Mouw (J.A.K.Mouw@its.tudelft.nl), April 21, 2000 - * (C) Stefan Eletzhofer <stefan.eletzhofer@eletztrick.de>, 2002 - * - * The HackKit has two leds (GPIO 22/23). The red led (gpio 22) is used - * as cpu led, the green one is used as timer led. - */ -#include <linux/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> - -#include "leds.h" - - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -#define LED_GREEN    GPIO_GPIO23 -#define LED_RED    GPIO_GPIO22 -#define LED_MASK  (LED_RED | LED_GREEN) - -void hackkit_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	switch(evt) { -		case led_start: -			/* pin 22/23 are outputs */ -			GPDR |= LED_MASK; -			hw_led_state = LED_MASK; -			led_state = LED_STATE_ENABLED; -			break; - -		case led_stop: -			led_state &= ~LED_STATE_ENABLED; -			break; - -		case led_claim: -			led_state |= LED_STATE_CLAIMED; -			hw_led_state = LED_MASK; -			break; - -		case led_release: -			led_state &= ~LED_STATE_CLAIMED; -			hw_led_state = LED_MASK; -			break; - -#ifdef CONFIG_LEDS_TIMER -		case led_timer: -			if (!(led_state & LED_STATE_CLAIMED)) -				hw_led_state ^= LED_GREEN; -			break; -#endif - -#ifdef CONFIG_LEDS_CPU -		case led_idle_start: -			/* The LART people like the LED to be off when the -			   system is idle... */ -			if (!(led_state & LED_STATE_CLAIMED)) -				hw_led_state &= ~LED_RED; -			break; - -		case led_idle_end: -			/* ... and on if the system is not idle */ -			if (!(led_state & LED_STATE_CLAIMED)) -				hw_led_state |= LED_RED; -			break; -#endif - -		case led_red_on: -			if (led_state & LED_STATE_CLAIMED) -				hw_led_state &= ~LED_RED; -			break; - -		case led_red_off: -			if (led_state & LED_STATE_CLAIMED) -				hw_led_state |= LED_RED; -			break; - -		case led_green_on: -			if (led_state & LED_STATE_CLAIMED) -				hw_led_state &= ~LED_GREEN; -			break; - -		case led_green_off: -			if (led_state & LED_STATE_CLAIMED) -				hw_led_state |= LED_GREEN; -			break; - -		default: -			break; -	} - -	/* Now set the GPIO state, or nothing will happen at all */ -	if (led_state & LED_STATE_ENABLED) { -		GPSR = hw_led_state; -		GPCR = hw_led_state ^ LED_MASK; -	} - -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-sa1100/leds-lart.c b/arch/arm/mach-sa1100/leds-lart.c deleted file mode 100644 index 50a5b143b46..00000000000 --- a/arch/arm/mach-sa1100/leds-lart.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/leds-lart.c - * - * (C) Erik Mouw (J.A.K.Mouw@its.tudelft.nl), April 21, 2000 - * - * LART uses the LED as follows: - *   - GPIO23 is the LED, on if system is not idle - *  You can use both CONFIG_LEDS_CPU and CONFIG_LEDS_TIMER at the same - *  time, but in that case the timer events will still dictate the - *  pace of the LED. - */ -#include <linux/init.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <asm/leds.h> - -#include "leds.h" - - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -#define LED_23    GPIO_GPIO23 -#define LED_MASK  (LED_23) - -void lart_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	local_irq_save(flags); - -	switch(evt) { -	case led_start: -		/* pin 23 is output pin */ -		GPDR |= LED_23; -		hw_led_state = LED_MASK; -		led_state = LED_STATE_ENABLED; -		break; - -	case led_stop: -		led_state &= ~LED_STATE_ENABLED; -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = LED_MASK; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = LED_MASK; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state ^= LED_23; -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		/* The LART people like the LED to be off when the -                   system is idle... */ -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state &= ~LED_23; -		break; - -	case led_idle_end: -		/* ... and on if the system is not idle */ -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state |= LED_23; -		break; -#endif - -	case led_red_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~LED_23; -		break; - -	case led_red_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= LED_23; -		break; - -	default: -		break; -	} - -	/* Now set the GPIO state, or nothing will happen at all */ -	if (led_state & LED_STATE_ENABLED) { -		GPSR = hw_led_state; -		GPCR = hw_led_state ^ LED_MASK; -	} - -	local_irq_restore(flags); -} diff --git a/arch/arm/mach-sa1100/leds.c b/arch/arm/mach-sa1100/leds.c deleted file mode 100644 index 5fe71a0f105..00000000000 --- a/arch/arm/mach-sa1100/leds.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/leds.c - * - * SA1100 LEDs dispatcher - * - * Copyright (C) 2001 Nicolas Pitre - */ -#include <linux/compiler.h> -#include <linux/init.h> - -#include <asm/leds.h> -#include <asm/mach-types.h> - -#include "leds.h" - -static int __init -sa1100_leds_init(void) -{ -	if (machine_is_assabet()) -		leds_event = assabet_leds_event; -	if (machine_is_consus()) -		leds_event = consus_leds_event; -	if (machine_is_badge4()) -		leds_event = badge4_leds_event; -	if (machine_is_brutus()) -		leds_event = brutus_leds_event; -	if (machine_is_cerf()) -		leds_event = cerf_leds_event; -	if (machine_is_flexanet()) -		leds_event = flexanet_leds_event; -	if (machine_is_graphicsclient()) -		leds_event = graphicsclient_leds_event; -	if (machine_is_hackkit()) -		leds_event = hackkit_leds_event; -	if (machine_is_lart()) -		leds_event = lart_leds_event; -	if (machine_is_pfs168()) -		leds_event = pfs168_leds_event; -	if (machine_is_graphicsmaster()) -		leds_event = graphicsmaster_leds_event; -	if (machine_is_adsbitsy()) -		leds_event = adsbitsy_leds_event; -	if (machine_is_pt_system3()) -		leds_event = system3_leds_event; - -	leds_event(led_start); -	return 0; -} - -core_initcall(sa1100_leds_init); diff --git a/arch/arm/mach-sa1100/leds.h b/arch/arm/mach-sa1100/leds.h deleted file mode 100644 index 776b6020f55..00000000000 --- a/arch/arm/mach-sa1100/leds.h +++ /dev/null @@ -1,13 +0,0 @@ -extern void assabet_leds_event(led_event_t evt); -extern void badge4_leds_event(led_event_t evt); -extern void consus_leds_event(led_event_t evt); -extern void brutus_leds_event(led_event_t evt); -extern void cerf_leds_event(led_event_t evt); -extern void flexanet_leds_event(led_event_t evt); -extern void graphicsclient_leds_event(led_event_t evt); -extern void hackkit_leds_event(led_event_t evt); -extern void lart_leds_event(led_event_t evt); -extern void pfs168_leds_event(led_event_t evt); -extern void graphicsmaster_leds_event(led_event_t evt); -extern void adsbitsy_leds_event(led_event_t evt); -extern void system3_leds_event(led_event_t evt); diff --git a/arch/arm/mach-shark/Makefile b/arch/arm/mach-shark/Makefile index 45be9b04e7b..29657183c45 100644 --- a/arch/arm/mach-shark/Makefile +++ b/arch/arm/mach-shark/Makefile @@ -4,9 +4,7 @@  # Object file lists. -obj-y			:= core.o dma.o irq.o pci.o +obj-y			:= core.o dma.o irq.o pci.o leds.o  obj-m			:=  obj-n			:=  obj-			:= - -obj-$(CONFIG_LEDS)	+= leds.o diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index 2704bcd869c..c709979ee75 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c @@ -13,7 +13,6 @@  #include <asm/setup.h>  #include <asm/mach-types.h> -#include <asm/leds.h>  #include <asm/param.h>  #include <asm/system_misc.h> diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c index 25609076921..081c778a10a 100644 --- a/arch/arm/mach-shark/leds.c +++ b/arch/arm/mach-shark/leds.c @@ -1,165 +1,117 @@  /* - * arch/arm/mach-shark/leds.c - * by Alexander Schulz - * - * derived from: - * arch/arm/kernel/leds-footbridge.c - * Copyright (C) 1998-1999 Russell King - *   * DIGITAL Shark LED control routines.   * - * The leds use is as follows: - *  - Green front - toggles state every 50 timer interrupts - *  - Amber front - Unused, this is a dual color led (Amber/Green) - *  - Amber back  - On if system is not idle + * Driver for the 3 user LEDs found on the Shark + * Based on Versatile and RealView machine LED code   * - * Changelog: + * License terms: GNU General Public License (GPL) version 2 + * Author: Bryan Wu <bryan.wu@canonical.com>   */  #include <linux/kernel.h> -#include <linux/module.h>  #include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/ioport.h>  #include <linux/io.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/leds.h> -#include <asm/leds.h> - -#define LED_STATE_ENABLED	1 -#define LED_STATE_CLAIMED	2 - -#define SEQUOIA_LED_GREEN       (1<<6) -#define SEQUOIA_LED_AMBER       (1<<5) -#define SEQUOIA_LED_BACK        (1<<7) +#include <asm/mach-types.h> -static char led_state; -static short hw_led_state; -static short saved_state; +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +struct shark_led { +	struct led_classdev cdev; +	u8 mask; +}; -static DEFINE_RAW_SPINLOCK(leds_lock); +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static const struct { +	const char *name; +	const char *trigger; +} shark_leds[] = { +	{ "shark:amber0", "default-on", },	/* Bit 5 */ +	{ "shark:green", "heartbeat", },	/* Bit 6 */ +	{ "shark:amber1", "cpu0" },		/* Bit 7 */ +}; -short sequoia_read(int addr) { -  outw(addr,0x24); -  return inw(0x26); +static u16 led_reg_read(void) +{ +	outw(0x09, 0x24); +	return inw(0x26);  } -void sequoia_write(short value,short addr) { -  outw(addr,0x24); -  outw(value,0x26); +static void led_reg_write(u16 value) +{ +	outw(0x09, 0x24); +	outw(value, 0x26);  } -static void sequoia_leds_event(led_event_t evt) +static void shark_led_set(struct led_classdev *cdev, +			      enum led_brightness b)  { -	unsigned long flags; - -	raw_spin_lock_irqsave(&leds_lock, flags); - -	hw_led_state = sequoia_read(0x09); - -	switch (evt) { -	case led_start: -		hw_led_state |= SEQUOIA_LED_GREEN; -		hw_led_state |= SEQUOIA_LED_AMBER; -#ifdef CONFIG_LEDS_CPU -		hw_led_state |= SEQUOIA_LED_BACK; -#else -		hw_led_state &= ~SEQUOIA_LED_BACK; -#endif -		led_state |= LED_STATE_ENABLED; -		break; - -	case led_stop: -		hw_led_state &= ~SEQUOIA_LED_BACK; -		hw_led_state |= SEQUOIA_LED_GREEN; -		hw_led_state |= SEQUOIA_LED_AMBER; -		led_state &= ~LED_STATE_ENABLED; -		break; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		saved_state = hw_led_state; -		hw_led_state &= ~SEQUOIA_LED_BACK; -		hw_led_state |= SEQUOIA_LED_GREEN; -		hw_led_state |= SEQUOIA_LED_AMBER; -		break; +	struct shark_led *led = container_of(cdev, +						 struct shark_led, cdev); +	u16 reg = led_reg_read(); -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		hw_led_state = saved_state; -		break; +	if (b != LED_OFF) +		reg |= led->mask; +	else +		reg &= ~led->mask; -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state ^= SEQUOIA_LED_GREEN; -		break; -#endif +	led_reg_write(reg); +} -#ifdef CONFIG_LEDS_CPU -	case led_idle_start: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state &= ~SEQUOIA_LED_BACK; -		break; +static enum led_brightness shark_led_get(struct led_classdev *cdev) +{ +	struct shark_led *led = container_of(cdev, +						 struct shark_led, cdev); +	u16 reg = led_reg_read(); -	case led_idle_end: -		if (!(led_state & LED_STATE_CLAIMED)) -			hw_led_state |= SEQUOIA_LED_BACK; -		break; -#endif +	return (reg & led->mask) ? LED_FULL : LED_OFF; +} -	case led_green_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~SEQUOIA_LED_GREEN; -		break; +static int __init shark_leds_init(void) +{ +	int i; +	u16 reg; -	case led_green_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= SEQUOIA_LED_GREEN; -		break; +	if (!machine_is_shark()) +		return -ENODEV; -	case led_amber_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~SEQUOIA_LED_AMBER; -		break; +	for (i = 0; i < ARRAY_SIZE(shark_leds); i++) { +		struct shark_led *led; -	case led_amber_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= SEQUOIA_LED_AMBER; -		break; +		led = kzalloc(sizeof(*led), GFP_KERNEL); +		if (!led) +			break; -	case led_red_on: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state |= SEQUOIA_LED_BACK; -		break; +		led->cdev.name = shark_leds[i].name; +		led->cdev.brightness_set = shark_led_set; +		led->cdev.brightness_get = shark_led_get; +		led->cdev.default_trigger = shark_leds[i].trigger; -	case led_red_off: -		if (led_state & LED_STATE_CLAIMED) -			hw_led_state &= ~SEQUOIA_LED_BACK; -		break; +		/* Count in 5 bits offset */ +		led->mask = BIT(i + 5); -	default: -		break; +		if (led_classdev_register(NULL, &led->cdev) < 0) { +			kfree(led); +			break; +		}  	} -	if  (led_state & LED_STATE_ENABLED) -		sequoia_write(hw_led_state,0x09); - -	raw_spin_unlock_irqrestore(&leds_lock, flags); -} - -static int __init leds_init(void) -{ -	extern void (*leds_event)(led_event_t); -	short temp; -	 -	leds_event = sequoia_leds_event; -  	/* Make LEDs independent of power-state */ -	request_region(0x24,4,"sequoia"); -	temp = sequoia_read(0x09); -	temp |= 1<<10; -	sequoia_write(temp,0x09); -	leds_event(led_start); +	request_region(0x24, 4, "led_reg"); +	reg = led_reg_read(); +	reg |= 1 << 10; +	led_reg_write(reg); +  	return 0;  } -__initcall(leds_init); +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(shark_leds_init); +#endif diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index cd8ea3588f9..855ca02581e 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -37,7 +37,6 @@  #include <linux/mtd/physmap.h>  #include <asm/irq.h> -#include <asm/leds.h>  #include <asm/hardware/arm_timer.h>  #include <asm/hardware/icst.h>  #include <asm/hardware/vic.h> @@ -763,10 +762,6 @@ void __init versatile_init(void)  		struct amba_device *d = amba_devs[i];  		amba_device_register(d, &iomem_resource);  	} - -#ifdef CONFIG_LEDS -	leds_event = versatile_leds_event; -#endif  }  /* diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index dd36eba9506..13910baae22 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -41,9 +41,8 @@ config OMAP_DEBUG_DEVICES  	  For debug cards on TI reference boards.  config OMAP_DEBUG_LEDS -	bool +	def_bool y if NEW_LEDS  	depends on OMAP_DEBUG_DEVICES -	default y if LEDS_CLASS  config POWER_AVS_OMAP  	bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2" diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c index 39407cbe34c..24e23f3dd6a 100644 --- a/arch/arm/plat-omap/debug-leds.c +++ b/arch/arm/plat-omap/debug-leds.c @@ -1,279 +1,118 @@  /*   * linux/arch/arm/plat-omap/debug-leds.c   * + * Copyright 2011 by Bryan Wu <bryan.wu@canonical.com>   * Copyright 2003 by Texas Instruments Incorporated   *   * 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/gpio.h> + +#include <linux/kernel.h>  #include <linux/init.h>  #include <linux/platform_device.h>  #include <linux/leds.h>  #include <linux/io.h> +#include <linux/slab.h>  #include <mach/hardware.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <plat/fpga.h> -  /* Many OMAP development platforms reuse the same "debug board"; these   * platforms include H2, H3, H4, and Perseus2.  There are 16 LEDs on the   * debug board (all green), accessed through FPGA registers. - * - * The "surfer" expansion board and H2 sample board also have two-color - * green+red LEDs (in parallel), used here for timer and idle indicators - * in preference to the ones on the debug board, for a "Disco LED" effect. - * - * This driver exports either the original ARM LED API, the new generic - * one, or both. - */ - -static spinlock_t			lock; -static struct h2p2_dbg_fpga __iomem	*fpga; -static u16				led_state, hw_led_state; - - -#ifdef	CONFIG_OMAP_DEBUG_LEDS -#define new_led_api()	1 -#else -#define new_led_api()	0 -#endif - - -/*-------------------------------------------------------------------------*/ - -/* original ARM debug LED API: - *  - timer and idle leds (some boards use non-FPGA leds here); - *  - up to 4 generic leds, easily accessed in-kernel (any context)   */ -#define GPIO_LED_RED		3 -#define GPIO_LED_GREEN		OMAP_MPUIO(4) - -#define LED_STATE_ENABLED	0x01 -#define LED_STATE_CLAIMED	0x02 -#define LED_TIMER_ON		0x04 - -#define GPIO_IDLE		GPIO_LED_GREEN -#define GPIO_TIMER		GPIO_LED_RED - -static void h2p2_dbg_leds_event(led_event_t evt) -{ -	unsigned long flags; - -	spin_lock_irqsave(&lock, flags); - -	if (!(led_state & LED_STATE_ENABLED) && evt != led_start) -		goto done; - -	switch (evt) { -	case led_start: -		if (fpga) -			led_state |= LED_STATE_ENABLED; -		break; - -	case led_stop: -	case led_halted: -		/* all leds off during suspend or shutdown */ - -		if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) { -			gpio_set_value(GPIO_TIMER, 0); -			gpio_set_value(GPIO_IDLE, 0); -		} - -		__raw_writew(~0, &fpga->leds); -		led_state &= ~LED_STATE_ENABLED; -		goto done; - -	case led_claim: -		led_state |= LED_STATE_CLAIMED; -		hw_led_state = 0; -		break; - -	case led_release: -		led_state &= ~LED_STATE_CLAIMED; -		break; - -#ifdef CONFIG_LEDS_TIMER -	case led_timer: -		led_state ^= LED_TIMER_ON; - -		if (machine_is_omap_perseus2() || machine_is_omap_h4()) -			hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; -		else { -			gpio_set_value(GPIO_TIMER, -					led_state & LED_TIMER_ON); -			goto done; -		} - -		break; -#endif - -#ifdef CONFIG_LEDS_CPU -	/* LED lit iff busy */ -	case led_idle_start: -		if (machine_is_omap_perseus2() || machine_is_omap_h4()) -			hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; -		else { -			gpio_set_value(GPIO_IDLE, 1); -			goto done; -		} - -		break; +static struct h2p2_dbg_fpga __iomem *fpga; -	case led_idle_end: -		if (machine_is_omap_perseus2() || machine_is_omap_h4()) -			hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; -		else { -			gpio_set_value(GPIO_IDLE, 0); -			goto done; -		} - -		break; -#endif - -	case led_green_on: -		hw_led_state |= H2P2_DBG_FPGA_LED_GREEN; -		break; -	case led_green_off: -		hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN; -		break; - -	case led_amber_on: -		hw_led_state |= H2P2_DBG_FPGA_LED_AMBER; -		break; -	case led_amber_off: -		hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER; -		break; - -	case led_red_on: -		hw_led_state |= H2P2_DBG_FPGA_LED_RED; -		break; -	case led_red_off: -		hw_led_state &= ~H2P2_DBG_FPGA_LED_RED; -		break; - -	case led_blue_on: -		hw_led_state |= H2P2_DBG_FPGA_LED_BLUE; -		break; -	case led_blue_off: -		hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE; -		break; - -	default: -		break; -	} - - -	/* -	 *  Actually burn the LEDs -	 */ -	if (led_state & LED_STATE_ENABLED) -		__raw_writew(~hw_led_state, &fpga->leds); - -done: -	spin_unlock_irqrestore(&lock, flags); -} - -/*-------------------------------------------------------------------------*/ - -/* "new" LED API - *  - with syfs access and generic triggering - *  - not readily accessible to in-kernel drivers - */ +static u16 fpga_led_state;  struct dbg_led {  	struct led_classdev	cdev;  	u16			mask;  }; -static struct dbg_led dbg_leds[] = { -	/* REVISIT at least H2 uses different timer & cpu leds... */ -#ifndef CONFIG_LEDS_TIMER -	{ .mask = 1 << 0,  .cdev.name =  "d4:green", -		.cdev.default_trigger = "heartbeat", }, -#endif -#ifndef CONFIG_LEDS_CPU -	{ .mask = 1 << 1,  .cdev.name =  "d5:green", },		/* !idle */ -#endif -	{ .mask = 1 << 2,  .cdev.name =  "d6:green", }, -	{ .mask = 1 << 3,  .cdev.name =  "d7:green", }, - -	{ .mask = 1 << 4,  .cdev.name =  "d8:green", }, -	{ .mask = 1 << 5,  .cdev.name =  "d9:green", }, -	{ .mask = 1 << 6,  .cdev.name = "d10:green", }, -	{ .mask = 1 << 7,  .cdev.name = "d11:green", }, - -	{ .mask = 1 << 8,  .cdev.name = "d12:green", }, -	{ .mask = 1 << 9,  .cdev.name = "d13:green", }, -	{ .mask = 1 << 10, .cdev.name = "d14:green", }, -	{ .mask = 1 << 11, .cdev.name = "d15:green", }, - -#ifndef	CONFIG_LEDS -	{ .mask = 1 << 12, .cdev.name = "d16:green", }, -	{ .mask = 1 << 13, .cdev.name = "d17:green", }, -	{ .mask = 1 << 14, .cdev.name = "d18:green", }, -	{ .mask = 1 << 15, .cdev.name = "d19:green", }, -#endif +static const struct { +	const char *name; +	const char *trigger; +} dbg_leds[] = { +	{ "dbg:d4", "heartbeat", }, +	{ "dbg:d5", "cpu0", }, +	{ "dbg:d6", "default-on", }, +	{ "dbg:d7", }, +	{ "dbg:d8", }, +	{ "dbg:d9", }, +	{ "dbg:d10", }, +	{ "dbg:d11", }, +	{ "dbg:d12", }, +	{ "dbg:d13", }, +	{ "dbg:d14", }, +	{ "dbg:d15", }, +	{ "dbg:d16", }, +	{ "dbg:d17", }, +	{ "dbg:d18", }, +	{ "dbg:d19", },  }; -static void -fpga_led_set(struct led_classdev *cdev, enum led_brightness value) +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static void dbg_led_set(struct led_classdev *cdev, +			      enum led_brightness b)  { -	struct dbg_led	*led = container_of(cdev, struct dbg_led, cdev); -	unsigned long	flags; +	struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); +	u16 reg; -	spin_lock_irqsave(&lock, flags); -	if (value == LED_OFF) -		hw_led_state &= ~led->mask; +	reg = __raw_readw(&fpga->leds); +	if (b != LED_OFF) +		reg |= led->mask;  	else -		hw_led_state |= led->mask; -	__raw_writew(~hw_led_state, &fpga->leds); -	spin_unlock_irqrestore(&lock, flags); +		reg &= ~led->mask; +	__raw_writew(reg, &fpga->leds);  } -static void __init newled_init(struct device *dev) +static enum led_brightness dbg_led_get(struct led_classdev *cdev)  { -	unsigned	i; -	struct dbg_led	*led; -	int		status; +	struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); +	u16 reg; -	for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) { -		led->cdev.brightness_set = fpga_led_set; -		status = led_classdev_register(dev, &led->cdev); -		if (status < 0) -			break; -	} -	return; +	reg = __raw_readw(&fpga->leds); +	return (reg & led->mask) ? LED_FULL : LED_OFF;  } - -/*-------------------------------------------------------------------------*/ - -static int /* __init */ fpga_probe(struct platform_device *pdev) +static int fpga_probe(struct platform_device *pdev)  {  	struct resource	*iomem; - -	spin_lock_init(&lock); +	int i;  	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!iomem)  		return -ENODEV;  	fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); -	__raw_writew(~0, &fpga->leds); +	__raw_writew(0xff, &fpga->leds); + +	for (i = 0; i < ARRAY_SIZE(dbg_leds); i++) { +		struct dbg_led *led; + +		led = kzalloc(sizeof(*led), GFP_KERNEL); +		if (!led) +			break; -#ifdef	CONFIG_LEDS -	leds_event = h2p2_dbg_leds_event; -	leds_event(led_start); -#endif +		led->cdev.name = dbg_leds[i].name; +		led->cdev.brightness_set = dbg_led_set; +		led->cdev.brightness_get = dbg_led_get; +		led->cdev.default_trigger = dbg_leds[i].trigger; +		led->mask = BIT(i); -	if (new_led_api()) { -		newled_init(&pdev->dev); +		if (led_classdev_register(NULL, &led->cdev) < 0) { +			kfree(led); +			break; +		}  	}  	return 0; @@ -281,13 +120,15 @@ static int /* __init */ fpga_probe(struct platform_device *pdev)  static int fpga_suspend_noirq(struct device *dev)  { -	__raw_writew(~0, &fpga->leds); +	fpga_led_state = __raw_readw(&fpga->leds); +	__raw_writew(0xff, &fpga->leds); +  	return 0;  }  static int fpga_resume_noirq(struct device *dev)  { -	__raw_writew(~hw_led_state, &fpga->leds); +	__raw_writew(~fpga_led_state, &fpga->leds);  	return 0;  } diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c index 4dcb11c3d89..60552e22f22 100644 --- a/arch/arm/plat-samsung/time.c +++ b/arch/arm/plat-samsung/time.c @@ -28,7 +28,6 @@  #include <linux/io.h>  #include <linux/platform_device.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/irq.h> diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig index 8d5c10a5084..2a4ae8a6a08 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig @@ -16,8 +16,10 @@ config PLAT_VERSATILE_FPGA_IRQ_NR         depends on PLAT_VERSATILE_FPGA_IRQ  config PLAT_VERSATILE_LEDS -	def_bool y if LEDS_CLASS +	def_bool y if NEW_LEDS  	depends on ARCH_REALVIEW || ARCH_VERSATILE +	select LEDS_CLASS +	select LEDS_TRIGGER  config PLAT_VERSATILE_SCHED_CLOCK  	def_bool y diff --git a/arch/arm/plat-versatile/leds.c b/arch/arm/plat-versatile/leds.c index 3169fa555ea..d2490d00b46 100644 --- a/arch/arm/plat-versatile/leds.c +++ b/arch/arm/plat-versatile/leds.c @@ -37,10 +37,10 @@ static const struct {  } versatile_leds[] = {  	{ "versatile:0", "heartbeat", },  	{ "versatile:1", "mmc0", }, -	{ "versatile:2", }, -	{ "versatile:3", }, -	{ "versatile:4", }, -	{ "versatile:5", }, +	{ "versatile:2", "cpu0" }, +	{ "versatile:3", "cpu1" }, +	{ "versatile:4", "cpu2" }, +	{ "versatile:5", "cpu3" },  	{ "versatile:6", },  	{ "versatile:7", },  }; diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index d45c3345b4a..a0e2f7d7035 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -30,7 +30,6 @@  #include <asm/hardware/dec21285.h>  #include <asm/io.h> -#include <asm/leds.h>  #include <asm/mach-types.h>  #include <asm/uaccess.h> @@ -179,9 +178,6 @@ static ssize_t flash_write(struct file *file, const char __user *buf,  	written = 0; -	leds_event(led_claim); -	leds_event(led_green_on); -  	nBlock = (int) p >> 16;	//block # of 64K bytes  	/* @@ -258,11 +254,6 @@ static ssize_t flash_write(struct file *file, const char __user *buf,  			printk(KERN_DEBUG "flash_write: written 0x%X bytes OK.\n", written);  	} -	/* -	 * restore reg on exit -	 */ -	leds_event(led_release); -  	mutex_unlock(&nwflash_mutex);  	return written; @@ -334,11 +325,6 @@ static int erase_block(int nBlock)  	int temp, temp1;  	/* -	 * orange LED == erase -	 */ -	leds_event(led_amber_on); - -	/*  	 * reset footbridge to the correct offset 0 (...0..3)  	 */  	*CSR_ROMWRITEREG = 0; @@ -446,12 +432,6 @@ static int write_block(unsigned long p, const char __user *buf, int count)  	unsigned long timeout;  	unsigned long timeout1; -	/* -	 * red LED == write -	 */ -	leds_event(led_amber_off); -	leds_event(led_red_on); -  	pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));  	/* @@ -558,17 +538,9 @@ static int write_block(unsigned long p, const char __user *buf, int count)  					       pWritePtr - FLASH_BASE);  				/* -				 * no LED == waiting -				 */ -				leds_event(led_amber_off); -				/*  				 * wait couple ms  				 */  				msleep(10); -				/* -				 * red LED == write -				 */ -				leds_event(led_red_on);  				goto WriteRetry;  			} else { @@ -583,12 +555,6 @@ static int write_block(unsigned long p, const char __user *buf, int count)  		}  	} -	/* -	 * green LED == read/verify -	 */ -	leds_event(led_amber_off); -	leds_event(led_green_on); -  	msleep(10);  	pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p)); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index c96bbaadeeb..16578d3b52b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -506,6 +506,16 @@ config LEDS_TRIGGER_BACKLIGHT  	  If unsure, say N. +config LEDS_TRIGGER_CPU +	bool "LED CPU Trigger" +	depends on LEDS_TRIGGERS +	help +	  This allows LEDs to be controlled by active CPUs. This shows +	  the active CPUs across an array of LEDs so you can see which +	  CPUs are active on the system at any given moment. + +	  If unsure, say N. +  config LEDS_TRIGGER_GPIO  	tristate "LED GPIO Trigger"  	depends on LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index a4429a9217b..a9b627c4f8b 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -61,5 +61,6 @@ obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)	+= ledtrig-ide-disk.o  obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+= ledtrig-heartbeat.o  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o  obj-$(CONFIG_LEDS_TRIGGER_GPIO)		+= ledtrig-gpio.o +obj-$(CONFIG_LEDS_TRIGGER_CPU)		+= ledtrig-cpu.o  obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o  obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)	+= ledtrig-transient.o diff --git a/drivers/leds/ledtrig-cpu.c b/drivers/leds/ledtrig-cpu.c new file mode 100644 index 00000000000..b312056da14 --- /dev/null +++ b/drivers/leds/ledtrig-cpu.c @@ -0,0 +1,163 @@ +/* + * ledtrig-cpu.c - LED trigger based on CPU activity + * + * This LED trigger will be registered for each possible CPU and named as + * cpu0, cpu1, cpu2, cpu3, etc. + * + * It can be bound to any LED just like other triggers using either a + * board file or via sysfs interface. + * + * An API named ledtrig_cpu is exported for any user, who want to add CPU + * activity indication in their code + * + * Copyright 2011 Linus Walleij <linus.walleij@linaro.org> + * Copyright 2011 - 2012 Bryan Wu <bryan.wu@canonical.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/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/percpu.h> +#include <linux/syscore_ops.h> +#include <linux/rwsem.h> +#include "leds.h" + +#define MAX_NAME_LEN	8 + +struct led_trigger_cpu { +	char name[MAX_NAME_LEN]; +	struct led_trigger *_trig; +	struct mutex lock; +	int lock_is_inited; +}; + +static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); + +/** + * ledtrig_cpu - emit a CPU event as a trigger + * @evt: CPU event to be emitted + * + * Emit a CPU event on a CPU core, which will trigger a + * binded LED to turn on or turn off. + */ +void ledtrig_cpu(enum cpu_led_event ledevt) +{ +	struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig); + +	/* mutex lock should be initialized before calling mutex_call() */ +	if (!trig->lock_is_inited) +		return; + +	mutex_lock(&trig->lock); + +	/* Locate the correct CPU LED */ +	switch (ledevt) { +	case CPU_LED_IDLE_END: +	case CPU_LED_START: +		/* Will turn the LED on, max brightness */ +		led_trigger_event(trig->_trig, LED_FULL); +		break; + +	case CPU_LED_IDLE_START: +	case CPU_LED_STOP: +	case CPU_LED_HALTED: +		/* Will turn the LED off */ +		led_trigger_event(trig->_trig, LED_OFF); +		break; + +	default: +		/* Will leave the LED as it is */ +		break; +	} + +	mutex_unlock(&trig->lock); +} +EXPORT_SYMBOL(ledtrig_cpu); + +static int ledtrig_cpu_syscore_suspend(void) +{ +	ledtrig_cpu(CPU_LED_STOP); +	return 0; +} + +static void ledtrig_cpu_syscore_resume(void) +{ +	ledtrig_cpu(CPU_LED_START); +} + +static void ledtrig_cpu_syscore_shutdown(void) +{ +	ledtrig_cpu(CPU_LED_HALTED); +} + +static struct syscore_ops ledtrig_cpu_syscore_ops = { +	.shutdown	= ledtrig_cpu_syscore_shutdown, +	.suspend	= ledtrig_cpu_syscore_suspend, +	.resume		= ledtrig_cpu_syscore_resume, +}; + +static int __init ledtrig_cpu_init(void) +{ +	int cpu; + +	/* Supports up to 9999 cpu cores */ +	BUILD_BUG_ON(CONFIG_NR_CPUS > 9999); + +	/* +	 * Registering CPU led trigger for each CPU core here +	 * ignores CPU hotplug, but after this CPU hotplug works +	 * fine with this trigger. +	 */ +	for_each_possible_cpu(cpu) { +		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu); + +		mutex_init(&trig->lock); + +		snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu); + +		mutex_lock(&trig->lock); +		led_trigger_register_simple(trig->name, &trig->_trig); +		trig->lock_is_inited = 1; +		mutex_unlock(&trig->lock); +	} + +	register_syscore_ops(&ledtrig_cpu_syscore_ops); + +	pr_info("ledtrig-cpu: registered to indicate activity on CPUs\n"); + +	return 0; +} +module_init(ledtrig_cpu_init); + +static void __exit ledtrig_cpu_exit(void) +{ +	int cpu; + +	for_each_possible_cpu(cpu) { +		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu); + +		mutex_lock(&trig->lock); + +		led_trigger_unregister_simple(trig->_trig); +		trig->_trig = NULL; +		memset(trig->name, 0, MAX_NAME_LEN); +		trig->lock_is_inited = 0; + +		mutex_unlock(&trig->lock); +		mutex_destroy(&trig->lock); +	} + +	unregister_syscore_ops(&ledtrig_cpu_syscore_ops); +} +module_exit(ledtrig_cpu_exit); + +MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); +MODULE_AUTHOR("Bryan Wu <bryan.wu@canonical.com>"); +MODULE_DESCRIPTION("CPU LED trigger"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds.h b/include/linux/leds.h index 3aade1d8f41..c6f8dad2ceb 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -237,4 +237,20 @@ struct gpio_led_platform_data {  struct platform_device *gpio_led_register_device(  		int id, const struct gpio_led_platform_data *pdata); +enum cpu_led_event { +	CPU_LED_IDLE_START,	/* CPU enters idle */ +	CPU_LED_IDLE_END,	/* CPU idle ends */ +	CPU_LED_START,		/* Machine starts, especially resume */ +	CPU_LED_STOP,		/* Machine stops, especially suspend */ +	CPU_LED_HALTED,		/* Machine shutdown */ +}; +#ifdef CONFIG_LEDS_TRIGGER_CPU +extern void ledtrig_cpu(enum cpu_led_event evt); +#else +static inline void ledtrig_cpu(enum cpu_led_event evt) +{ +	return; +} +#endif +  #endif		/* __LINUX_LEDS_H_INCLUDED */  |