MIPS: TXx9: IOC LED support
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Mon, 1 Sep 2008 13:22:38 +0000 (22:22 +0900)
committerRalf Baechle <ralf@linux-mips.org>
Sat, 11 Oct 2008 15:18:49 +0000 (16:18 +0100)
Add leds-gpio platform device for controlling LEDs connected to IOC on
RBTX49XX and JMR3927 board.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/txx9/generic/setup.c
arch/mips/txx9/jmr3927/setup.c
arch/mips/txx9/rbtx4927/setup.c
arch/mips/txx9/rbtx4938/setup.c
include/asm-mips/txx9/generic.h
include/asm-mips/txx9/rbtx4927.h

index 118d716f7832e0bbcd59b88e3e328799b95735be..1ea06553a1e1f0385fe45ac93093f2a0207aec61 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 #include <linux/mtd/physmap.h>
+#include <linux/leds.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 #include <asm/reboot.h>
@@ -649,3 +650,113 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr,
                platform_device_put(pdev);
 #endif
 }
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static DEFINE_SPINLOCK(txx9_iocled_lock);
+
+#define TXX9_IOCLED_MAXLEDS 8
+
+struct txx9_iocled_data {
+       struct gpio_chip chip;
+       u8 cur_val;
+       void __iomem *mmioaddr;
+       struct gpio_led_platform_data pdata;
+       struct gpio_led leds[TXX9_IOCLED_MAXLEDS];
+       char names[TXX9_IOCLED_MAXLEDS][32];
+};
+
+static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset)
+{
+       struct txx9_iocled_data *data =
+               container_of(chip, struct txx9_iocled_data, chip);
+       return data->cur_val & (1 << offset);
+}
+
+static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset,
+                           int value)
+{
+       struct txx9_iocled_data *data =
+               container_of(chip, struct txx9_iocled_data, chip);
+       unsigned long flags;
+       spin_lock_irqsave(&txx9_iocled_lock, flags);
+       if (value)
+               data->cur_val |= 1 << offset;
+       else
+               data->cur_val &= ~(1 << offset);
+       writeb(data->cur_val, data->mmioaddr);
+       mmiowb();
+       spin_unlock_irqrestore(&txx9_iocled_lock, flags);
+}
+
+static int txx9_iocled_dir_in(struct gpio_chip *chip, unsigned int offset)
+{
+       return 0;
+}
+
+static int txx9_iocled_dir_out(struct gpio_chip *chip, unsigned int offset,
+                              int value)
+{
+       txx9_iocled_set(chip, offset, value);
+       return 0;
+}
+
+void __init txx9_iocled_init(unsigned long baseaddr,
+                            int basenum, unsigned int num, int lowactive,
+                            const char *color, char **deftriggers)
+{
+       struct txx9_iocled_data *iocled;
+       struct platform_device *pdev;
+       int i;
+       static char *default_triggers[] __initdata = {
+               "heartbeat",
+               "ide-disk",
+               "nand-disk",
+               NULL,
+       };
+
+       if (!deftriggers)
+               deftriggers = default_triggers;
+       iocled = kzalloc(sizeof(*iocled), GFP_KERNEL);
+       if (!iocled)
+               return;
+       iocled->mmioaddr = ioremap(baseaddr, 1);
+       if (!iocled->mmioaddr)
+               return;
+       iocled->chip.get = txx9_iocled_get;
+       iocled->chip.set = txx9_iocled_set;
+       iocled->chip.direction_input = txx9_iocled_dir_in;
+       iocled->chip.direction_output = txx9_iocled_dir_out;
+       iocled->chip.label = "iocled";
+       iocled->chip.base = basenum;
+       iocled->chip.ngpio = num;
+       if (gpiochip_add(&iocled->chip))
+               return;
+       if (basenum < 0)
+               basenum = iocled->chip.base;
+
+       pdev = platform_device_alloc("leds-gpio", basenum);
+       if (!pdev)
+               return;
+       iocled->pdata.num_leds = num;
+       iocled->pdata.leds = iocled->leds;
+       for (i = 0; i < num; i++) {
+               struct gpio_led *led = &iocled->leds[i];
+               snprintf(iocled->names[i], sizeof(iocled->names[i]),
+                        "iocled:%s:%u", color, i);
+               led->name = iocled->names[i];
+               led->gpio = basenum + i;
+               led->active_low = lowactive;
+               if (deftriggers && *deftriggers)
+                       led->default_trigger = *deftriggers++;
+       }
+       pdev->dev.platform_data = &iocled->pdata;
+       if (platform_device_add(pdev))
+               platform_device_put(pdev);
+}
+#else /* CONFIG_LEDS_GPIO */
+void __init txx9_iocled_init(unsigned long baseaddr,
+                            int basenum, unsigned int num, int lowactive,
+                            const char *color, char **deftriggers)
+{
+}
+#endif /* CONFIG_LEDS_GPIO */
index 0f3843c92cf72981affa0c26450ba8f693d17c49..25e50a7be3877692d1ffb8ec40c5f23aa17813fa 100644 (file)
@@ -200,10 +200,15 @@ static void __init jmr3927_mtd_init(void)
 
 static void __init jmr3927_device_init(void)
 {
+       unsigned long iocled_base = JMR3927_IOC_LED_ADDR - IO_BASE;
+#ifdef __LITTLE_ENDIAN
+       iocled_base |= 1;
+#endif
        __swizzle_addr_b = jmr3927_swizzle_addr_b;
        jmr3927_rtc_init();
        tx3927_wdt_init();
        jmr3927_mtd_init();
+       txx9_iocled_init(iocled_base, -1, 8, 1, "green", NULL);
 }
 
 struct txx9_board_vec jmr3927_vec __initdata = {
index abe32c1a79dce2f1a384ab7398e97361b3a68e27..4a74423b2ba80a49c4047a3aaf679209c039e620 100644 (file)
@@ -321,6 +321,7 @@ static void __init rbtx4927_device_init(void)
        rbtx4927_ne_init();
        tx4927_wdt_init();
        rbtx4927_mtd_init();
+       txx9_iocled_init(RBTX4927_LED_ADDR - IO_BASE, -1, 3, 1, "green", NULL);
 }
 
 struct txx9_board_vec rbtx4927_vec __initdata = {
index ec6e81258f7326207f4a15df92fd9ff5eb66d599..e077cc4d3a59b67c3ace6eea0832fa6f786173ca 100644 (file)
@@ -352,6 +352,7 @@ static void __init rbtx4938_device_init(void)
        rbtx4938_ne_init();
        tx4938_wdt_init();
        rbtx4938_mtd_init();
+       txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL);
 }
 
 struct txx9_board_vec rbtx4938_vec __initdata = {
index dc85515eac13659e2b909258ddb22fdc5d7efb3e..4316a3e57678e995219c8a8a4f4278adfe80baa2 100644 (file)
@@ -82,4 +82,8 @@ static inline unsigned int __fls8(unsigned char x)
        return r;
 }
 
+void txx9_iocled_init(unsigned long baseaddr,
+                     int basenum, unsigned int num, int lowactive,
+                     const char *color, char **deftriggers);
+
 #endif /* __ASM_TXX9_GENERIC_H */
index c6015463432e2df843fc5cde1358b9a794a441ef..b2adab3d1acceef690627a1feeff82338cc291ba 100644 (file)
@@ -34,6 +34,7 @@
 #define RBTX4927_PCIIO         0x16000000
 #define RBTX4927_PCIIO_SIZE    0x01000000
 
+#define RBTX4927_LED_ADDR      (IO_BASE + TXX9_CE(2) + 0x00001000)
 #define RBTX4927_IMASK_ADDR    (IO_BASE + TXX9_CE(2) + 0x00002000)
 #define RBTX4927_IMSTAT_ADDR   (IO_BASE + TXX9_CE(2) + 0x00002006)
 #define RBTX4927_SOFTINT_ADDR  (IO_BASE + TXX9_CE(2) + 0x00003000)