[PATCH 16/17] mach-sa1100: retire custom LED code

Bryan Wu bryan.wu at canonical.com
Mon Jul 11 10:36:49 EDT 2011


On Sun, Jul 10, 2011 at 5:24 PM, Russell King - ARM Linux
<linux at arm.linux.org.uk> wrote:
> On Wed, Jul 06, 2011 at 08:34:46PM +0800, Bryan Wu wrote:
>> diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
>> index 5778274..13e4e5d 100644
>> --- a/arch/arm/mach-sa1100/assabet.c
>> +++ b/arch/arm/mach-sa1100/assabet.c
>> @@ -19,6 +19,8 @@
>>  #include <linux/mtd/partitions.h>
>>  #include <linux/delay.h>
>>  #include <linux/mm.h>
>> +#include <linux/leds.h>
>> +#include <linux/slab.h>
>>
>>  #include <mach/hardware.h>
>>  #include <asm/mach-types.h>
>> @@ -445,6 +447,79 @@ static void __init assabet_map_io(void)
>>       sa1100_register_uart(2, 3);
>>  }
>>
>> +/* LEDs */
>> +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", "cpu",},
>> +     { "assabet:green", "heartbeat", },
>> +};
>> +
>> +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;
>> +
>> +     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);
>
> This is buggy.  init functions are called irrespective of what platform
> we're running on, so this means if assabet is built in to the kernel,
> then we'll register its LEDs and try to access the BCR register
> irrespective of whether we are on assabet or not.
>

Right, I got it. So if we are going to run a single binary for all the
sa1100 machines, how about we check the machine in each fs_initcall

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;

Thanks,

>> diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
>> index cfb7607..6f87258 100644
>> --- a/arch/arm/mach-sa1100/simpad.c
>> +++ b/arch/arm/mach-sa1100/simpad.c
>> @@ -13,6 +13,8 @@
>>  #include <linux/mtd/mtd.h>
>>  #include <linux/mtd/partitions.h>
>>  #include <linux/io.h>
>> +#include <linux/leds.h>
>> +#include <linux/slab.h>
>>
>>  #include <asm/irq.h>
>>  #include <mach/hardware.h>
>> @@ -205,7 +207,53 @@ static struct platform_device *devices[] __initdata = {
>>       &simpad_mq200fb
>>  };
>>
>> +/* LEDs */
>> +#define LED_GREEN    1
>>
>> +static void simpad_led_set(struct led_classdev *cdev,
>> +                           enum led_brightness b)
>> +{
>> +     if (b != LED_OFF)
>> +             set_cs3_bit(LED_GREEN);
>> +     else
>> +             clear_cs3_bit(LED_GREEN);
>> +}
>> +
>> +static enum led_brightness simpad_led_get(struct led_classdev *cdev)
>> +{
>> +     u32 reg = *(CS3BUSTYPE *)(CS3_BASE);
>> +
>> +     return (reg & LED_GREEN) ? LED_FULL : LED_OFF;
>> +}
>> +
>> +static int __init simpad_leds_init(void)
>> +{
>> +     struct led_classdev *simpad_led;
>> +     int ret;
>> +
>> +     simpad_led = kzalloc(sizeof(*simpad_led), GFP_KERNEL);
>> +     if (!simpad_led)
>> +             return -ENOMEM;
>> +
>> +     simpad_led->name = "simpad:green";
>> +     simpad_led->brightness_set = simpad_led_set;
>> +     simpad_led->brightness_get = simpad_led_get;
>> +     simpad_led->default_trigger = "heartbeat";
>> +
>> +     ret = led_classdev_register(NULL, simpad_led);
>> +     if (ret < 0) {
>> +             kfree(simpad_led);
>> +             return ret;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +/*
>> + * Since we may have triggers on any subsystem, defer registration
>> + * until after subsystem_init.
>> + */
>> +fs_initcall(simpad_leds_init);
>
> Looks like simpad is similarly afflicted.  I haven't gone through the
> rest to check for similar issues.
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>



-- 
Bryan Wu <bryan.wu at canonical.com>
Kernel Developer    +86.138-1617-6545 Mobile
Ubuntu Kernel Team
Canonical Ltd.      www.canonical.com
Ubuntu - Linux for human beings | www.ubuntu.com



More information about the linux-arm-kernel mailing list