// SPDX-License-Identifier: GPL-2.0

#include <linux/smp.h>
#include <linux/types.h>
#include <asm/cpu.h>
#include <asm/cpu-info.h>
#include <asm/elf.h>

#include <loongson_regs.h>
#include <cpucfg-emul.h>

static bool is_loongson(struct cpuinfo_mips *c)
{
	switch (c->processor_id & PRID_COMP_MASK) {
	case PRID_COMP_LEGACY:
		return ((c->processor_id & PRID_IMP_MASK) ==
			PRID_IMP_LOONGSON_64C);

	case PRID_COMP_LOONGSON:
		return true;

	default:
		return false;
	}
}

static u32 get_loongson_fprev(struct cpuinfo_mips *c)
{
	return c->fpu_id & LOONGSON_FPREV_MASK;
}

static bool cpu_has_uca(void)
{
	u32 diag = read_c0_diag();
	u32 new_diag;

	if (diag & LOONGSON_DIAG_UCAC)
		/* UCA is already enabled. */
		return true;

	/* See if UCAC bit can be flipped on. This should be safe. */
	new_diag = diag | LOONGSON_DIAG_UCAC;
	write_c0_diag(new_diag);
	new_diag = read_c0_diag();
	write_c0_diag(diag);

	return (new_diag & LOONGSON_DIAG_UCAC) != 0;
}

static void probe_uca(struct cpuinfo_mips *c)
{
	if (cpu_has_uca())
		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LSUCA;
}

static void decode_loongson_config6(struct cpuinfo_mips *c)
{
	u32 config6 = read_c0_config6();

	if (config6 & LOONGSON_CONF6_SFBEN)
		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SFBP;
	if (config6 & LOONGSON_CONF6_LLEXC)
		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LLEXC;
	if (config6 & LOONGSON_CONF6_SCRAND)
		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SCRAND;
}

static void patch_cpucfg_sel1(struct cpuinfo_mips *c)
{
	u64 ases = c->ases;
	u64 options = c->options;
	u32 data = c->loongson3_cpucfg_data[0];

	if (options & MIPS_CPU_FPU) {
		data |= LOONGSON_CFG1_FP;
		data |= get_loongson_fprev(c) << LOONGSON_CFG1_FPREV_OFFSET;
	}
	if (ases & MIPS_ASE_LOONGSON_MMI)
		data |= LOONGSON_CFG1_MMI;
	if (ases & MIPS_ASE_MSA)
		data |= LOONGSON_CFG1_MSA1;

	c->loongson3_cpucfg_data[0] = data;
}

static void patch_cpucfg_sel2(struct cpuinfo_mips *c)
{
	u64 ases = c->ases;
	u64 options = c->options;
	u32 data = c->loongson3_cpucfg_data[1];

	if (ases & MIPS_ASE_LOONGSON_EXT)
		data |= LOONGSON_CFG2_LEXT1;
	if (ases & MIPS_ASE_LOONGSON_EXT2)
		data |= LOONGSON_CFG2_LEXT2;
	if (options & MIPS_CPU_LDPTE)
		data |= LOONGSON_CFG2_LSPW;

	if (ases & MIPS_ASE_VZ)
		data |= LOONGSON_CFG2_LVZP;
	else
		data &= ~LOONGSON_CFG2_LVZREV;

	c->loongson3_cpucfg_data[1] = data;
}

static void patch_cpucfg_sel3(struct cpuinfo_mips *c)
{
	u64 ases = c->ases;
	u32 data = c->loongson3_cpucfg_data[2];

	if (ases & MIPS_ASE_LOONGSON_CAM) {
		data |= LOONGSON_CFG3_LCAMP;
	} else {
		data &= ~LOONGSON_CFG3_LCAMREV;
		data &= ~LOONGSON_CFG3_LCAMNUM;
		data &= ~LOONGSON_CFG3_LCAMKW;
		data &= ~LOONGSON_CFG3_LCAMVW;
	}

	c->loongson3_cpucfg_data[2] = data;
}

void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
{
	/* Only engage the logic on Loongson processors. */
	if (!is_loongson(c))
		return;

	/* CPUs with CPUCFG support don't need to synthesize anything. */
	if (cpu_has_cfg())
		goto have_cpucfg_now;

	c->loongson3_cpucfg_data[0] = 0;
	c->loongson3_cpucfg_data[1] = 0;
	c->loongson3_cpucfg_data[2] = 0;

	/* Add CPUCFG features non-discoverable otherwise. */
	switch (c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) {
	case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_0:
	case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_1:
	case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_2:
	case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_3:
		decode_loongson_config6(c);
		probe_uca(c);

		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
			LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LLSYNC |
			LOONGSON_CFG1_TGTSYNC);
		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
			LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LPMP |
			LOONGSON_CFG2_LPM_REV2);
		c->loongson3_cpucfg_data[2] = 0;
		break;

	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R1:
		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
			LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
			LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
			LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
		c->loongson3_cpucfg_data[2] |= (
			LOONGSON_CFG3_LCAM_REV1 |
			LOONGSON_CFG3_LCAMNUM_REV1 |
			LOONGSON_CFG3_LCAMKW_REV1 |
			LOONGSON_CFG3_LCAMVW_REV1);
		break;

	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3B_R1:
	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3B_R2:
		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
			LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
			LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
			LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
		c->loongson3_cpucfg_data[2] |= (
			LOONGSON_CFG3_LCAM_REV1 |
			LOONGSON_CFG3_LCAMNUM_REV1 |
			LOONGSON_CFG3_LCAMKW_REV1 |
			LOONGSON_CFG3_LCAMVW_REV1);
		break;

	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0:
	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_1:
	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R3_0:
	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R3_1:
		decode_loongson_config6(c);
		probe_uca(c);

		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_CNT64 |
			LOONGSON_CFG1_LSLDR0 | LOONGSON_CFG1_LSPREF |
			LOONGSON_CFG1_LSPREFX | LOONGSON_CFG1_LSSYNCI |
			LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
			LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LBTMMU |
			LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1 |
			LOONGSON_CFG2_LVZ_REV1);
		c->loongson3_cpucfg_data[2] |= (LOONGSON_CFG3_LCAM_REV1 |
			LOONGSON_CFG3_LCAMNUM_REV1 |
			LOONGSON_CFG3_LCAMKW_REV1 |
			LOONGSON_CFG3_LCAMVW_REV1);
		break;

	default:
		/* It is possible that some future Loongson cores still do
		 * not have CPUCFG, so do not emulate anything for these
		 * cores.
		 */
		return;
	}

	/* This feature is set by firmware, but all known Loongson-64 systems
	 * are configured this way.
	 */
	c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;

	/* Patch in dynamically probed bits. */
	patch_cpucfg_sel1(c);
	patch_cpucfg_sel2(c);
	patch_cpucfg_sel3(c);

have_cpucfg_now:
	/* We have usable CPUCFG now, emulated or not.
	 * Announce CPUCFG availability to userspace via hwcap.
	 */
	elf_hwcap |= HWCAP_LOONGSON_CPUCFG;
}
