// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2019 Julien Masson <jmasson@baylibre.com>
 * (C) Copyright 2019 Neil Armstrong <narmstrong@baylibre.com>
 */

#include <common.h>
#include <init.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <dm.h>
#include <linux/bitfield.h>
#include <regmap.h>
#include <syscon.h>
#include <linux/bitops.h>
#include <linux/err.h>

#define AO_SEC_SD_CFG8		0xe0
#define AO_SEC_SOCINFO_OFFSET	AO_SEC_SD_CFG8

#define SOCINFO_MAJOR	GENMASK(31, 24)
#define SOCINFO_PACK	GENMASK(23, 16)
#define SOCINFO_MINOR	GENMASK(15, 8)
#define SOCINFO_MISC	GENMASK(7, 0)

static const struct meson_gx_soc_id {
	const char *name;
	unsigned int id;
} soc_ids[] = {
	{ "GXBB",   0x1f },
	{ "GXTVBB", 0x20 },
	{ "GXL",    0x21 },
	{ "GXM",    0x22 },
	{ "TXL",    0x23 },
	{ "TXLX",   0x24 },
	{ "AXG",    0x25 },
	{ "GXLX",   0x26 },
	{ "TXHD",   0x27 },
	{ "G12A",   0x28 },
	{ "G12B",   0x29 },
	{ "SM1",    0x2b },
	{ "A1",	    0x2c },
};

static const struct meson_gx_package_id {
	const char *name;
	unsigned int major_id;
	unsigned int pack_id;
	unsigned int pack_mask;
} soc_packages[] = {
	{ "S905",   0x1f, 0,    0x20 }, /* pack_id != 0x20 */
	{ "S905H",  0x1f, 0x3,  0xf },  /* pack_id & 0xf == 0x3 */
	{ "S905M",  0x1f, 0x20, 0xf0 }, /* pack_id == 0x20 */
	{ "S905D",  0x21, 0,    0xf0 },
	{ "S905X",  0x21, 0x80, 0xf0 },
	{ "S905W",  0x21, 0xa0, 0xf0 },
	{ "S905L",  0x21, 0xc0, 0xf0 },
	{ "S905M2", 0x21, 0xe0, 0xf0 },
	{ "S805X",  0x21, 0x30, 0xf0 },
	{ "S805Y",  0x21, 0xb0, 0xf0 },
	{ "S912",   0x22, 0,    0x0 },  /* Only S912 is known for GXM */
	{ "962X",   0x24, 0x10, 0xf0 },
	{ "962E",   0x24, 0x20, 0xf0 },
	{ "A113X",  0x25, 0x37, 0xff },
	{ "A113D",  0x25, 0x22, 0xff },
	{ "S905D2", 0x28, 0x10, 0xf0 },
	{ "S905Y2", 0x28, 0x30, 0xf0 },
	{ "S905X2", 0x28, 0x40, 0xf0 },
	{ "A311D",  0x29, 0x10, 0xf0 },
	{ "S922X",  0x29, 0x40, 0xf0 },
	{ "S905D3", 0x2b, 0x4, 0xf5 },
	{ "S905X3", 0x2b, 0x5, 0xf5 },
	{ "S905X3", 0x2b, 0x10, 0x3f },
	{ "S905D3", 0x2b, 0x30, 0x3f },
	{ "A113L", 0x2c, 0x0, 0xf8 },
};

DECLARE_GLOBAL_DATA_PTR;

static inline unsigned int socinfo_to_major(u32 socinfo)
{
	return FIELD_GET(SOCINFO_MAJOR, socinfo);
}

static inline unsigned int socinfo_to_minor(u32 socinfo)
{
	return FIELD_GET(SOCINFO_MINOR, socinfo);
}

static inline unsigned int socinfo_to_pack(u32 socinfo)
{
	return FIELD_GET(SOCINFO_PACK, socinfo);
}

static inline unsigned int socinfo_to_misc(u32 socinfo)
{
	return FIELD_GET(SOCINFO_MISC, socinfo);
}

static const char *socinfo_to_package_id(u32 socinfo)
{
	unsigned int pack = socinfo_to_pack(socinfo);
	unsigned int major = socinfo_to_major(socinfo);
	int i;

	for (i = 0 ; i < ARRAY_SIZE(soc_packages) ; ++i) {
		if (soc_packages[i].major_id == major &&
		    soc_packages[i].pack_id ==
		    (pack & soc_packages[i].pack_mask))
			return soc_packages[i].name;
	}

	return "Unknown";
}

static const char *socinfo_to_soc_id(u32 socinfo)
{
	unsigned int id = socinfo_to_major(socinfo);
	int i;

	for (i = 0 ; i < ARRAY_SIZE(soc_ids) ; ++i) {
		if (soc_ids[i].id == id)
			return soc_ids[i].name;
	}

	return "Unknown";
}

static void print_board_model(void)
{
	const char *model;
	model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
	printf("Model: %s\n", model ? model : "Unknown");
}

static unsigned int get_socinfo(void)
{
	struct regmap *regmap;
	int nodeoffset, ret;
	ofnode node;
	unsigned int socinfo;

	/* find the offset of compatible node */
	nodeoffset = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
						   "amlogic,meson-gx-ao-secure");
	if (nodeoffset < 0)
		return 0;

	/* check if chip-id is available */
	if (!fdt_getprop(gd->fdt_blob, nodeoffset, "amlogic,has-chip-id", NULL))
		return 0;

	/* get regmap from the syscon node */
	node = offset_to_ofnode(nodeoffset);
	regmap = syscon_node_to_regmap(node);
	if (IS_ERR(regmap)) {
		printf("%s: failed to get regmap\n", __func__);
		return 0;
	}

	/* read soc info */
	ret = regmap_read(regmap, AO_SEC_SOCINFO_OFFSET, &socinfo);
	if (ret && !socinfo) {
		printf("%s: invalid chipid value\n", __func__);
		return 0;
	}

	return socinfo;
}

int show_board_info(void)
{
	unsigned int socinfo;

	/* print board information */
	print_board_model();

	socinfo = get_socinfo();
	if (!socinfo)
		return 0;

	printf("SoC:   Amlogic Meson %s (%s) Revision %x:%x (%x:%x)\n",
	       socinfo_to_soc_id(socinfo),
	       socinfo_to_package_id(socinfo),
	       socinfo_to_major(socinfo),
	       socinfo_to_minor(socinfo),
	       socinfo_to_pack(socinfo),
	       socinfo_to_misc(socinfo));

	return 0;
}

int meson_get_soc_rev(char *buff, size_t buff_len)
{
	unsigned int socinfo;

	socinfo = get_socinfo();
	if (!socinfo)
		return -1;

	/* Write SoC info */
	return snprintf(buff, buff_len, "%x", socinfo_to_minor(socinfo));
}
