/*
 * Copyright 2017 Google Inc
 *
 * 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.
 *
 * Provides a simple driver to control the ASPEED LPC snoop interface which
 * allows the BMC to listen on and save the data written by
 * the host to an arbitrary LPC I/O port.
 *
 * Typically used by the BMC to "watch" host boot progress via port
 * 0x80 writes made by the BIOS during the boot process.
 */

#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/kfifo.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

#define DEVICE_NAME	"aspeed-lpc-snoop"

#define NUM_SNOOP_CHANNELS 2
#define SNOOP_FIFO_SIZE 2048

#define HICR5	0x0
#define HICR5_EN_SNP0W		BIT(0)
#define HICR5_ENINT_SNP0W	BIT(1)
#define HICR5_EN_SNP1W		BIT(2)
#define HICR5_ENINT_SNP1W	BIT(3)

#define HICR6	0x4
#define HICR6_STR_SNP0W		BIT(0)
#define HICR6_STR_SNP1W		BIT(1)
#define SNPWADR	0x10
#define SNPWADR_CH0_MASK	GENMASK(15, 0)
#define SNPWADR_CH0_SHIFT	0
#define SNPWADR_CH1_MASK	GENMASK(31, 16)
#define SNPWADR_CH1_SHIFT	16
#define SNPWDR	0x14
#define SNPWDR_CH0_MASK		GENMASK(7, 0)
#define SNPWDR_CH0_SHIFT	0
#define SNPWDR_CH1_MASK		GENMASK(15, 8)
#define SNPWDR_CH1_SHIFT	8
#define HICRB	0x80
#define HICRB_ENSNP0D		BIT(14)
#define HICRB_ENSNP1D		BIT(15)

struct aspeed_lpc_snoop_model_data {
	/* The ast2400 has bits 14 and 15 as reserved, whereas the ast2500
	 * can use them.
	 */
	unsigned int has_hicrb_ensnp;
};

struct aspeed_lpc_snoop {
	struct regmap		*regmap;
	int			irq;
	struct kfifo		snoop_fifo[NUM_SNOOP_CHANNELS];
};

/* Save a byte to a FIFO and discard the oldest byte if FIFO is full */
static void put_fifo_with_discard(struct kfifo *fifo, u8 val)
{
	if (!kfifo_initialized(fifo))
		return;
	if (kfifo_is_full(fifo))
		kfifo_skip(fifo);
	kfifo_put(fifo, val);
}

static irqreturn_t aspeed_lpc_snoop_irq(int irq, void *arg)
{
	struct aspeed_lpc_snoop *lpc_snoop = arg;
	u32 reg, data;

	if (regmap_read(lpc_snoop->regmap, HICR6, &reg))
		return IRQ_NONE;

	/* Check if one of the snoop channels is interrupting */
	reg &= (HICR6_STR_SNP0W | HICR6_STR_SNP1W);
	if (!reg)
		return IRQ_NONE;

	/* Ack pending IRQs */
	regmap_write(lpc_snoop->regmap, HICR6, reg);

	/* Read and save most recent snoop'ed data byte to FIFO */
	regmap_read(lpc_snoop->regmap, SNPWDR, &data);

	if (reg & HICR6_STR_SNP0W) {
		u8 val = (data & SNPWDR_CH0_MASK) >> SNPWDR_CH0_SHIFT;

		put_fifo_with_discard(&lpc_snoop->snoop_fifo[0], val);
	}
	if (reg & HICR6_STR_SNP1W) {
		u8 val = (data & SNPWDR_CH1_MASK) >> SNPWDR_CH1_SHIFT;

		put_fifo_with_discard(&lpc_snoop->snoop_fifo[1], val);
	}

	return IRQ_HANDLED;
}

static int aspeed_lpc_snoop_config_irq(struct aspeed_lpc_snoop *lpc_snoop,
				       struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	int rc;

	lpc_snoop->irq = platform_get_irq(pdev, 0);
	if (!lpc_snoop->irq)
		return -ENODEV;

	rc = devm_request_irq(dev, lpc_snoop->irq,
			      aspeed_lpc_snoop_irq, IRQF_SHARED,
			      DEVICE_NAME, lpc_snoop);
	if (rc < 0) {
		dev_warn(dev, "Unable to request IRQ %d\n", lpc_snoop->irq);
		lpc_snoop->irq = 0;
		return rc;
	}

	return 0;
}

static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
				   struct device *dev,
				   int channel, u16 lpc_port)
{
	int rc = 0;
	u32 hicr5_en, snpwadr_mask, snpwadr_shift, hicrb_en;
	const struct aspeed_lpc_snoop_model_data *model_data =
		of_device_get_match_data(dev);

	/* Create FIFO datastructure */
	rc = kfifo_alloc(&lpc_snoop->snoop_fifo[channel],
			 SNOOP_FIFO_SIZE, GFP_KERNEL);
	if (rc)
		return rc;

	/* Enable LPC snoop channel at requested port */
	switch (channel) {
	case 0:
		hicr5_en = HICR5_EN_SNP0W | HICR5_ENINT_SNP0W;
		snpwadr_mask = SNPWADR_CH0_MASK;
		snpwadr_shift = SNPWADR_CH0_SHIFT;
		hicrb_en = HICRB_ENSNP0D;
		break;
	case 1:
		hicr5_en = HICR5_EN_SNP1W | HICR5_ENINT_SNP1W;
		snpwadr_mask = SNPWADR_CH1_MASK;
		snpwadr_shift = SNPWADR_CH1_SHIFT;
		hicrb_en = HICRB_ENSNP1D;
		break;
	default:
		return -EINVAL;
	}

	regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en);
	regmap_update_bits(lpc_snoop->regmap, SNPWADR, snpwadr_mask,
			   lpc_port << snpwadr_shift);
	if (model_data->has_hicrb_ensnp)
		regmap_update_bits(lpc_snoop->regmap, HICRB,
				hicrb_en, hicrb_en);

	return rc;
}

static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
				     int channel)
{
	switch (channel) {
	case 0:
		regmap_update_bits(lpc_snoop->regmap, HICR5,
				   HICR5_EN_SNP0W | HICR5_ENINT_SNP0W,
				   0);
		break;
	case 1:
		regmap_update_bits(lpc_snoop->regmap, HICR5,
				   HICR5_EN_SNP1W | HICR5_ENINT_SNP1W,
				   0);
		break;
	default:
		return;
	}

	kfifo_free(&lpc_snoop->snoop_fifo[channel]);
}

static int aspeed_lpc_snoop_probe(struct platform_device *pdev)
{
	struct aspeed_lpc_snoop *lpc_snoop;
	struct device *dev;
	u32 port;
	int rc;

	dev = &pdev->dev;

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

	lpc_snoop->regmap = syscon_node_to_regmap(
			pdev->dev.parent->of_node);
	if (IS_ERR(lpc_snoop->regmap)) {
		dev_err(dev, "Couldn't get regmap\n");
		return -ENODEV;
	}

	dev_set_drvdata(&pdev->dev, lpc_snoop);

	rc = of_property_read_u32_index(dev->of_node, "snoop-ports", 0, &port);
	if (rc) {
		dev_err(dev, "no snoop ports configured\n");
		return -ENODEV;
	}

	rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev);
	if (rc)
		return rc;

	rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port);
	if (rc)
		return rc;

	/* Configuration of 2nd snoop channel port is optional */
	if (of_property_read_u32_index(dev->of_node, "snoop-ports",
				       1, &port) == 0) {
		rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port);
		if (rc)
			aspeed_lpc_disable_snoop(lpc_snoop, 0);
	}

	return rc;
}

static int aspeed_lpc_snoop_remove(struct platform_device *pdev)
{
	struct aspeed_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev);

	/* Disable both snoop channels */
	aspeed_lpc_disable_snoop(lpc_snoop, 0);
	aspeed_lpc_disable_snoop(lpc_snoop, 1);

	return 0;
}

static const struct aspeed_lpc_snoop_model_data ast2400_model_data = {
	.has_hicrb_ensnp = 0,
};

static const struct aspeed_lpc_snoop_model_data ast2500_model_data = {
	.has_hicrb_ensnp = 1,
};

static const struct of_device_id aspeed_lpc_snoop_match[] = {
	{ .compatible = "aspeed,ast2400-lpc-snoop",
	  .data = &ast2400_model_data },
	{ .compatible = "aspeed,ast2500-lpc-snoop",
	  .data = &ast2500_model_data },
	{ },
};

static struct platform_driver aspeed_lpc_snoop_driver = {
	.driver = {
		.name		= DEVICE_NAME,
		.of_match_table = aspeed_lpc_snoop_match,
	},
	.probe = aspeed_lpc_snoop_probe,
	.remove = aspeed_lpc_snoop_remove,
};

module_platform_driver(aspeed_lpc_snoop_driver);

MODULE_DEVICE_TABLE(of, aspeed_lpc_snoop_match);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Robert Lippert <rlippert@google.com>");
MODULE_DESCRIPTION("Linux driver to control Aspeed LPC snoop functionality");
