ARM: plat-versatile: convert LEDs to platform device
authorLinus Walleij <linus.walleij@linaro.org>
Thu, 27 Feb 2014 13:29:22 +0000 (14:29 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Thu, 27 Feb 2014 13:56:19 +0000 (14:56 +0100)
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>
arch/arm/mach-realview/core.c
arch/arm/mach-realview/core.h
arch/arm/mach-realview/realview_eb.c
arch/arm/mach-realview/realview_pb1176.c
arch/arm/mach-realview/realview_pb11mp.c
arch/arm/mach-realview/realview_pba8.c
arch/arm/mach-realview/realview_pbx.c
arch/arm/mach-versatile/core.c
arch/arm/plat-versatile/leds.c

index 1d5ee5c9a1dcd36624ab2c29d0a7111e7a3e1bdc..960b8dd78c4498f935fb841a510bb38736d09d4e 100644 (file)
@@ -148,6 +148,21 @@ struct platform_device realview_cf_device = {
        },
 };
 
+static struct resource realview_leds_resources[] = {
+       {
+               .start  = REALVIEW_SYS_BASE + REALVIEW_SYS_LED_OFFSET,
+               .end    = REALVIEW_SYS_BASE + REALVIEW_SYS_LED_OFFSET + 4,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+struct platform_device realview_leds_device = {
+       .name           = "versatile-leds",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(realview_leds_resources),
+       .resource       = realview_leds_resources,
+};
+
 static struct resource realview_i2c_resource = {
        .start          = REALVIEW_I2C_BASE,
        .end            = REALVIEW_I2C_BASE + SZ_4K - 1,
index 602ca5ec52c53a855e3bb6fa8ec2013486d28ba8..13dc830ef469a3587e22a54e1ad31a2b44a43737 100644 (file)
@@ -37,6 +37,7 @@ struct machine_desc;
 
 extern struct platform_device realview_flash_device;
 extern struct platform_device realview_cf_device;
+extern struct platform_device realview_leds_device;
 extern struct platform_device realview_i2c_device;
 extern struct mmci_platform_data realview_mmc0_plat_data;
 extern struct mmci_platform_data realview_mmc1_plat_data;
index c85ddb2a0ad09083e3e3c30901bc28bb3c807af2..6bb070e801287606466a54cd1e411d4b377570ef 100644 (file)
@@ -452,6 +452,7 @@ static void __init realview_eb_init(void)
        realview_flash_register(&realview_eb_flash_resource, 1);
        platform_device_register(&realview_i2c_device);
        platform_device_register(&char_lcd_device);
+       platform_device_register(&realview_leds_device);
        eth_device_register();
        realview_usb_register(realview_eb_isp1761_resources);
 
index c5eade76461be3cf2faa4d6dffbb9becc7cbb872..173f2c15de49ac6709d028d607fb0bb49a339df5 100644 (file)
@@ -367,6 +367,7 @@ static void __init realview_pb1176_init(void)
        realview_usb_register(realview_pb1176_isp1761_resources);
        platform_device_register(&pmu_device);
        platform_device_register(&char_lcd_device);
+       platform_device_register(&realview_leds_device);
 
        for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
                struct amba_device *d = amba_devs[i];
index f4b0962578feb94dd653033620bfed0fcfddeaac..bde7e6b1fd44ddba8cde40e13497b0bfc9f71314 100644 (file)
@@ -347,6 +347,7 @@ static void __init realview_pb11mp_init(void)
        realview_eth_register(NULL, realview_pb11mp_smsc911x_resources);
        platform_device_register(&realview_i2c_device);
        platform_device_register(&realview_cf_device);
+       platform_device_register(&realview_leds_device);
        realview_usb_register(realview_pb11mp_isp1761_resources);
        platform_device_register(&pmu_device);
 
index 10a3e1d76891315d6fce093a36d69618cbe48f44..4e57a8599265b6d69c70285a7573957f3da9347d 100644 (file)
@@ -289,6 +289,7 @@ static void __init realview_pba8_init(void)
        realview_eth_register(NULL, realview_pba8_smsc911x_resources);
        platform_device_register(&realview_i2c_device);
        platform_device_register(&realview_cf_device);
+       platform_device_register(&realview_leds_device);
        realview_usb_register(realview_pba8_isp1761_resources);
        platform_device_register(&pmu_device);
 
index 9d75493e3f0cc110751b168cadff78093b0d129f..72c96caebefa92fdfaac1f4cb19348b793a69631 100644 (file)
@@ -385,6 +385,7 @@ static void __init realview_pbx_init(void)
        realview_eth_register(NULL, realview_pbx_smsc911x_resources);
        platform_device_register(&realview_i2c_device);
        platform_device_register(&realview_cf_device);
+       platform_device_register(&realview_leds_device);
        realview_usb_register(realview_pbx_isp1761_resources);
 
        for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
index a335126ae18f3abc248d1373c2e39659a53431a9..b31878570a000b0e4156853b6c2a68b63a37bf57 100644 (file)
@@ -310,6 +310,21 @@ static struct platform_device char_lcd_device = {
        .resource       =       char_lcd_resources,
 };
 
+static struct resource leds_resources[] = {
+       {
+               .start  = VERSATILE_SYS_BASE + VERSATILE_SYS_LED_OFFSET,
+               .end    = VERSATILE_SYS_BASE + VERSATILE_SYS_LED_OFFSET + 4,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device leds_device = {
+       .name           = "versatile-leds",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(leds_resources),
+       .resource       = leds_resources,
+};
+
 /*
  * Clock handling
  */
@@ -795,6 +810,7 @@ void __init versatile_init(void)
        platform_device_register(&versatile_i2c_device);
        platform_device_register(&smc91x_device);
        platform_device_register(&char_lcd_device);
+       platform_device_register(&leds_device);
 
        for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
                struct amba_device *d = amba_devs[i];
index 2018f307f32eb4338c49324a173da8883faca996..80553022d661fcbd09e1a0048472deb5486b70ef 100644 (file)
@@ -7,22 +7,14 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/leds.h>
-
-#include <mach/hardware.h>
-#include <mach/platform.h>
-
-#ifdef VERSATILE_SYS_BASE
-#define LEDREG (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
-#endif
-
-#ifdef REALVIEW_SYS_BASE
-#define LEDREG (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET)
-#endif
+#include <linux/platform_device.h>
 
 struct versatile_led {
+       void __iomem            *base;
        struct led_classdev     cdev;
        u8                      mask;
 };
@@ -50,30 +42,37 @@ static void versatile_led_set(struct led_classdev *cdev,
 {
        struct versatile_led *led = container_of(cdev,
                                                 struct versatile_led, cdev);
-       u32 reg = readl(LEDREG);
+       u32 reg = readl(led->base);
 
        if (b != LED_OFF)
                reg |= led->mask;
        else
                reg &= ~led->mask;
-       writel(reg, LEDREG);
+       writel(reg, led->base);
 }
 
 static enum led_brightness versatile_led_get(struct led_classdev *cdev)
 {
        struct versatile_led *led = container_of(cdev,
                                                 struct versatile_led, cdev);
-       u32 reg = readl(LEDREG);
+       u32 reg = readl(led->base);
 
        return (reg & led->mask) ? LED_FULL : LED_OFF;
 }
 
-static int __init versatile_leds_init(void)
+static int versatile_leds_probe(struct platform_device *dev)
 {
        int i;
+       struct resource *res;
+       void __iomem *base;
+
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&dev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
 
        /* All off */
-       writel(0, LEDREG);
+       writel(0, base);
        for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) {
                struct versatile_led *led;
 
@@ -81,6 +80,7 @@ static int __init versatile_leds_init(void)
                if (!led)
                        break;
 
+               led->base = base;
                led->cdev.name = versatile_leds[i].name;
                led->cdev.brightness_set = versatile_led_set;
                led->cdev.brightness_get = versatile_led_get;
@@ -96,8 +96,15 @@ static int __init versatile_leds_init(void)
        return 0;
 }
 
-/*
- * Since we may have triggers on any subsystem, defer registration
- * until after subsystem_init.
- */
-fs_initcall(versatile_leds_init);
+static struct platform_driver versatile_leds_driver = {
+       .driver = {
+               .name   = "versatile-leds",
+       },
+       .probe = versatile_leds_probe,
+};
+
+module_platform_driver(versatile_leds_driver);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("ARM Versatile LED driver");
+MODULE_LICENSE("GPL v2");