// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
/*
 * NX Accellerator unit support
 *
 * Copyright 2013-2019 IBM Corp.
 */

#include <skiboot.h>
#include <slw.h>
#include <xscom.h>
#include <io.h>
#include <cpu.h>
#include <nx.h>
#include <chip.h>
#include <xscom-p9-regs.h>
#include <xscom-p10-regs.h>
#include <phys-map.h>
#include <vas.h>
#include <p9_stop_api.H>

static void darn_init(void)
{
	struct dt_node *nx;
	struct proc_chip *chip;
	struct cpu_thread *c;
	uint64_t bar, default_bar;

	if (chip_quirk(QUIRK_NO_RNG))
		return;

	/*
	 * To allow the DARN instruction to function there must be at least
	 * one NX available in the system. Otherwise using DARN will result
	 * in a checkstop. I suppose we could mask the FIR...
	 */
	dt_for_each_compatible(dt_root, nx, "ibm,power9-nx")
		break;
	assert(nx);

	phys_map_get(dt_get_chip_id(nx), NX_RNG, 0, &default_bar, NULL);

	for_each_chip(chip) {
		/* is this NX enabled? */
		xscom_read(chip->id, P9X_NX_MMIO_BAR, &bar);
		if (!(bar & ~P9X_NX_MMIO_BAR_EN))
			bar = default_bar;

		for_each_available_core_in_chip(c, chip->id) {
			uint64_t addr;

			if (proc_gen == proc_gen_p9) {
				addr = XSCOM_ADDR_P9_EX(pir_to_core_id(c->pir),
						P9X_EX_NCU_DARN_BAR);
				xscom_write(chip->id, addr,
				    bar | P9X_EX_NCU_DARN_BAR_EN);
			} else if (proc_gen >= proc_gen_p10) {
				addr = XSCOM_ADDR_P10_NCU(pir_to_core_id(c->pir),
						P10_NCU_DARN_BAR);
				xscom_write(chip->id, addr,
				    bar | P10_NCU_DARN_BAR_EN);
				/*  Init for sibling core also */
				if (c->is_fused_core) {
					addr = XSCOM_ADDR_P10_NCU(pir_to_core_id(c->pir + 1),
								  P10_NCU_DARN_BAR);
					xscom_write(chip->id, addr,
						    bar | P10_NCU_DARN_BAR_EN);
				}
			}
		}
	}
}

void nx_p9_rng_late_init(void)
{
	struct cpu_thread *c;
	uint64_t rc;

	if (proc_gen < proc_gen_p9)
		return;
	if (chip_quirk(QUIRK_NO_RNG))
		return;

	prlog(PR_INFO, "SLW: Configuring self-restore for P9X_EX_NCU_DARN_BAR\n");
	for_each_present_cpu(c) {
		if(cpu_is_thread0(c)) {
			struct proc_chip *chip = get_chip(c->chip_id);
			uint64_t addr, bar;

			phys_map_get(chip->id, NX_RNG, 0, &bar, NULL);
			addr = XSCOM_ADDR_P9_EX(pir_to_core_id(c->pir),
					P9X_EX_NCU_DARN_BAR);
			/* Bail out if wakeup engine has already failed */
			if ( wakeup_engine_state != WAKEUP_ENGINE_PRESENT) {
				prlog(PR_ERR,"DARN BAR p9_stop_api fail detected\n");
				break;
			}
			rc = p9_stop_save_scom((void *)chip->homer_base,
					addr, bar | P9X_EX_NCU_DARN_BAR_EN,
					P9_STOP_SCOM_REPLACE,
					P9_STOP_SECTION_EQ_SCOM);
			if (rc) {
				prlog(PR_ERR,
				"p9_stop_api for DARN_BAR failed rc= %lld",
				rc);
				prlog(PR_ERR, "Disabling deep stop states\n");
				wakeup_engine_state = WAKEUP_ENGINE_FAILED;
				break;
			}
		}
	}
}

static void nx_init_one(struct dt_node *node)
{
	nx_create_rng_node(node);

	if (!vas_nx_enabled())
		return;

	nx_create_crypto_node(node);

	nx_create_compress_node(node);
}

void nx_init(void)
{
	struct dt_node *node;

	dt_for_each_compatible(dt_root, node, "ibm,power-nx") {
		nx_init_one(node);
	}

	dt_for_each_compatible(dt_root, node, "ibm,power9-nx") {
		nx_init_one(node);
	}

	if (proc_gen >= proc_gen_p9)
		darn_init();
}

DEFINE_HWPROBE_DEPS(nx, nx_init, "vas");
