// SPDX-License-Identifier: GPL-2.0
/*
 * TI K3 SoC info driver
 *
 * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
 */

#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/regmap.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/sys_soc.h>

#define CTRLMMR_WKUP_JTAGID_REG		0
/*
 * Bits:
 *  31-28 VARIANT	Device variant
 *  27-12 PARTNO	Part number
 *  11-1  MFG		Indicates TI as manufacturer (0x17)
 *  0			Always 1
 */
#define CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT	(28)
#define CTRLMMR_WKUP_JTAGID_VARIANT_MASK	GENMASK(31, 28)

#define CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT	(12)
#define CTRLMMR_WKUP_JTAGID_PARTNO_MASK		GENMASK(27, 12)

#define CTRLMMR_WKUP_JTAGID_MFG_SHIFT		(1)
#define CTRLMMR_WKUP_JTAGID_MFG_MASK		GENMASK(11, 1)

#define CTRLMMR_WKUP_JTAGID_MFG_TI		0x17

#define JTAG_ID_PARTNO_AM65X		0xBB5A
#define JTAG_ID_PARTNO_J721E		0xBB64
#define JTAG_ID_PARTNO_J7200		0xBB6D
#define JTAG_ID_PARTNO_AM64X		0xBB38
#define JTAG_ID_PARTNO_J721S2		0xBB75
#define JTAG_ID_PARTNO_AM62X		0xBB7E
#define JTAG_ID_PARTNO_J784S4		0xBB80
#define JTAG_ID_PARTNO_AM62AX		0xBB8D
#define JTAG_ID_PARTNO_AM62PX		0xBB9D
#define JTAG_ID_PARTNO_J722S		0xBBA0

static const struct k3_soc_id {
	unsigned int id;
	const char *family_name;
} k3_soc_ids[] = {
	{ JTAG_ID_PARTNO_AM65X, "AM65X" },
	{ JTAG_ID_PARTNO_J721E, "J721E" },
	{ JTAG_ID_PARTNO_J7200, "J7200" },
	{ JTAG_ID_PARTNO_AM64X, "AM64X" },
	{ JTAG_ID_PARTNO_J721S2, "J721S2"},
	{ JTAG_ID_PARTNO_AM62X, "AM62X" },
	{ JTAG_ID_PARTNO_J784S4, "J784S4" },
	{ JTAG_ID_PARTNO_AM62AX, "AM62AX" },
	{ JTAG_ID_PARTNO_AM62PX, "AM62PX" },
	{ JTAG_ID_PARTNO_J722S, "J722S" },
};

static const char * const j721e_rev_string_map[] = {
	"1.0", "1.1", "2.0",
};

static int
k3_chipinfo_partno_to_names(unsigned int partno,
			    struct soc_device_attribute *soc_dev_attr)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(k3_soc_ids); i++)
		if (partno == k3_soc_ids[i].id) {
			soc_dev_attr->family = k3_soc_ids[i].family_name;
			return 0;
		}

	return -ENODEV;
}

static int
k3_chipinfo_variant_to_sr(unsigned int partno, unsigned int variant,
			  struct soc_device_attribute *soc_dev_attr)
{
	switch (partno) {
	case JTAG_ID_PARTNO_J721E:
		if (variant >= ARRAY_SIZE(j721e_rev_string_map))
			goto err_unknown_variant;
		soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%s",
						   j721e_rev_string_map[variant]);
		break;
	default:
		variant++;
		soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0",
						   variant);
	}

	if (!soc_dev_attr->revision)
		return -ENOMEM;

	return 0;

err_unknown_variant:
	return -ENODEV;
}

static int k3_chipinfo_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	struct soc_device_attribute *soc_dev_attr;
	struct device *dev = &pdev->dev;
	struct soc_device *soc_dev;
	struct regmap *regmap;
	u32 partno_id;
	u32 variant;
	u32 jtag_id;
	u32 mfg;
	int ret;

	regmap = device_node_to_regmap(node);
	if (IS_ERR(regmap))
		return PTR_ERR(regmap);

	ret = regmap_read(regmap, CTRLMMR_WKUP_JTAGID_REG, &jtag_id);
	if (ret < 0)
		return ret;

	mfg = (jtag_id & CTRLMMR_WKUP_JTAGID_MFG_MASK) >>
	       CTRLMMR_WKUP_JTAGID_MFG_SHIFT;

	if (mfg != CTRLMMR_WKUP_JTAGID_MFG_TI) {
		dev_err(dev, "Invalid MFG SoC\n");
		return -ENODEV;
	}

	variant = (jtag_id & CTRLMMR_WKUP_JTAGID_VARIANT_MASK) >>
		  CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT;

	partno_id = (jtag_id & CTRLMMR_WKUP_JTAGID_PARTNO_MASK) >>
		 CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT;

	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
	if (!soc_dev_attr)
		return -ENOMEM;

	ret = k3_chipinfo_partno_to_names(partno_id, soc_dev_attr);
	if (ret) {
		dev_err(dev, "Unknown SoC JTAGID[0x%08X]: %d\n", jtag_id, ret);
		goto err;
	}

	ret = k3_chipinfo_variant_to_sr(partno_id, variant, soc_dev_attr);
	if (ret) {
		dev_err(dev, "Unknown SoC SR[0x%08X]: %d\n", jtag_id, ret);
		goto err;
	}

	node = of_find_node_by_path("/");
	of_property_read_string(node, "model", &soc_dev_attr->machine);
	of_node_put(node);

	soc_dev = soc_device_register(soc_dev_attr);
	if (IS_ERR(soc_dev)) {
		ret = PTR_ERR(soc_dev);
		goto err_free_rev;
	}

	dev_info(dev, "Family:%s rev:%s JTAGID[0x%08x] Detected\n",
		 soc_dev_attr->family,
		 soc_dev_attr->revision, jtag_id);

	return 0;

err_free_rev:
	kfree(soc_dev_attr->revision);
err:
	kfree(soc_dev_attr);
	return ret;
}

static const struct of_device_id k3_chipinfo_of_match[] = {
	{ .compatible = "ti,am654-chipid", },
	{ /* sentinel */ },
};

static struct platform_driver k3_chipinfo_driver = {
	.driver = {
		.name = "k3-chipinfo",
		.of_match_table = k3_chipinfo_of_match,
	},
	.probe = k3_chipinfo_probe,
};

static int __init k3_chipinfo_init(void)
{
	return platform_driver_register(&k3_chipinfo_driver);
}
subsys_initcall(k3_chipinfo_init);
