// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2020 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
 */

#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/genalloc.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/remoteproc.h>
#include <linux/reset.h>
#include <linux/sizes.h>

#include "remoteproc_internal.h"

#define AO_REMAP_REG0						0x0
#define AO_REMAP_REG0_REMAP_AHB_SRAM_BITS_17_14_FOR_ARM_CPU	GENMASK(3, 0)

#define AO_REMAP_REG1						0x4
#define AO_REMAP_REG1_MOVE_AHB_SRAM_TO_0X0_INSTEAD_OF_DDR	BIT(4)
#define AO_REMAP_REG1_REMAP_AHB_SRAM_BITS_17_14_FOR_MEDIA_CPU	GENMASK(3, 0)

#define AO_CPU_CNTL						0x0
#define AO_CPU_CNTL_AHB_SRAM_BITS_31_20				GENMASK(28, 16)
#define AO_CPU_CNTL_HALT					BIT(9)
#define AO_CPU_CNTL_UNKNONWN					BIT(8)
#define AO_CPU_CNTL_RUN						BIT(0)

#define AO_CPU_STAT						0x4

#define AO_SECURE_REG0						0x0
#define AO_SECURE_REG0_AHB_SRAM_BITS_19_12			GENMASK(15, 8)

/* Only bits [31:20] and [17:14] are usable, all other bits must be zero */
#define MESON_AO_RPROC_SRAM_USABLE_BITS				0xfff3c000ULL

#define MESON_AO_RPROC_MEMORY_OFFSET				0x10000000

struct meson_mx_ao_arc_rproc_priv {
	void __iomem		*remap_base;
	void __iomem		*cpu_base;
	unsigned long		sram_va;
	phys_addr_t		sram_pa;
	size_t			sram_size;
	struct gen_pool		*sram_pool;
	struct reset_control	*arc_reset;
	struct clk		*arc_pclk;
	struct regmap		*secbus2_regmap;
};

static int meson_mx_ao_arc_rproc_start(struct rproc *rproc)
{
	struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv;
	phys_addr_t translated_sram_addr;
	u32 tmp;
	int ret;

	ret = clk_prepare_enable(priv->arc_pclk);
	if (ret)
		return ret;

	tmp = FIELD_PREP(AO_REMAP_REG0_REMAP_AHB_SRAM_BITS_17_14_FOR_ARM_CPU,
			 priv->sram_pa >> 14);
	writel(tmp, priv->remap_base + AO_REMAP_REG0);

	/*
	 * The SRAM content as seen by the ARC core always starts at 0x0
	 * regardless of the value given here (this was discovered by trial and
	 * error). For SoCs older than Meson6 we probably have to set
	 * AO_REMAP_REG1_MOVE_AHB_SRAM_TO_0X0_INSTEAD_OF_DDR to achieve the
	 * same. (At least) For Meson8 and newer that bit must not be set.
	 */
	writel(0x0, priv->remap_base + AO_REMAP_REG1);

	regmap_update_bits(priv->secbus2_regmap, AO_SECURE_REG0,
			   AO_SECURE_REG0_AHB_SRAM_BITS_19_12,
			   FIELD_PREP(AO_SECURE_REG0_AHB_SRAM_BITS_19_12,
				      priv->sram_pa >> 12));

	ret = reset_control_reset(priv->arc_reset);
	if (ret) {
		clk_disable_unprepare(priv->arc_pclk);
		return ret;
	}

	usleep_range(10, 100);

	/*
	 * Convert from 0xd9000000 to 0xc9000000 as the vendor driver does.
	 * This only seems to be relevant for the AO_CPU_CNTL register. It is
	 * unknown why this is needed.
	 */
	translated_sram_addr = priv->sram_pa - MESON_AO_RPROC_MEMORY_OFFSET;

	tmp = FIELD_PREP(AO_CPU_CNTL_AHB_SRAM_BITS_31_20,
			 translated_sram_addr >> 20);
	tmp |= AO_CPU_CNTL_UNKNONWN | AO_CPU_CNTL_RUN;
	writel(tmp, priv->cpu_base + AO_CPU_CNTL);

	usleep_range(20, 200);

	return 0;
}

static int meson_mx_ao_arc_rproc_stop(struct rproc *rproc)
{
	struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv;

	writel(AO_CPU_CNTL_HALT, priv->cpu_base + AO_CPU_CNTL);

	clk_disable_unprepare(priv->arc_pclk);

	return 0;
}

static void *meson_mx_ao_arc_rproc_da_to_va(struct rproc *rproc, u64 da,
					    size_t len, bool *is_iomem)
{
	struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv;

	/* The memory from the ARC core's perspective always starts at 0x0. */
	if ((da + len) > priv->sram_size)
		return NULL;

	return (void *)priv->sram_va + da;
}

static struct rproc_ops meson_mx_ao_arc_rproc_ops = {
	.start		= meson_mx_ao_arc_rproc_start,
	.stop		= meson_mx_ao_arc_rproc_stop,
	.da_to_va	= meson_mx_ao_arc_rproc_da_to_va,
	.get_boot_addr	= rproc_elf_get_boot_addr,
	.load		= rproc_elf_load_segments,
	.sanity_check	= rproc_elf_sanity_check,
};

static int meson_mx_ao_arc_rproc_probe(struct platform_device *pdev)
{
	struct meson_mx_ao_arc_rproc_priv *priv;
	struct device *dev = &pdev->dev;
	const char *fw_name = NULL;
	struct rproc *rproc;
	int ret;

	device_property_read_string(dev, "firmware-name", &fw_name);

	rproc = devm_rproc_alloc(dev, "meson-mx-ao-arc",
				 &meson_mx_ao_arc_rproc_ops, fw_name,
				 sizeof(*priv));
	if (!rproc)
		return -ENOMEM;

	rproc->has_iommu = false;
	priv = rproc->priv;

	priv->sram_pool = of_gen_pool_get(dev->of_node, "sram", 0);
	if (!priv->sram_pool) {
		dev_err(dev, "Could not get SRAM pool\n");
		return -ENODEV;
	}

	priv->sram_size = gen_pool_avail(priv->sram_pool);

	priv->sram_va = gen_pool_alloc(priv->sram_pool, priv->sram_size);
	if (!priv->sram_va) {
		dev_err(dev, "Could not alloc memory in SRAM pool\n");
		return -ENOMEM;
	}

	priv->sram_pa = gen_pool_virt_to_phys(priv->sram_pool, priv->sram_va);
	if (priv->sram_pa & ~MESON_AO_RPROC_SRAM_USABLE_BITS) {
		dev_err(dev, "SRAM address contains unusable bits\n");
		ret = -EINVAL;
		goto err_free_genpool;
	}

	priv->secbus2_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
							       "amlogic,secbus2");
	if (IS_ERR(priv->secbus2_regmap)) {
		dev_err(dev, "Failed to find SECBUS2 regmap\n");
		ret = PTR_ERR(priv->secbus2_regmap);
		goto err_free_genpool;
	}

	priv->remap_base = devm_platform_ioremap_resource_byname(pdev, "remap");
	if (IS_ERR(priv->remap_base)) {
		ret = PTR_ERR(priv->remap_base);
		goto err_free_genpool;
	}

	priv->cpu_base = devm_platform_ioremap_resource_byname(pdev, "cpu");
	if (IS_ERR(priv->cpu_base)) {
		ret = PTR_ERR(priv->cpu_base);
		goto err_free_genpool;
	}

	priv->arc_reset = devm_reset_control_get_exclusive(dev, NULL);
	if (IS_ERR(priv->arc_reset)) {
		dev_err(dev, "Failed to get ARC reset\n");
		ret = PTR_ERR(priv->arc_reset);
		goto err_free_genpool;
	}

	priv->arc_pclk = devm_clk_get(dev, NULL);
	if (IS_ERR(priv->arc_pclk)) {
		dev_err(dev, "Failed to get the ARC PCLK\n");
		ret = PTR_ERR(priv->arc_pclk);
		goto err_free_genpool;
	}

	platform_set_drvdata(pdev, rproc);

	ret = rproc_add(rproc);
	if (ret)
		goto err_free_genpool;

	return 0;

err_free_genpool:
	gen_pool_free(priv->sram_pool, priv->sram_va, priv->sram_size);
	return ret;
}

static int meson_mx_ao_arc_rproc_remove(struct platform_device *pdev)
{
	struct rproc *rproc = platform_get_drvdata(pdev);
	struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv;

	rproc_del(rproc);
	gen_pool_free(priv->sram_pool, priv->sram_va, priv->sram_size);

	return 0;
}

static const struct of_device_id meson_mx_ao_arc_rproc_match[] = {
	{ .compatible = "amlogic,meson8-ao-arc" },
	{ .compatible = "amlogic,meson8b-ao-arc" },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, meson_mx_ao_arc_rproc_match);

static struct platform_driver meson_mx_ao_arc_rproc_driver = {
	.probe = meson_mx_ao_arc_rproc_probe,
	.remove = meson_mx_ao_arc_rproc_remove,
	.driver = {
		.name = "meson-mx-ao-arc-rproc",
		.of_match_table = meson_mx_ao_arc_rproc_match,
	},
};
module_platform_driver(meson_mx_ao_arc_rproc_driver);

MODULE_DESCRIPTION("Amlogic Meson6/8/8b/8m2 AO ARC remote processor driver");
MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
MODULE_LICENSE("GPL v2");
