/*
 * SPDX-FileCopyrightText: Copyright 2021, 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 * SPDX-License-Identifier: GPL-2.0-only
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 */

#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>

#define JUNO_FPGA_RESET_DRIVER_VERSION "0.1.0"

struct juno_fpga_reset {
	struct reset_controller_dev rst;
	struct device               *dev;
	void __iomem                *base;
};

/* Supported controller IDs */
#define JUNO_FPGA_RESET_MIN_SUPPORTED_ID 0x2010f
#define JUNO_FPGA_RESET_MAX_SUPPORTED_ID 0x20113

#define JUNO_FPGA_RESET_ID(base)          (base)
#define JUNO_FPGA_RESET_SOFT_RESET(base) ((base) + 0x140)
#define JUNO_FPGA_RESET_CPU_WAIT(base)   ((base) + 0x144)

#define JUNO_FPGA_RESET_SET_RESET       (0x1)
#define JUNO_FPGA_RESET_UNSET_RESET     (0x0)
#define JUNO_FPGA_RESET_SET_CPUWAIT     (0x1)
#define JUNO_FPGA_RESET_UNSET_CPUWAIT   (0x0)

static void __iomem *verify_and_remap(struct device *dev,
				      struct resource *res)
{
	void __iomem *base = devm_ioremap_resource(dev, res);
	u32 id;

	if (IS_ERR(base))
		return base;

	id = readl(JUNO_FPGA_RESET_ID(base));

	if (id < JUNO_FPGA_RESET_MIN_SUPPORTED_ID ||
	    id > JUNO_FPGA_RESET_MAX_SUPPORTED_ID) {
		dev_err(dev, "Unknown controller ID: %u", id);

		return IOMEM_ERR_PTR(-EINVAL);
	}

	return base;
}

int juno_fpga_reset_assert(struct reset_controller_dev *rcdev,
			   unsigned long id)
{
	struct juno_fpga_reset *reset = container_of(rcdev,
						     struct juno_fpga_reset,
						     rst);

	/* pull reset */
	dev_dbg(reset->dev, "Asserting reset");

	/* set wait and reset */
	writel(JUNO_FPGA_RESET_SET_RESET,
	       JUNO_FPGA_RESET_SOFT_RESET(reset->base));
	writel(JUNO_FPGA_RESET_SET_CPUWAIT,
	       JUNO_FPGA_RESET_CPU_WAIT(reset->base));

	writel(JUNO_FPGA_RESET_UNSET_RESET,
	       JUNO_FPGA_RESET_SOFT_RESET(reset->base));

	return 0;
}

int juno_fpga_reset_deassert(struct reset_controller_dev *rcdev,
			     unsigned long id)
{
	struct juno_fpga_reset *reset = container_of(rcdev,
						     struct juno_fpga_reset,
						     rst);

	/* release wait */
	dev_dbg(reset->dev, "Deasserting reset");

	writel(JUNO_FPGA_RESET_UNSET_CPUWAIT,
	       JUNO_FPGA_RESET_CPU_WAIT(reset->base));

	return 0;
}

static struct reset_control_ops juno_fpga_reset_ops = {
	.assert   = juno_fpga_reset_assert,
	.deassert = juno_fpga_reset_deassert,
};

static const struct of_device_id juno_fpga_reset_match[] = {
	{ .compatible = "arm,mali_fpga_sysctl", .data = 0 },
	{ /* sentinel */ },
};

static int juno_fpga_reset_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct juno_fpga_reset *reset;
	struct resource *res;

	reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
	if (!reset)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	reset->base = verify_and_remap(dev, res);
	reset->dev = dev;

	if (IS_ERR(reset->base)) {
		dev_err(dev, "Failed to verify and remap base address (%ld)",
			PTR_ERR(reset->base));

		return PTR_ERR(reset->base);
	}

	platform_set_drvdata(pdev, reset);

	reset->rst.owner = THIS_MODULE;
	reset->rst.nr_resets = 1;
	reset->rst.ops = &juno_fpga_reset_ops;
	reset->rst.of_node = pdev->dev.of_node;

	dev_info(dev, "registering to reset controller core");

	return devm_reset_controller_register(dev, &reset->rst);
}

static int juno_fpga_reset_remove(struct platform_device *pdev)
{
	return 0;
}

static struct platform_driver juno_fpga_reset_driver = {
	.probe                  = juno_fpga_reset_probe,
	.remove                 = juno_fpga_reset_remove,
	.driver                 = {
		.name           = "juno-fpga-reset",
		.of_match_table = of_match_ptr(juno_fpga_reset_match),
	},
};

module_platform_driver(juno_fpga_reset_driver);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Arm Ltd");
MODULE_DESCRIPTION("Arm Juno FPGA Reset Driver");
MODULE_VERSION(JUNO_FPGA_RESET_DRIVER_VERSION);
