// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2013-2014, 2018 Synopsys, Inc. All rights reserved.
 */

#include <common.h>
#include <malloc.h>
#include <asm/arcregs.h>
#include <asm/cache.h>

DECLARE_GLOBAL_DATA_PTR;

int arch_cpu_init(void)
{
	timer_init();

	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;

	cache_init();

	return 0;
}

int arch_early_init_r(void)
{
	gd->bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
	gd->bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
	return 0;
}

/* This is a dummy function on arc */
int dram_init(void)
{
	return 0;
}

#ifdef CONFIG_DISPLAY_CPUINFO
const char *arc_700_version(int arcver, char *name, int name_len)
{
	const char *arc_ver;

	switch (arcver) {
	case 0x32:
		arc_ver = "v4.4-4.5";
		break;
	case 0x33:
		arc_ver = "v4.6-v4.9";
		break;
	case 0x34:
		arc_ver = "v4.10";
		break;
	case 0x35:
		arc_ver = "v4.11";
		break;
	default:
		arc_ver = "unknown version";
	}

	snprintf(name, name_len, "ARC 700 %s", arc_ver);

	return name;
}

struct em_template_t {
	const bool cache;
	const bool dsp;
	const bool xymem;
	const char name[8];
};

static const struct em_template_t em_versions[] = {
	{false,	false,	false,	"EM4"},
	{true,	false,	false,	"EM6"},
	{false,	true,	false,	"EM5D"},
	{true,	true,	false,	"EM7D"},
	{false,	true,	true,	"EM9D"},
	{true,	true,	true,	"EM11D"},
};

const char *arc_em_version(int arcver, char *name, int name_len)
{
	const char *arc_name = "EM";
	const char *arc_ver;
	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
	bool xymem = ARC_FEATURE_EXISTS(ARC_AUX_XY_BUILD);
	int i;

	for (i = 0; i++ < sizeof(em_versions) / sizeof(struct em_template_t);) {
		if (em_versions[i].cache == cache &&
		    em_versions[i].dsp == dsp &&
		    em_versions[i].xymem == xymem) {
			arc_name = em_versions[i].name;
			break;
		}
	}

	switch (arcver) {
	case 0x41:
		arc_ver = "v1.1a";
		break;
	case 0x42:
		arc_ver = "v3.0";
		break;
	case 0x43:
		arc_ver = "v4.0";
		break;
	case 0x44:
		arc_ver = "v5.0";
		break;
	default:
		arc_ver = "unknown version";
	}

	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);

	return name;
}

struct hs_template_t {
	const bool cache;
	const bool mmu;
	const bool dual_issue;
	const bool dsp;
	const char name[8];
};

static const struct hs_template_t hs_versions[] = {
	{false,	false,	false,	false,	"HS34"},
	{true,	false,	false,	false,	"HS36"},
	{true,	true,	false,	false,	"HS38"},
	{false,	false,	true,	false,	"HS44"},
	{true,	false,	true,	false,	"HS46"},
	{true,	true,	true,	false,	"HS48"},
	{false,	false,	true,	true,	"HS45D"},
	{true,	false,	true,	true,	"HS47D"},
};

const char *arc_hs_version(int arcver, char *name, int name_len)
{
	const char *arc_name = "HS";
	const char *arc_ver;
	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
	bool mmu = !!read_aux_reg(ARC_AUX_MMU_BCR);
	bool dual_issue = arcver == 0x54 ? true : false;
	int i;

	for (i = 0; i++ < sizeof(hs_versions) / sizeof(struct hs_template_t);) {
		if (hs_versions[i].cache == cache &&
		    hs_versions[i].mmu == mmu &&
		    hs_versions[i].dual_issue == dual_issue &&
		    hs_versions[i].dsp == dsp) {
			arc_name = hs_versions[i].name;
			break;
		}
	}

	switch (arcver) {
	case 0x50:
		arc_ver = "v1.0";
		break;
	case 0x51:
		arc_ver = "v2.0";
		break;
	case 0x52:
		arc_ver = "v2.1c";
		break;
	case 0x53:
		arc_ver = "v3.0";
		break;
	case 0x54:
		arc_ver = "v4.0";
		break;
	default:
		arc_ver = "unknown version";
	}

	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);

	return name;
}

const char *decode_identity(void)
{
#define MAX_CPU_NAME_LEN	64

	int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff;
	char *name = malloc(MAX_CPU_NAME_LEN);

	if (arcver >= 0x50)
		return arc_hs_version(arcver, name, MAX_CPU_NAME_LEN);
	else if (arcver >= 0x40)
		return arc_em_version(arcver, name, MAX_CPU_NAME_LEN);
	else if (arcver >= 0x30)
		return arc_700_version(arcver, name, MAX_CPU_NAME_LEN);
	else
		return "Unknown ARC core";
}

const char *decode_subsystem(void)
{
	int subsys_type = read_aux_reg(ARC_AUX_SUBSYS_BUILD) & GENMASK(3, 0);

	switch (subsys_type) {
	case 0: return NULL;
	case 2: return "ARC Sensor & Control IP Subsystem";
	case 3: return "ARC Data Fusion IP Subsystem";
	case 4: return "ARC Secure Subsystem";
	default: return "Unknown subsystem";
	};
}

__weak int print_cpuinfo(void)
{
	const char *subsys_name = decode_subsystem();
	char mhz[8];

	printf("CPU:   %s at %s MHz\n", decode_identity(),
	       strmhz(mhz, gd->cpu_clk));

	if (subsys_name)
		printf("Subsys:%s\n", subsys_name);

	return 0;
}
#endif /* CONFIG_DISPLAY_CPUINFO */
