/*
 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <dm.h>
#include <errno.h>
#include <led.h>
#include <asm/io.h>
#include <dm/lists.h>

#define LEDS_MAX		32
#define LEDS_WAIT		100

/* LED Mode register */
#define LED_MODE_REG		0x0
#define LED_MODE_OFF		0
#define LED_MODE_ON		1
#define LED_MODE_MASK		1

/* LED Control register */
#define LED_CTRL_REG		0x4
#define LED_CTRL_CLK_MASK	0x3
#define LED_CTRL_CLK_1		0
#define LED_CTRL_CLK_2		1
#define LED_CTRL_CLK_4		2
#define LED_CTRL_CLK_8		3
#define LED_CTRL_POL_SHIFT	2
#define LED_CTRL_POL_MASK	(1 << LED_CTRL_POL_SHIFT)
#define LED_CTRL_BUSY_SHIFT	3
#define LED_CTRL_BUSY_MASK	(1 << LED_CTRL_BUSY_SHIFT)

DECLARE_GLOBAL_DATA_PTR;

struct bcm6358_led_priv {
	void __iomem *regs;
	uint8_t pin;
	bool active_low;
};

static void bcm6358_led_busy(void __iomem *regs)
{
	while (readl_be(regs + LED_CTRL_REG) & LED_CTRL_BUSY_MASK)
		udelay(LEDS_WAIT);
}

static unsigned long bcm6358_led_get_mode(struct bcm6358_led_priv *priv)
{
	bcm6358_led_busy(priv->regs);

	return (readl_be(priv->regs + LED_MODE_REG) >> priv->pin) &
	       LED_MODE_MASK;
}

static int bcm6358_led_set_mode(struct bcm6358_led_priv *priv, uint8_t mode)
{
	bcm6358_led_busy(priv->regs);

	clrsetbits_be32(priv->regs + LED_MODE_REG,
			(LED_MODE_MASK << priv->pin),
			(mode << priv->pin));

	return 0;
}

static enum led_state_t bcm6358_led_get_state(struct udevice *dev)
{
	struct bcm6358_led_priv *priv = dev_get_priv(dev);
	enum led_state_t state = LEDST_OFF;

	switch (bcm6358_led_get_mode(priv)) {
	case LED_MODE_OFF:
		state = (priv->active_low ? LEDST_ON : LEDST_OFF);
		break;
	case LED_MODE_ON:
		state = (priv->active_low ? LEDST_OFF : LEDST_ON);
		break;
	}

	return state;
}

static int bcm6358_led_set_state(struct udevice *dev, enum led_state_t state)
{
	struct bcm6358_led_priv *priv = dev_get_priv(dev);
	unsigned long mode;

	switch (state) {
	case LEDST_OFF:
		mode = (priv->active_low ? LED_MODE_ON : LED_MODE_OFF);
		break;
	case LEDST_ON:
		mode = (priv->active_low ? LED_MODE_OFF : LED_MODE_ON);
		break;
	case LEDST_TOGGLE:
		if (bcm6358_led_get_state(dev) == LEDST_OFF)
			return bcm6358_led_set_state(dev, LEDST_ON);
		else
			return bcm6358_led_set_state(dev, LEDST_OFF);
		break;
	default:
		return -ENOSYS;
	}

	return bcm6358_led_set_mode(priv, mode);
}

static const struct led_ops bcm6358_led_ops = {
	.get_state = bcm6358_led_get_state,
	.set_state = bcm6358_led_set_state,
};

static int bcm6358_led_probe(struct udevice *dev)
{
	struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
	fdt_addr_t addr;
	fdt_size_t size;

	/* Top-level LED node */
	if (!uc_plat->label) {
		void __iomem *regs;
		unsigned int clk_div;
		u32 set_bits = 0;

		addr = devfdt_get_addr_size_index(dev, 0, &size);
		if (addr == FDT_ADDR_T_NONE)
			return -EINVAL;

		regs = ioremap(addr, size);

		if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
				    "brcm,clk-dat-low"))
			set_bits |= LED_CTRL_POL_MASK;
		clk_div = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
					  "brcm,clk-div", LED_CTRL_CLK_1);
		switch (clk_div) {
		case 8:
			set_bits |= LED_CTRL_CLK_8;
			break;
		case 4:
			set_bits |= LED_CTRL_CLK_4;
			break;
		case 2:
			set_bits |= LED_CTRL_CLK_2;
			break;
		default:
			set_bits |= LED_CTRL_CLK_1;
			break;
		}

		bcm6358_led_busy(regs);
		clrsetbits_be32(regs + LED_CTRL_REG,
				LED_CTRL_POL_MASK | LED_CTRL_CLK_MASK,
				set_bits);
	} else {
		struct bcm6358_led_priv *priv = dev_get_priv(dev);
		unsigned int pin;

		addr = devfdt_get_addr_size_index(dev_get_parent(dev), 0,
						  &size);
		if (addr == FDT_ADDR_T_NONE)
			return -EINVAL;

		pin = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), "reg",
				      LEDS_MAX);
		if (pin >= LEDS_MAX)
			return -EINVAL;

		priv->regs = ioremap(addr, size);
		priv->pin = pin;

		if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
				    "active-low"))
			priv->active_low = true;
	}

	return 0;
}

static int bcm6358_led_bind(struct udevice *parent)
{
	const void *blob = gd->fdt_blob;
	int node;

	for (node = fdt_first_subnode(blob, dev_of_offset(parent));
	     node > 0;
	     node = fdt_next_subnode(blob, node)) {
		struct led_uc_plat *uc_plat;
		struct udevice *dev;
		const char *label;
		int ret;

		label = fdt_getprop(blob, node, "label", NULL);
		if (!label) {
			debug("%s: node %s has no label\n", __func__,
			      fdt_get_name(blob, node, NULL));
			return -EINVAL;
		}

		ret = device_bind_driver_to_node(parent, "bcm6358-led",
						 fdt_get_name(blob, node, NULL),
						 node, &dev);
		if (ret)
			return ret;

		uc_plat = dev_get_uclass_platdata(dev);
		uc_plat->label = label;
	}

	return 0;
}

static const struct udevice_id bcm6358_led_ids[] = {
	{ .compatible = "brcm,bcm6358-leds" },
	{ /* sentinel */ }
};

U_BOOT_DRIVER(bcm6358_led) = {
	.name = "bcm6358-led",
	.id = UCLASS_LED,
	.of_match = bcm6358_led_ids,
	.bind = bcm6358_led_bind,
	.probe = bcm6358_led_probe,
	.priv_auto_alloc_size = sizeof(struct bcm6358_led_priv),
	.ops = &bcm6358_led_ops,
};
