diff options
Diffstat (limited to 'arch/arm/mach-footbridge/netwinder-hw.c')
-rw-r--r-- | arch/arm/mach-footbridge/netwinder-hw.c | 112 |
1 files changed, 98 insertions, 14 deletions
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index cac9f67e7da7..d2d14339c6c4 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c | |||
@@ -12,9 +12,10 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/slab.h> | ||
16 | #include <linux/leds.h> | ||
15 | 17 | ||
16 | #include <asm/hardware/dec21285.h> | 18 | #include <asm/hardware/dec21285.h> |
17 | #include <asm/leds.h> | ||
18 | #include <asm/mach-types.h> | 19 | #include <asm/mach-types.h> |
19 | #include <asm/setup.h> | 20 | #include <asm/setup.h> |
20 | #include <asm/system_misc.h> | 21 | #include <asm/system_misc.h> |
@@ -27,13 +28,6 @@ | |||
27 | #define GP1_IO_BASE 0x338 | 28 | #define GP1_IO_BASE 0x338 |
28 | #define GP2_IO_BASE 0x33a | 29 | #define GP2_IO_BASE 0x33a |
29 | 30 | ||
30 | |||
31 | #ifdef CONFIG_LEDS | ||
32 | #define DEFAULT_LEDS 0 | ||
33 | #else | ||
34 | #define DEFAULT_LEDS GPIO_GREEN_LED | ||
35 | #endif | ||
36 | |||
37 | /* | 31 | /* |
38 | * Winbond WB83977F accessibility stuff | 32 | * Winbond WB83977F accessibility stuff |
39 | */ | 33 | */ |
@@ -611,15 +605,9 @@ static void __init rwa010_init(void) | |||
611 | static int __init nw_hw_init(void) | 605 | static int __init nw_hw_init(void) |
612 | { | 606 | { |
613 | if (machine_is_netwinder()) { | 607 | if (machine_is_netwinder()) { |
614 | unsigned long flags; | ||
615 | |||
616 | wb977_init(); | 608 | wb977_init(); |
617 | cpld_init(); | 609 | cpld_init(); |
618 | rwa010_init(); | 610 | rwa010_init(); |
619 | |||
620 | raw_spin_lock_irqsave(&nw_gpio_lock, flags); | ||
621 | nw_gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS); | ||
622 | raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); | ||
623 | } | 611 | } |
624 | return 0; | 612 | return 0; |
625 | } | 613 | } |
@@ -672,6 +660,102 @@ static void netwinder_restart(char mode, const char *cmd) | |||
672 | } | 660 | } |
673 | } | 661 | } |
674 | 662 | ||
663 | /* LEDs */ | ||
664 | #if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) | ||
665 | struct netwinder_led { | ||
666 | struct led_classdev cdev; | ||
667 | u8 mask; | ||
668 | }; | ||
669 | |||
670 | /* | ||
671 | * The triggers lines up below will only be used if the | ||
672 | * LED triggers are compiled in. | ||
673 | */ | ||
674 | static const struct { | ||
675 | const char *name; | ||
676 | const char *trigger; | ||
677 | } netwinder_leds[] = { | ||
678 | { "netwinder:green", "heartbeat", }, | ||
679 | { "netwinder:red", "cpu0", }, | ||
680 | }; | ||
681 | |||
682 | /* | ||
683 | * The LED control in Netwinder is reversed: | ||
684 | * - setting bit means turn off LED | ||
685 | * - clearing bit means turn on LED | ||
686 | */ | ||
687 | static void netwinder_led_set(struct led_classdev *cdev, | ||
688 | enum led_brightness b) | ||
689 | { | ||
690 | struct netwinder_led *led = container_of(cdev, | ||
691 | struct netwinder_led, cdev); | ||
692 | unsigned long flags; | ||
693 | u32 reg; | ||
694 | |||
695 | spin_lock_irqsave(&nw_gpio_lock, flags); | ||
696 | reg = nw_gpio_read(); | ||
697 | if (b != LED_OFF) | ||
698 | reg &= ~led->mask; | ||
699 | else | ||
700 | reg |= led->mask; | ||
701 | nw_gpio_modify_op(led->mask, reg); | ||
702 | spin_unlock_irqrestore(&nw_gpio_lock, flags); | ||
703 | } | ||
704 | |||
705 | static enum led_brightness netwinder_led_get(struct led_classdev *cdev) | ||
706 | { | ||
707 | struct netwinder_led *led = container_of(cdev, | ||
708 | struct netwinder_led, cdev); | ||
709 | unsigned long flags; | ||
710 | u32 reg; | ||
711 | |||
712 | spin_lock_irqsave(&nw_gpio_lock, flags); | ||
713 | reg = nw_gpio_read(); | ||
714 | spin_unlock_irqrestore(&nw_gpio_lock, flags); | ||
715 | |||
716 | return (reg & led->mask) ? LED_OFF : LED_FULL; | ||
717 | } | ||
718 | |||
719 | static int __init netwinder_leds_init(void) | ||
720 | { | ||
721 | int i; | ||
722 | |||
723 | if (!machine_is_netwinder()) | ||
724 | return -ENODEV; | ||
725 | |||
726 | for (i = 0; i < ARRAY_SIZE(netwinder_leds); i++) { | ||
727 | struct netwinder_led *led; | ||
728 | |||
729 | led = kzalloc(sizeof(*led), GFP_KERNEL); | ||
730 | if (!led) | ||
731 | break; | ||
732 | |||
733 | led->cdev.name = netwinder_leds[i].name; | ||
734 | led->cdev.brightness_set = netwinder_led_set; | ||
735 | led->cdev.brightness_get = netwinder_led_get; | ||
736 | led->cdev.default_trigger = netwinder_leds[i].trigger; | ||
737 | |||
738 | if (i == 0) | ||
739 | led->mask = GPIO_GREEN_LED; | ||
740 | else | ||
741 | led->mask = GPIO_RED_LED; | ||
742 | |||
743 | if (led_classdev_register(NULL, &led->cdev) < 0) { | ||
744 | kfree(led); | ||
745 | break; | ||
746 | } | ||
747 | } | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | /* | ||
753 | * Since we may have triggers on any subsystem, defer registration | ||
754 | * until after subsystem_init. | ||
755 | */ | ||
756 | fs_initcall(netwinder_leds_init); | ||
757 | #endif | ||
758 | |||
675 | MACHINE_START(NETWINDER, "Rebel-NetWinder") | 759 | MACHINE_START(NETWINDER, "Rebel-NetWinder") |
676 | /* Maintainer: Russell King/Rebel.com */ | 760 | /* Maintainer: Russell King/Rebel.com */ |
677 | .atag_offset = 0x100, | 761 | .atag_offset = 0x100, |