Commit ae027ead authored by Atsushi Nemoto's avatar Atsushi Nemoto Committed by Ralf Baechle

MIPS: TXx9: IOC LED support

Add leds-gpio platform device for controlling LEDs connected to IOC on
RBTX49XX and JMR3927 board.
Signed-off-by: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 21e77df2
......@@ -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 */
......@@ -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 = {
......
......@@ -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 = {
......
......@@ -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 = {
......
......@@ -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 */
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment