]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/mips/txx9/generic/setup.c
MIPS: TXx9: IOC LED support
[linux-2.6-omap-h63xx.git] / arch / mips / txx9 / generic / setup.c
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 */