/*
 * Driver for UniPhier AIDET (ARM Interrupt Detector)
 *
 * Copyright (C) 2017 Socionext Inc.
 *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>

#define UNIPHIER_AIDET_NR_IRQS		256

#define UNIPHIER_AIDET_DETCONF		0x04	/* inverter register base */

struct uniphier_aidet_priv {
	struct irq_domain *domain;
	void __iomem *reg_base;
	spinlock_t lock;
	u32 saved_vals[UNIPHIER_AIDET_NR_IRQS / 32];
};

static void uniphier_aidet_reg_update(struct uniphier_aidet_priv *priv,
				      unsigned int reg, u32 mask, u32 val)
{
	unsigned long flags;
	u32 tmp;

	spin_lock_irqsave(&priv->lock, flags);
	tmp = readl_relaxed(priv->reg_base + reg);
	tmp &= ~mask;
	tmp |= mask & val;
	writel_relaxed(tmp, priv->reg_base + reg);
	spin_unlock_irqrestore(&priv->lock, flags);
}

static void uniphier_aidet_detconf_update(struct uniphier_aidet_priv *priv,
					  unsigned long index, unsigned int val)
{
	unsigned int reg;
	u32 mask;

	reg = UNIPHIER_AIDET_DETCONF + index / 32 * 4;
	mask = BIT(index % 32);

	uniphier_aidet_reg_update(priv, reg, mask, val ? mask : 0);
}

static int uniphier_aidet_irq_set_type(struct irq_data *data, unsigned int type)
{
	struct uniphier_aidet_priv *priv = data->chip_data;
	unsigned int val;

	/* enable inverter for active low triggers */
	switch (type) {
	case IRQ_TYPE_EDGE_RISING:
	case IRQ_TYPE_LEVEL_HIGH:
		val = 0;
		break;
	case IRQ_TYPE_EDGE_FALLING:
		val = 1;
		type = IRQ_TYPE_EDGE_RISING;
		break;
	case IRQ_TYPE_LEVEL_LOW:
		val = 1;
		type = IRQ_TYPE_LEVEL_HIGH;
		break;
	default:
		return -EINVAL;
	}

	uniphier_aidet_detconf_update(priv, data->hwirq, val);

	return irq_chip_set_type_parent(data, type);
}

static struct irq_chip uniphier_aidet_irq_chip = {
	.name = "AIDET",
	.irq_mask = irq_chip_mask_parent,
	.irq_unmask = irq_chip_unmask_parent,
	.irq_eoi = irq_chip_eoi_parent,
	.irq_set_affinity = irq_chip_set_affinity_parent,
	.irq_set_type = uniphier_aidet_irq_set_type,
};

static int uniphier_aidet_domain_translate(struct irq_domain *domain,
					   struct irq_fwspec *fwspec,
					   unsigned long *out_hwirq,
					   unsigned int *out_type)
{
	if (WARN_ON(fwspec->param_count < 2))
		return -EINVAL;

	*out_hwirq = fwspec->param[0];
	*out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;

	return 0;
}

static int uniphier_aidet_domain_alloc(struct irq_domain *domain,
				       unsigned int virq, unsigned int nr_irqs,
				       void *arg)
{
	struct irq_fwspec parent_fwspec;
	irq_hw_number_t hwirq;
	unsigned int type;
	int ret;

	if (nr_irqs != 1)
		return -EINVAL;

	ret = uniphier_aidet_domain_translate(domain, arg, &hwirq, &type);
	if (ret)
		return ret;

	switch (type) {
	case IRQ_TYPE_EDGE_RISING:
	case IRQ_TYPE_LEVEL_HIGH:
		break;
	case IRQ_TYPE_EDGE_FALLING:
		type = IRQ_TYPE_EDGE_RISING;
		break;
	case IRQ_TYPE_LEVEL_LOW:
		type = IRQ_TYPE_LEVEL_HIGH;
		break;
	default:
		return -EINVAL;
	}

	if (hwirq >= UNIPHIER_AIDET_NR_IRQS)
		return -ENXIO;

	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
					    &uniphier_aidet_irq_chip,
					    domain->host_data);
	if (ret)
		return ret;

	/* parent is GIC */
	parent_fwspec.fwnode = domain->parent->fwnode;
	parent_fwspec.param_count = 3;
	parent_fwspec.param[0] = 0;		/* SPI */
	parent_fwspec.param[1] = hwirq;
	parent_fwspec.param[2] = type;

	return irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec);
}

static const struct irq_domain_ops uniphier_aidet_domain_ops = {
	.alloc = uniphier_aidet_domain_alloc,
	.free = irq_domain_free_irqs_common,
	.translate = uniphier_aidet_domain_translate,
};

static int uniphier_aidet_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *parent_np;
	struct irq_domain *parent_domain;
	struct uniphier_aidet_priv *priv;
	struct resource *res;

	parent_np = of_irq_find_parent(dev->of_node);
	if (!parent_np)
		return -ENXIO;

	parent_domain = irq_find_host(parent_np);
	of_node_put(parent_np);
	if (!parent_domain)
		return -EPROBE_DEFER;

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

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	priv->reg_base = devm_ioremap_resource(dev, res);
	if (IS_ERR(priv->reg_base))
		return PTR_ERR(priv->reg_base);

	spin_lock_init(&priv->lock);

	priv->domain = irq_domain_create_hierarchy(
					parent_domain, 0,
					UNIPHIER_AIDET_NR_IRQS,
					of_node_to_fwnode(dev->of_node),
					&uniphier_aidet_domain_ops, priv);
	if (!priv->domain)
		return -ENOMEM;

	platform_set_drvdata(pdev, priv);

	return 0;
}

static int __maybe_unused uniphier_aidet_suspend(struct device *dev)
{
	struct uniphier_aidet_priv *priv = dev_get_drvdata(dev);
	int i;

	for (i = 0; i < ARRAY_SIZE(priv->saved_vals); i++)
		priv->saved_vals[i] = readl_relaxed(
			priv->reg_base + UNIPHIER_AIDET_DETCONF + i * 4);

	return 0;
}

static int __maybe_unused uniphier_aidet_resume(struct device *dev)
{
	struct uniphier_aidet_priv *priv = dev_get_drvdata(dev);
	int i;

	for (i = 0; i < ARRAY_SIZE(priv->saved_vals); i++)
		writel_relaxed(priv->saved_vals[i],
			       priv->reg_base + UNIPHIER_AIDET_DETCONF + i * 4);

	return 0;
}

static const struct dev_pm_ops uniphier_aidet_pm_ops = {
	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(uniphier_aidet_suspend,
				      uniphier_aidet_resume)
};

static const struct of_device_id uniphier_aidet_match[] = {
	{ .compatible = "socionext,uniphier-ld4-aidet" },
	{ .compatible = "socionext,uniphier-pro4-aidet" },
	{ .compatible = "socionext,uniphier-sld8-aidet" },
	{ .compatible = "socionext,uniphier-pro5-aidet" },
	{ .compatible = "socionext,uniphier-pxs2-aidet" },
	{ .compatible = "socionext,uniphier-ld11-aidet" },
	{ .compatible = "socionext,uniphier-ld20-aidet" },
	{ .compatible = "socionext,uniphier-pxs3-aidet" },
	{ /* sentinel */ }
};

static struct platform_driver uniphier_aidet_driver = {
	.probe = uniphier_aidet_probe,
	.driver = {
		.name = "uniphier-aidet",
		.of_match_table = uniphier_aidet_match,
		.pm = &uniphier_aidet_pm_ops,
	},
};
builtin_platform_driver(uniphier_aidet_driver);
