diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2014-02-27 08:29:22 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-02-27 08:56:19 -0500 |
commit | e4ecf2bda239ddef5f4edd0e05d48bfdf88a475d (patch) | |
tree | cda31855444c116394cec653eef7ffbc833823b9 /arch/arm/plat-versatile | |
parent | d1cb3ecf327066137fb6245b13030cde60241dd6 (diff) |
ARM: plat-versatile: convert LEDs to platform device
The LEDs were initialized unconditionally with an fs_initcall()
which doesn't play well with multiplatform. Convert the driver
to a platform device and convert all boards with these LEDs
to register a platform device and pass the register as a
resource instead.
Tested successfully on the Versatile/AB and RealView PB1176.
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Pawel Moll <pawel.moll@arm.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch/arm/plat-versatile')
-rw-r--r-- | arch/arm/plat-versatile/leds.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/arch/arm/plat-versatile/leds.c b/arch/arm/plat-versatile/leds.c index 2018f307f32e..80553022d661 100644 --- a/arch/arm/plat-versatile/leds.c +++ b/arch/arm/plat-versatile/leds.c | |||
@@ -7,22 +7,14 @@ | |||
7 | */ | 7 | */ |
8 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/module.h> | ||
10 | #include <linux/io.h> | 11 | #include <linux/io.h> |
11 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
12 | #include <linux/leds.h> | 13 | #include <linux/leds.h> |
13 | 14 | #include <linux/platform_device.h> | |
14 | #include <mach/hardware.h> | ||
15 | #include <mach/platform.h> | ||
16 | |||
17 | #ifdef VERSATILE_SYS_BASE | ||
18 | #define LEDREG (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) | ||
19 | #endif | ||
20 | |||
21 | #ifdef REALVIEW_SYS_BASE | ||
22 | #define LEDREG (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET) | ||
23 | #endif | ||
24 | 15 | ||
25 | struct versatile_led { | 16 | struct versatile_led { |
17 | void __iomem *base; | ||
26 | struct led_classdev cdev; | 18 | struct led_classdev cdev; |
27 | u8 mask; | 19 | u8 mask; |
28 | }; | 20 | }; |
@@ -50,30 +42,37 @@ static void versatile_led_set(struct led_classdev *cdev, | |||
50 | { | 42 | { |
51 | struct versatile_led *led = container_of(cdev, | 43 | struct versatile_led *led = container_of(cdev, |
52 | struct versatile_led, cdev); | 44 | struct versatile_led, cdev); |
53 | u32 reg = readl(LEDREG); | 45 | u32 reg = readl(led->base); |
54 | 46 | ||
55 | if (b != LED_OFF) | 47 | if (b != LED_OFF) |
56 | reg |= led->mask; | 48 | reg |= led->mask; |
57 | else | 49 | else |
58 | reg &= ~led->mask; | 50 | reg &= ~led->mask; |
59 | writel(reg, LEDREG); | 51 | writel(reg, led->base); |
60 | } | 52 | } |
61 | 53 | ||
62 | static enum led_brightness versatile_led_get(struct led_classdev *cdev) | 54 | static enum led_brightness versatile_led_get(struct led_classdev *cdev) |
63 | { | 55 | { |
64 | struct versatile_led *led = container_of(cdev, | 56 | struct versatile_led *led = container_of(cdev, |
65 | struct versatile_led, cdev); | 57 | struct versatile_led, cdev); |
66 | u32 reg = readl(LEDREG); | 58 | u32 reg = readl(led->base); |
67 | 59 | ||
68 | return (reg & led->mask) ? LED_FULL : LED_OFF; | 60 | return (reg & led->mask) ? LED_FULL : LED_OFF; |
69 | } | 61 | } |
70 | 62 | ||
71 | static int __init versatile_leds_init(void) | 63 | static int versatile_leds_probe(struct platform_device *dev) |
72 | { | 64 | { |
73 | int i; | 65 | int i; |
66 | struct resource *res; | ||
67 | void __iomem *base; | ||
68 | |||
69 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
70 | base = devm_ioremap_resource(&dev->dev, res); | ||
71 | if (IS_ERR(base)) | ||
72 | return PTR_ERR(base); | ||
74 | 73 | ||
75 | /* All off */ | 74 | /* All off */ |
76 | writel(0, LEDREG); | 75 | writel(0, base); |
77 | for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) { | 76 | for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) { |
78 | struct versatile_led *led; | 77 | struct versatile_led *led; |
79 | 78 | ||
@@ -81,6 +80,7 @@ static int __init versatile_leds_init(void) | |||
81 | if (!led) | 80 | if (!led) |
82 | break; | 81 | break; |
83 | 82 | ||
83 | led->base = base; | ||
84 | led->cdev.name = versatile_leds[i].name; | 84 | led->cdev.name = versatile_leds[i].name; |
85 | led->cdev.brightness_set = versatile_led_set; | 85 | led->cdev.brightness_set = versatile_led_set; |
86 | led->cdev.brightness_get = versatile_led_get; | 86 | led->cdev.brightness_get = versatile_led_get; |
@@ -96,8 +96,15 @@ static int __init versatile_leds_init(void) | |||
96 | return 0; | 96 | return 0; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* | 99 | static struct platform_driver versatile_leds_driver = { |
100 | * Since we may have triggers on any subsystem, defer registration | 100 | .driver = { |
101 | * until after subsystem_init. | 101 | .name = "versatile-leds", |
102 | */ | 102 | }, |
103 | fs_initcall(versatile_leds_init); | 103 | .probe = versatile_leds_probe, |
104 | }; | ||
105 | |||
106 | module_platform_driver(versatile_leds_driver); | ||
107 | |||
108 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); | ||
109 | MODULE_DESCRIPTION("ARM Versatile LED driver"); | ||
110 | MODULE_LICENSE("GPL v2"); | ||