Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+111 −0
Original line number Diff line number Diff line
@@ -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 */
+5 −0
Original line number Diff line number Diff line
@@ -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 = {
+1 −0
Original line number Diff line number Diff line
@@ -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 = {
+1 −0
Original line number Diff line number Diff line
@@ -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 = {
+4 −0
Original line number Diff line number Diff line
@@ -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 */
Loading