// SPDX-License-Identifier: GPL-2.0
/*
 * Device driver for irqs in HISI PMIC IC
 *
 * Copyright (c) 2013 Linaro Ltd.
 * Copyright (c) 2011 Hisilicon.
 * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd.
 */

#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/irqdomain.h>
#include <linux/regmap.h>

struct hi6421v600_irq {
	struct device		*dev;
	struct irq_domain	*domain;
	int			irq;
	unsigned int		*irqs;
	struct regmap		*regmap;

	/* Protect IRQ mask changes */
	spinlock_t		lock;
};

enum hi6421v600_irq_list {
	OTMP = 0,
	VBUS_CONNECT,
	VBUS_DISCONNECT,
	ALARMON_R,
	HOLD_6S,
	HOLD_1S,
	POWERKEY_UP,
	POWERKEY_DOWN,
	OCP_SCP_R,
	COUL_R,
	SIM0_HPD_R,
	SIM0_HPD_F,
	SIM1_HPD_R,
	SIM1_HPD_F,

	PMIC_IRQ_LIST_MAX
};

#define HISI_IRQ_BANK_SIZE		2

/*
 * IRQ number for the power key button and mask for both UP and DOWN IRQs
 */
#define HISI_POWERKEY_IRQ_NUM		0
#define HISI_IRQ_POWERKEY_UP_DOWN	(BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))

/*
 * Registers for IRQ address and IRQ mask bits
 *
 * Please notice that we need to regmap a larger region, as other
 * registers are used by the irqs.
 * See drivers/irq/hi6421-irq.c.
 */
#define SOC_PMIC_IRQ_MASK_0_ADDR	0x0202
#define SOC_PMIC_IRQ0_ADDR		0x0212

/*
 * The IRQs are mapped as:
 *
 *	======================  =============   ============	=====
 *	IRQ			MASK REGISTER	IRQ REGISTER	BIT
 *	======================  =============   ============	=====
 *	OTMP			0x0202		0x212		bit 0
 *	VBUS_CONNECT		0x0202		0x212		bit 1
 *	VBUS_DISCONNECT		0x0202		0x212		bit 2
 *	ALARMON_R		0x0202		0x212		bit 3
 *	HOLD_6S			0x0202		0x212		bit 4
 *	HOLD_1S			0x0202		0x212		bit 5
 *	POWERKEY_UP		0x0202		0x212		bit 6
 *	POWERKEY_DOWN		0x0202		0x212		bit 7
 *
 *	OCP_SCP_R		0x0203		0x213		bit 0
 *	COUL_R			0x0203		0x213		bit 1
 *	SIM0_HPD_R		0x0203		0x213		bit 2
 *	SIM0_HPD_F		0x0203		0x213		bit 3
 *	SIM1_HPD_R		0x0203		0x213		bit 4
 *	SIM1_HPD_F		0x0203		0x213		bit 5
 *	======================  =============   ============	=====
 *
 * Each mask register contains 8 bits. The ancillary macros below
 * convert a number from 0 to 14 into a register address and a bit mask
 */
#define HISI_IRQ_MASK_REG(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
					 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
#define HISI_IRQ_MASK_BIT(irq_data)	BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
#define HISI_8BITS_MASK			0xff

static irqreturn_t hi6421v600_irq_handler(int irq, void *__priv)
{
	struct hi6421v600_irq *priv = __priv;
	unsigned long pending;
	unsigned int in;
	int i, offset;

	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
		regmap_read(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);

		/* Mark pending IRQs as handled */
		regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, in);

		pending = in & HISI_8BITS_MASK;

		if (i == HISI_POWERKEY_IRQ_NUM &&
		    (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) {
			/*
			 * If both powerkey down and up IRQs are received,
			 * handle them at the right order
			 */
			generic_handle_irq_safe(priv->irqs[POWERKEY_DOWN]);
			generic_handle_irq_safe(priv->irqs[POWERKEY_UP]);
			pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
		}

		if (!pending)
			continue;

		for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
			generic_handle_irq_safe(priv->irqs[offset + i * BITS_PER_BYTE]);
		}
	}

	return IRQ_HANDLED;
}

static void hi6421v600_irq_mask(struct irq_data *d)
{
	struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d);
	unsigned long flags;
	unsigned int data;
	u32 offset;

	offset = HISI_IRQ_MASK_REG(d);

	spin_lock_irqsave(&priv->lock, flags);

	regmap_read(priv->regmap, offset, &data);
	data |= HISI_IRQ_MASK_BIT(d);
	regmap_write(priv->regmap, offset, data);

	spin_unlock_irqrestore(&priv->lock, flags);
}

static void hi6421v600_irq_unmask(struct irq_data *d)
{
	struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d);
	u32 data, offset;
	unsigned long flags;

	offset = HISI_IRQ_MASK_REG(d);

	spin_lock_irqsave(&priv->lock, flags);

	regmap_read(priv->regmap, offset, &data);
	data &= ~HISI_IRQ_MASK_BIT(d);
	regmap_write(priv->regmap, offset, data);

	spin_unlock_irqrestore(&priv->lock, flags);
}

static struct irq_chip hi6421v600_pmu_irqchip = {
	.name		= "hi6421v600-irq",
	.irq_mask	= hi6421v600_irq_mask,
	.irq_unmask	= hi6421v600_irq_unmask,
	.irq_disable	= hi6421v600_irq_mask,
	.irq_enable	= hi6421v600_irq_unmask,
};

static int hi6421v600_irq_map(struct irq_domain *d, unsigned int virq,
			      irq_hw_number_t hw)
{
	struct hi6421v600_irq *priv = d->host_data;

	irq_set_chip_and_handler_name(virq, &hi6421v600_pmu_irqchip,
				      handle_simple_irq, "hi6421v600");
	irq_set_chip_data(virq, priv);
	irq_set_irq_type(virq, IRQ_TYPE_NONE);

	return 0;
}

static const struct irq_domain_ops hi6421v600_domain_ops = {
	.map	= hi6421v600_irq_map,
	.xlate	= irq_domain_xlate_twocell,
};

static void hi6421v600_irq_init(struct hi6421v600_irq *priv)
{
	int i;
	unsigned int pending;

	/* Mask all IRQs */
	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
		regmap_write(priv->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
			     HISI_8BITS_MASK);

	/* Mark all IRQs as handled */
	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
		regmap_read(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
		regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i,
			     HISI_8BITS_MASK);
	}
}

static int hi6421v600_irq_probe(struct platform_device *pdev)
{
	struct device *pmic_dev = pdev->dev.parent;
	struct device_node *np = pmic_dev->of_node;
	struct platform_device *pmic_pdev;
	struct device *dev = &pdev->dev;
	struct hi6421v600_irq *priv;
	struct regmap *regmap;
	unsigned int virq;
	int i, ret;

	/*
	 * This driver is meant to be called by hi6421-spmi-core,
	 * which should first set drvdata. If this doesn't happen, hit
	 * a warn on and return.
	 */
	regmap = dev_get_drvdata(pmic_dev);
	if (WARN_ON(!regmap))
		return -ENODEV;

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

	priv->dev = dev;
	priv->regmap = regmap;

	spin_lock_init(&priv->lock);

	pmic_pdev = container_of(pmic_dev, struct platform_device, dev);

	priv->irq = platform_get_irq(pmic_pdev, 0);
	if (priv->irq < 0)
		return priv->irq;

	platform_set_drvdata(pdev, priv);

	hi6421v600_irq_init(priv);

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

	priv->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
					     &hi6421v600_domain_ops, priv);
	if (!priv->domain) {
		dev_err(dev, "Failed to create IRQ domain\n");
		return -ENODEV;
	}

	for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
		virq = irq_create_mapping(priv->domain, i);
		if (!virq) {
			dev_err(dev, "Failed to map H/W IRQ\n");
			return -ENODEV;
		}
		priv->irqs[i] = virq;
	}

	ret = devm_request_threaded_irq(dev,
					priv->irq, hi6421v600_irq_handler,
					NULL,
					IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
					"pmic", priv);
	if (ret < 0) {
		dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
			ret);
		return ret;
	}

	return 0;
}

static const struct platform_device_id hi6421v600_irq_table[] = {
	{ .name = "hi6421v600-irq" },
	{},
};
MODULE_DEVICE_TABLE(platform, hi6421v600_irq_table);

static struct platform_driver hi6421v600_irq_driver = {
	.id_table = hi6421v600_irq_table,
	.driver = {
		.name = "hi6421v600-irq",
	},
	.probe	= hi6421v600_irq_probe,
};
module_platform_driver(hi6421v600_irq_driver);

MODULE_DESCRIPTION("HiSilicon Hi6421v600 IRQ driver");
MODULE_LICENSE("GPL v2");
