/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spmi.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/err.h>
#include <linux/qpnp/qpnp-revid.h>
#include <linux/of.h>

#define REVID_REVISION1	0x0
#define REVID_REVISION2	0x1
#define REVID_REVISION3	0x2
#define REVID_REVISION4	0x3
#define REVID_TYPE	0x4
#define REVID_SUBTYPE	0x5
#define REVID_STATUS1	0x8
#define REVID_SPARE_0	0x60
#define REVID_TP_REV	0xf1
#define REVID_FAB_ID	0xf2

#define QPNP_REVID_DEV_NAME "qcom,qpnp-revid"

static const char *const pmic_names[] = {
	[0] =	"Unknown PMIC",
	[PM8941_SUBTYPE] = "PM8941",
	[PM8841_SUBTYPE] = "PM8841",
	[PM8019_SUBTYPE] = "PM8019",
	[PM8226_SUBTYPE] = "PM8226",
	[PM8110_SUBTYPE] = "PM8110",
	[PMA8084_SUBTYPE] = "PMA8084",
	[PMI8962_SUBTYPE] = "PMI8962",
	[PMD9635_SUBTYPE] = "PMD9635",
	[PM8994_SUBTYPE] = "PM8994",
	[PMI8994_SUBTYPE] = "PMI8994",
	[PM8916_SUBTYPE] = "PM8916",
	[PM8004_SUBTYPE] = "PM8004",
	[PM8909_SUBTYPE] = "PM8909",
	[PM2433_SUBTYPE] = "PM2433",
	[PMD9655_SUBTYPE] = "PMD9655",
	[PM8950_SUBTYPE] = "PM8950",
	[PMI8950_SUBTYPE] = "PMI8950",
	[PMK8001_SUBTYPE] = "PMK8001",
	[PMI8996_SUBTYPE] = "PMI8996",
	[PM8998_SUBTYPE] = "PM8998",
	[PMI8998_SUBTYPE] = "PMI8998",
	[PM8005_SUBTYPE] = "PM8005",
	[PM8937_SUBTYPE] = "PM8937",
	[PM660L_SUBTYPE] = "PM660L",
	[PM660_SUBTYPE] = "PM660",
	[PMI632_SUBTYPE] = "PMI632",
	[PMI8937_SUBTYPE] = "PMI8937",
	[PM855_SUBTYPE] = "PM855",
	[PM855B_SUBTYPE] = "PM855B",
	[PM855L_SUBTYPE] = "PM855L",
};

struct revid_chip {
	struct list_head	link;
	struct device_node	*dev_node;
	struct pmic_revid_data	data;
};

static LIST_HEAD(revid_chips);
static DEFINE_MUTEX(revid_chips_lock);

static const struct of_device_id qpnp_revid_match_table[] = {
	{ .compatible = QPNP_REVID_DEV_NAME },
	{}
};

static u8 qpnp_read_byte(struct regmap *regmap, u16 addr)
{
	int rc;
	int val;

	rc = regmap_read(regmap, addr, &val);
	if (rc) {
		pr_err("read failed rc=%d\n", rc);
		return 0;
	}
	return (u8)val;
}

/**
 * get_revid_data - Return the revision information of PMIC
 * @dev_node: Pointer to the revid peripheral of the PMIC for which
 *		revision information is seeked
 *
 * CONTEXT: Should be called in non atomic context
 *
 * RETURNS: pointer to struct pmic_revid_data filled with the information
 *		about the PMIC revision
 */
struct pmic_revid_data *get_revid_data(struct device_node *dev_node)
{
	struct revid_chip *revid_chip;

	if (!dev_node)
		return ERR_PTR(-EINVAL);

	mutex_lock(&revid_chips_lock);
	list_for_each_entry(revid_chip, &revid_chips, link) {
		if (dev_node == revid_chip->dev_node) {
			mutex_unlock(&revid_chips_lock);
			return &revid_chip->data;
		}
	}
	mutex_unlock(&revid_chips_lock);
	return ERR_PTR(-EINVAL);
}
EXPORT_SYMBOL(get_revid_data);

#define PM8941_PERIPHERAL_SUBTYPE	0x01
#define PM8226_PERIPHERAL_SUBTYPE	0x04
#define PMD9655_PERIPHERAL_SUBTYPE	0x0F
#define PMI8950_PERIPHERAL_SUBTYPE	0x11
#define PMI8937_PERIPHERAL_SUBTYPE	0x37
static size_t build_pmic_string(char *buf, size_t n, int sid,
		u8 subtype, u8 rev1, u8 rev2, u8 rev3, u8 rev4)
{
	size_t pos = 0;
	/*
	 * In early versions of PM8941 and PM8226, the major revision number
	 * started incrementing from 0 (eg 0 = v1.0, 1 = v2.0).
	 * Increment the major revision number here if the chip is an early
	 * version of PM8941 or PM8226.
	 */
	if (((int)subtype == PM8941_PERIPHERAL_SUBTYPE
			|| (int)subtype == PM8226_PERIPHERAL_SUBTYPE)
			&& rev4 < 0x02)
		rev4++;

	pos += snprintf(buf + pos, n - pos, "PMIC@SID%d", sid);
	if (subtype >= ARRAY_SIZE(pmic_names) || subtype == 0)
		pos += snprintf(buf + pos, n - pos, ": %s (subtype: 0x%02X)",
				pmic_names[0], subtype);
	else
		pos += snprintf(buf + pos, n - pos, ": %s",
				pmic_names[subtype]);
	pos += snprintf(buf + pos, n - pos, " v%d.%d", rev4, rev3);
	if (rev2 || rev1)
		pos += snprintf(buf + pos, n - pos, ".%d", rev2);
	if (rev1)
		pos += snprintf(buf + pos, n - pos, ".%d", rev1);
	return pos;
}

#define PMIC_PERIPHERAL_TYPE		0x51
#define PMIC_STRING_MAXLENGTH		80
static int qpnp_revid_probe(struct platform_device *pdev)
{
	u8 rev1, rev2, rev3, rev4, pmic_type, pmic_subtype, pmic_status;
	u8 option1, option2, option3, option4, spare0;
	unsigned int base;
	int rc, fab_id, tp_rev;
	char pmic_string[PMIC_STRING_MAXLENGTH] = {'\0'};
	struct revid_chip *revid_chip;
	struct regmap *regmap;

	regmap = dev_get_regmap(pdev->dev.parent, NULL);
	if (!regmap) {
		dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
		return -EINVAL;
	}

	rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
	if (rc < 0) {
		dev_err(&pdev->dev,
			"Couldn't find reg in node = %s rc = %d\n",
			pdev->dev.of_node->full_name, rc);
		return rc;
	}
	pmic_type = qpnp_read_byte(regmap, base + REVID_TYPE);
	if (pmic_type != PMIC_PERIPHERAL_TYPE) {
		pr_err("Invalid REVID peripheral type: %02X\n", pmic_type);
		return -EINVAL;
	}

	rev1 = qpnp_read_byte(regmap, base + REVID_REVISION1);
	rev2 = qpnp_read_byte(regmap, base + REVID_REVISION2);
	rev3 = qpnp_read_byte(regmap, base + REVID_REVISION3);
	rev4 = qpnp_read_byte(regmap, base + REVID_REVISION4);

	pmic_subtype = qpnp_read_byte(regmap, base + REVID_SUBTYPE);
	if (pmic_subtype != PMD9655_PERIPHERAL_SUBTYPE)
		pmic_status = qpnp_read_byte(regmap, base + REVID_STATUS1);
	else
		pmic_status = 0;

	/* special case for PMI8937 */
	if (pmic_subtype == PMI8950_PERIPHERAL_SUBTYPE) {
		/* read spare register */
		spare0 = qpnp_read_byte(regmap, base + REVID_SPARE_0);
		if (spare0)
			pmic_subtype = PMI8937_PERIPHERAL_SUBTYPE;
	}

	if (of_property_read_bool(pdev->dev.of_node, "qcom,fab-id-valid"))
		fab_id = qpnp_read_byte(regmap, base + REVID_FAB_ID);
	else
		fab_id = -EINVAL;

	if (of_property_read_bool(pdev->dev.of_node, "qcom,tp-rev-valid"))
		tp_rev = qpnp_read_byte(regmap, base + REVID_TP_REV);
	else
		tp_rev = -EINVAL;

	revid_chip = devm_kzalloc(&pdev->dev, sizeof(struct revid_chip),
						GFP_KERNEL);
	if (!revid_chip)
		return -ENOMEM;

	revid_chip->dev_node = pdev->dev.of_node;
	revid_chip->data.rev1 = rev1;
	revid_chip->data.rev2 = rev2;
	revid_chip->data.rev3 = rev3;
	revid_chip->data.rev4 = rev4;
	revid_chip->data.pmic_subtype = pmic_subtype;
	revid_chip->data.pmic_type = pmic_type;
	revid_chip->data.fab_id = fab_id;
	revid_chip->data.tp_rev = tp_rev;

	if (pmic_subtype < ARRAY_SIZE(pmic_names))
		revid_chip->data.pmic_name = pmic_names[pmic_subtype];
	else
		revid_chip->data.pmic_name = pmic_names[0];

	mutex_lock(&revid_chips_lock);
	list_add(&revid_chip->link, &revid_chips);
	mutex_unlock(&revid_chips_lock);

	option1 = pmic_status & 0x3;
	option2 = (pmic_status >> 2) & 0x3;
	option3 = (pmic_status >> 4) & 0x3;
	option4 = (pmic_status >> 6) & 0x3;

	build_pmic_string(pmic_string, PMIC_STRING_MAXLENGTH,
			  to_spmi_device(pdev->dev.parent)->usid,
			pmic_subtype, rev1, rev2, rev3, rev4);
	pr_info("%s options: %d, %d, %d, %d\n",
			pmic_string, option1, option2, option3, option4);
	return 0;
}

static struct platform_driver qpnp_revid_driver = {
	.probe	= qpnp_revid_probe,
	.driver	= {
		.name		= QPNP_REVID_DEV_NAME,
		.owner		= THIS_MODULE,
		.of_match_table	= qpnp_revid_match_table,
	},
};

static int __init qpnp_revid_init(void)
{
	return platform_driver_register(&qpnp_revid_driver);
}

static void __exit qpnp_revid_exit(void)
{
	return platform_driver_unregister(&qpnp_revid_driver);
}

subsys_initcall(qpnp_revid_init);
module_exit(qpnp_revid_exit);

MODULE_DESCRIPTION("QPNP REVID DRIVER");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" QPNP_REVID_DEV_NAME);
