/*
 * Driver for BCM6358 memory-mapped LEDs, based on leds-syscon.c
 *
 * Copyright 2015 Álvaro Fernández Rojas <noltari@gmail.com>
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>

#define BCM6358_REG_MODE		0x0
#define BCM6358_REG_CTRL		0x4

#define BCM6358_SLED_CLKDIV_MASK	3
#define BCM6358_SLED_CLKDIV_1		0
#define BCM6358_SLED_CLKDIV_2		1
#define BCM6358_SLED_CLKDIV_4		2
#define BCM6358_SLED_CLKDIV_8		3

#define BCM6358_SLED_POLARITY		BIT(2)
#define BCM6358_SLED_BUSY		BIT(3)

#define BCM6358_SLED_MAX_COUNT		32
#define BCM6358_SLED_WAIT		100

/**
 * struct bcm6358_led - state container for bcm6358 based LEDs
 * @cdev: LED class device for this LED
 * @mem: memory resource
 * @lock: memory lock
 * @pin: LED pin number
 * @active_low: LED is active low
 */
struct bcm6358_led {
	struct led_classdev cdev;
	void __iomem *mem;
	spinlock_t *lock;
	unsigned long pin;
	bool active_low;
};

static void bcm6358_led_write(void __iomem *reg, unsigned long data)
{
	iowrite32be(data, reg);
}

static unsigned long bcm6358_led_read(void __iomem *reg)
{
	return ioread32be(reg);
}

static unsigned long bcm6358_led_busy(void __iomem *mem)
{
	unsigned long val;

	while ((val = bcm6358_led_read(mem + BCM6358_REG_CTRL)) &
		BCM6358_SLED_BUSY)
		udelay(BCM6358_SLED_WAIT);

	return val;
}

static void bcm6358_led_mode(struct bcm6358_led *led, unsigned long value)
{
	unsigned long val;

	bcm6358_led_busy(led->mem);

	val = bcm6358_led_read(led->mem + BCM6358_REG_MODE);
	if ((led->active_low && value == LED_OFF) ||
	    (!led->active_low && value != LED_OFF))
		val |= BIT(led->pin);
	else
		val &= ~(BIT(led->pin));
	bcm6358_led_write(led->mem + BCM6358_REG_MODE, val);
}

static void bcm6358_led_set(struct led_classdev *led_cdev,
			    enum led_brightness value)
{
	struct bcm6358_led *led =
		container_of(led_cdev, struct bcm6358_led, cdev);
	unsigned long flags;

	spin_lock_irqsave(led->lock, flags);
	bcm6358_led_mode(led, value);
	spin_unlock_irqrestore(led->lock, flags);
}

static int bcm6358_led(struct device *dev, struct device_node *nc, u32 reg,
		       void __iomem *mem, spinlock_t *lock)
{
	struct bcm6358_led *led;
	unsigned long flags;
	const char *state;
	int rc;

	led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
	if (!led)
		return -ENOMEM;

	led->pin = reg;
	led->mem = mem;
	led->lock = lock;

	if (of_property_read_bool(nc, "active-low"))
		led->active_low = true;

	led->cdev.name = of_get_property(nc, "label", NULL) ? : nc->name;
	led->cdev.default_trigger = of_get_property(nc,
						    "linux,default-trigger",
						    NULL);

	spin_lock_irqsave(lock, flags);
	if (!of_property_read_string(nc, "default-state", &state)) {
		if (!strcmp(state, "on")) {
			led->cdev.brightness = LED_FULL;
		} else if (!strcmp(state, "keep")) {
			unsigned long val;

			bcm6358_led_busy(led->mem);

			val = bcm6358_led_read(led->mem + BCM6358_REG_MODE);
			val &= BIT(led->pin);
			if ((led->active_low && !val) ||
			    (!led->active_low && val))
				led->cdev.brightness = LED_FULL;
			else
				led->cdev.brightness = LED_OFF;
		} else {
			led->cdev.brightness = LED_OFF;
		}
	} else {
		led->cdev.brightness = LED_OFF;
	}
	bcm6358_led_mode(led, led->cdev.brightness);
	spin_unlock_irqrestore(lock, flags);

	led->cdev.brightness_set = bcm6358_led_set;

	rc = led_classdev_register(dev, &led->cdev);
	if (rc < 0)
		return rc;

	dev_dbg(dev, "registered LED %s\n", led->cdev.name);

	return 0;
}

static int bcm6358_leds_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = pdev->dev.of_node;
	struct device_node *child;
	struct resource *mem_r;
	void __iomem *mem;
	spinlock_t *lock; /* memory lock */
	unsigned long val;
	u32 clk_div;

	mem_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem_r)
		return -EINVAL;

	mem = devm_ioremap_resource(dev, mem_r);
	if (IS_ERR(mem))
		return PTR_ERR(mem);

	lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL);
	if (!lock)
		return -ENOMEM;

	spin_lock_init(lock);

	val = bcm6358_led_busy(mem);
	val &= ~(BCM6358_SLED_POLARITY | BCM6358_SLED_CLKDIV_MASK);
	if (of_property_read_bool(np, "brcm,clk-dat-low"))
		val |= BCM6358_SLED_POLARITY;
	of_property_read_u32(np, "brcm,clk-div", &clk_div);
	switch (clk_div) {
	case 8:
		val |= BCM6358_SLED_CLKDIV_8;
		break;
	case 4:
		val |= BCM6358_SLED_CLKDIV_4;
		break;
	case 2:
		val |= BCM6358_SLED_CLKDIV_2;
		break;
	default:
		val |= BCM6358_SLED_CLKDIV_1;
		break;
	}
	bcm6358_led_write(mem + BCM6358_REG_CTRL, val);

	for_each_available_child_of_node(np, child) {
		int rc;
		u32 reg;

		if (of_property_read_u32(child, "reg", &reg))
			continue;

		if (reg >= BCM6358_SLED_MAX_COUNT) {
			dev_err(dev, "invalid LED (%u >= %d)\n", reg,
				BCM6358_SLED_MAX_COUNT);
			continue;
		}

		rc = bcm6358_led(dev, child, reg, mem, lock);
		if (rc < 0)
			return rc;
	}

	return 0;
}

static const struct of_device_id bcm6358_leds_of_match[] = {
	{ .compatible = "brcm,bcm6358-leds", },
	{ },
};

static struct platform_driver bcm6358_leds_driver = {
	.probe = bcm6358_leds_probe,
	.driver = {
		.name = "leds-bcm6358",
		.of_match_table = bcm6358_leds_of_match,
	},
};

module_platform_driver(bcm6358_leds_driver);

MODULE_AUTHOR("Álvaro Fernández Rojas <noltari@gmail.com>");
MODULE_DESCRIPTION("LED driver for BCM6358 controllers");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:leds-bcm6358");
