xref: /openbmc/linux/drivers/soc/ti/k3-socinfo.c (revision 907a2b7e2fc746ac3b57b7eb64c220b81d74fc42)
1*907a2b7eSGrygorii Strashko // SPDX-License-Identifier: GPL-2.0
2*907a2b7eSGrygorii Strashko /*
3*907a2b7eSGrygorii Strashko  * TI K3 SoC info driver
4*907a2b7eSGrygorii Strashko  *
5*907a2b7eSGrygorii Strashko  * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
6*907a2b7eSGrygorii Strashko  */
7*907a2b7eSGrygorii Strashko 
8*907a2b7eSGrygorii Strashko #include <linux/mfd/syscon.h>
9*907a2b7eSGrygorii Strashko #include <linux/of.h>
10*907a2b7eSGrygorii Strashko #include <linux/of_address.h>
11*907a2b7eSGrygorii Strashko #include <linux/regmap.h>
12*907a2b7eSGrygorii Strashko #include <linux/platform_device.h>
13*907a2b7eSGrygorii Strashko #include <linux/slab.h>
14*907a2b7eSGrygorii Strashko #include <linux/string.h>
15*907a2b7eSGrygorii Strashko #include <linux/sys_soc.h>
16*907a2b7eSGrygorii Strashko 
17*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_REG		0
18*907a2b7eSGrygorii Strashko /*
19*907a2b7eSGrygorii Strashko  * Bits:
20*907a2b7eSGrygorii Strashko  *  31-28 VARIANT	Device variant
21*907a2b7eSGrygorii Strashko  *  27-12 PARTNO	Part number
22*907a2b7eSGrygorii Strashko  *  11-1  MFG		Indicates TI as manufacturer (0x17)
23*907a2b7eSGrygorii Strashko  *  1			Always 1
24*907a2b7eSGrygorii Strashko  */
25*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT	(28)
26*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_VARIANT_MASK	GENMASK(31, 28)
27*907a2b7eSGrygorii Strashko 
28*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT	(12)
29*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_PARTNO_MASK		GENMASK(27, 12)
30*907a2b7eSGrygorii Strashko 
31*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_MFG_SHIFT		(1)
32*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_MFG_MASK		GENMASK(11, 1)
33*907a2b7eSGrygorii Strashko 
34*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_MFG_TI		0x17
35*907a2b7eSGrygorii Strashko 
36*907a2b7eSGrygorii Strashko static const struct k3_soc_id {
37*907a2b7eSGrygorii Strashko 	unsigned int id;
38*907a2b7eSGrygorii Strashko 	const char *family_name;
39*907a2b7eSGrygorii Strashko } k3_soc_ids[] = {
40*907a2b7eSGrygorii Strashko 	{ 0xBB5A, "AM65X" },
41*907a2b7eSGrygorii Strashko 	{ 0xBB64, "J721E" },
42*907a2b7eSGrygorii Strashko };
43*907a2b7eSGrygorii Strashko 
44*907a2b7eSGrygorii Strashko static int
45*907a2b7eSGrygorii Strashko k3_chipinfo_partno_to_names(unsigned int partno,
46*907a2b7eSGrygorii Strashko 			    struct soc_device_attribute *soc_dev_attr)
47*907a2b7eSGrygorii Strashko {
48*907a2b7eSGrygorii Strashko 	int i;
49*907a2b7eSGrygorii Strashko 
50*907a2b7eSGrygorii Strashko 	for (i = 0; i < ARRAY_SIZE(k3_soc_ids); i++)
51*907a2b7eSGrygorii Strashko 		if (partno == k3_soc_ids[i].id) {
52*907a2b7eSGrygorii Strashko 			soc_dev_attr->family = k3_soc_ids[i].family_name;
53*907a2b7eSGrygorii Strashko 			return 0;
54*907a2b7eSGrygorii Strashko 		}
55*907a2b7eSGrygorii Strashko 
56*907a2b7eSGrygorii Strashko 	return -EINVAL;
57*907a2b7eSGrygorii Strashko }
58*907a2b7eSGrygorii Strashko 
59*907a2b7eSGrygorii Strashko static int k3_chipinfo_probe(struct platform_device *pdev)
60*907a2b7eSGrygorii Strashko {
61*907a2b7eSGrygorii Strashko 	struct device_node *node = pdev->dev.of_node;
62*907a2b7eSGrygorii Strashko 	struct soc_device_attribute *soc_dev_attr;
63*907a2b7eSGrygorii Strashko 	struct device *dev = &pdev->dev;
64*907a2b7eSGrygorii Strashko 	struct soc_device *soc_dev;
65*907a2b7eSGrygorii Strashko 	struct regmap *regmap;
66*907a2b7eSGrygorii Strashko 	u32 partno_id;
67*907a2b7eSGrygorii Strashko 	u32 variant;
68*907a2b7eSGrygorii Strashko 	u32 jtag_id;
69*907a2b7eSGrygorii Strashko 	u32 mfg;
70*907a2b7eSGrygorii Strashko 	int ret;
71*907a2b7eSGrygorii Strashko 
72*907a2b7eSGrygorii Strashko 	regmap = device_node_to_regmap(node);
73*907a2b7eSGrygorii Strashko 	if (IS_ERR(regmap))
74*907a2b7eSGrygorii Strashko 		return PTR_ERR(regmap);
75*907a2b7eSGrygorii Strashko 
76*907a2b7eSGrygorii Strashko 	ret = regmap_read(regmap, CTRLMMR_WKUP_JTAGID_REG, &jtag_id);
77*907a2b7eSGrygorii Strashko 	if (ret < 0)
78*907a2b7eSGrygorii Strashko 		return ret;
79*907a2b7eSGrygorii Strashko 
80*907a2b7eSGrygorii Strashko 	mfg = (jtag_id & CTRLMMR_WKUP_JTAGID_MFG_MASK) >>
81*907a2b7eSGrygorii Strashko 	       CTRLMMR_WKUP_JTAGID_MFG_SHIFT;
82*907a2b7eSGrygorii Strashko 
83*907a2b7eSGrygorii Strashko 	if (mfg != CTRLMMR_WKUP_JTAGID_MFG_TI) {
84*907a2b7eSGrygorii Strashko 		dev_err(dev, "Invalid MFG SoC\n");
85*907a2b7eSGrygorii Strashko 		return -ENODEV;
86*907a2b7eSGrygorii Strashko 	}
87*907a2b7eSGrygorii Strashko 
88*907a2b7eSGrygorii Strashko 	variant = (jtag_id & CTRLMMR_WKUP_JTAGID_VARIANT_MASK) >>
89*907a2b7eSGrygorii Strashko 		  CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT;
90*907a2b7eSGrygorii Strashko 	variant++;
91*907a2b7eSGrygorii Strashko 
92*907a2b7eSGrygorii Strashko 	partno_id = (jtag_id & CTRLMMR_WKUP_JTAGID_PARTNO_MASK) >>
93*907a2b7eSGrygorii Strashko 		 CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT;
94*907a2b7eSGrygorii Strashko 
95*907a2b7eSGrygorii Strashko 	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
96*907a2b7eSGrygorii Strashko 	if (!soc_dev_attr)
97*907a2b7eSGrygorii Strashko 		return -ENOMEM;
98*907a2b7eSGrygorii Strashko 
99*907a2b7eSGrygorii Strashko 	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0", variant);
100*907a2b7eSGrygorii Strashko 	if (!soc_dev_attr->revision) {
101*907a2b7eSGrygorii Strashko 		ret = -ENOMEM;
102*907a2b7eSGrygorii Strashko 		goto err;
103*907a2b7eSGrygorii Strashko 	}
104*907a2b7eSGrygorii Strashko 
105*907a2b7eSGrygorii Strashko 	ret = k3_chipinfo_partno_to_names(partno_id, soc_dev_attr);
106*907a2b7eSGrygorii Strashko 	if (ret) {
107*907a2b7eSGrygorii Strashko 		dev_err(dev, "Unknown SoC JTAGID[0x%08X]\n", jtag_id);
108*907a2b7eSGrygorii Strashko 		ret = -ENODEV;
109*907a2b7eSGrygorii Strashko 		goto err_free_rev;
110*907a2b7eSGrygorii Strashko 	}
111*907a2b7eSGrygorii Strashko 
112*907a2b7eSGrygorii Strashko 	node = of_find_node_by_path("/");
113*907a2b7eSGrygorii Strashko 	of_property_read_string(node, "model", &soc_dev_attr->machine);
114*907a2b7eSGrygorii Strashko 	of_node_put(node);
115*907a2b7eSGrygorii Strashko 
116*907a2b7eSGrygorii Strashko 	soc_dev = soc_device_register(soc_dev_attr);
117*907a2b7eSGrygorii Strashko 	if (IS_ERR(soc_dev)) {
118*907a2b7eSGrygorii Strashko 		ret = PTR_ERR(soc_dev);
119*907a2b7eSGrygorii Strashko 		goto err_free_rev;
120*907a2b7eSGrygorii Strashko 	}
121*907a2b7eSGrygorii Strashko 
122*907a2b7eSGrygorii Strashko 	dev_info(dev, "Family:%s rev:%s JTAGID[0x%08x] Detected\n",
123*907a2b7eSGrygorii Strashko 		 soc_dev_attr->family,
124*907a2b7eSGrygorii Strashko 		 soc_dev_attr->revision, jtag_id);
125*907a2b7eSGrygorii Strashko 
126*907a2b7eSGrygorii Strashko 	return 0;
127*907a2b7eSGrygorii Strashko 
128*907a2b7eSGrygorii Strashko err_free_rev:
129*907a2b7eSGrygorii Strashko 	kfree(soc_dev_attr->revision);
130*907a2b7eSGrygorii Strashko err:
131*907a2b7eSGrygorii Strashko 	kfree(soc_dev_attr);
132*907a2b7eSGrygorii Strashko 	return ret;
133*907a2b7eSGrygorii Strashko }
134*907a2b7eSGrygorii Strashko 
135*907a2b7eSGrygorii Strashko static const struct of_device_id k3_chipinfo_of_match[] = {
136*907a2b7eSGrygorii Strashko 	{ .compatible = "ti,am654-chipid", },
137*907a2b7eSGrygorii Strashko 	{ /* sentinel */ },
138*907a2b7eSGrygorii Strashko };
139*907a2b7eSGrygorii Strashko 
140*907a2b7eSGrygorii Strashko static struct platform_driver k3_chipinfo_driver = {
141*907a2b7eSGrygorii Strashko 	.driver = {
142*907a2b7eSGrygorii Strashko 		.name = "k3-chipinfo",
143*907a2b7eSGrygorii Strashko 		.of_match_table = k3_chipinfo_of_match,
144*907a2b7eSGrygorii Strashko 	},
145*907a2b7eSGrygorii Strashko 	.probe = k3_chipinfo_probe,
146*907a2b7eSGrygorii Strashko };
147*907a2b7eSGrygorii Strashko 
148*907a2b7eSGrygorii Strashko static int __init k3_chipinfo_init(void)
149*907a2b7eSGrygorii Strashko {
150*907a2b7eSGrygorii Strashko 	return platform_driver_register(&k3_chipinfo_driver);
151*907a2b7eSGrygorii Strashko }
152*907a2b7eSGrygorii Strashko subsys_initcall(k3_chipinfo_init);
153