// SPDX-License-Identifier: GPL-2.0
/*
 * R-Car Generation 2 Power management support
 *
 * Copyright (C) 2013 - 2015  Renesas Electronics Corporation
 * Copyright (C) 2011  Renesas Solutions Corp.
 * Copyright (C) 2011  Magnus Damm
 */

#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/smp.h>
#include <asm/io.h>
#include <asm/cputype.h>
#include "common.h"
#include "rcar-gen2.h"

/* RST */
#define RST		0xe6160000

#define CA15BAR		0x0020		/* CA15 Boot Address Register */
#define CA7BAR		0x0030		/* CA7 Boot Address Register */
#define CA15RESCNT	0x0040		/* CA15 Reset Control Register */
#define CA7RESCNT	0x0044		/* CA7 Reset Control Register */

/* SYS Boot Address Register */
#define SBAR_BAREN	BIT(4)		/* SBAR is valid */

/* Reset Control Registers */
#define CA15RESCNT_CODE	0xa5a50000
#define CA15RESCNT_CPUS	0xf		/* CPU0-3 */
#define CA7RESCNT_CODE	0x5a5a0000
#define CA7RESCNT_CPUS	0xf		/* CPU0-3 */

/* On-chip RAM */
#define ICRAM1		0xe63c0000	/* Inter Connect RAM1 (4 KiB) */

static inline u32 phys_to_sbar(phys_addr_t addr)
{
	return (addr >> 8) & 0xfffffc00;
}

void __init rcar_gen2_pm_init(void)
{
	void __iomem *p;
	u32 bar;
	struct device_node *np;
	bool has_a7 = false;
	bool has_a15 = false;
	struct resource res;
	int error;

	if (!request_mem_region(0, SZ_256K, "Boot Area")) {
		pr_err("Failed to request boot area\n");
		return;
	}

	for_each_of_cpu_node(np) {
		if (of_device_is_compatible(np, "arm,cortex-a15"))
			has_a15 = true;
		else if (of_device_is_compatible(np, "arm,cortex-a7"))
			has_a7 = true;
	}

	np = of_find_compatible_node(NULL, NULL, "renesas,smp-sram");
	if (!np) {
		/* No smp-sram in DT, fall back to hardcoded address */
		res = (struct resource)DEFINE_RES_MEM(ICRAM1,
						      shmobile_boot_size);
		goto map;
	}

	error = of_address_to_resource(np, 0, &res);
	of_node_put(np);
	if (error) {
		pr_err("Failed to get smp-sram address: %d\n", error);
		return;
	}

map:
	/* RAM for jump stub, because BAR requires 256KB aligned address */
	if (res.start & (256 * 1024 - 1) ||
	    resource_size(&res) < shmobile_boot_size) {
		pr_err("Invalid smp-sram region\n");
		return;
	}

	p = ioremap(res.start, resource_size(&res));
	if (!p)
		return;
	/*
	 * install the reset vector, use the largest version if we have enough
	 * memory available
	 */
	if (resource_size(&res) >= shmobile_boot_size_gen2) {
		shmobile_boot_cpu_gen2 = read_cpuid_mpidr();
		memcpy_toio(p, shmobile_boot_vector_gen2,
			    shmobile_boot_size_gen2);
	} else {
		memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
	}
	iounmap(p);

	/* setup reset vectors */
	p = ioremap(RST, 0x63);
	bar = phys_to_sbar(res.start);
	if (has_a15) {
		writel_relaxed(bar, p + CA15BAR);
		writel_relaxed(bar | SBAR_BAREN, p + CA15BAR);

		/* de-assert reset for CA15 CPUs */
		writel_relaxed((readl_relaxed(p + CA15RESCNT) &
				~CA15RESCNT_CPUS) | CA15RESCNT_CODE,
			       p + CA15RESCNT);
	}
	if (has_a7) {
		writel_relaxed(bar, p + CA7BAR);
		writel_relaxed(bar | SBAR_BAREN, p + CA7BAR);

		/* de-assert reset for CA7 CPUs */
		writel_relaxed((readl_relaxed(p + CA7RESCNT) &
				~CA7RESCNT_CPUS) | CA7RESCNT_CODE,
			       p + CA7RESCNT);
	}
	iounmap(p);

	shmobile_smp_apmu_suspend_init();
}
