xref: /linux/drivers/soc/vt8500/wmt-socinfo.c (revision 297d9111e9fcf47dd1dcc6f79bba915f35378d01)
1*96f94587SAlexey Charkov // SPDX-License-Identifier: GPL-2.0-or-later
2*96f94587SAlexey Charkov /*
3*96f94587SAlexey Charkov  * Copyright 2025 Alexey Charkov <alchark@gmail.com>
4*96f94587SAlexey Charkov  * Based on aspeed-socinfo.c
5*96f94587SAlexey Charkov  */
6*96f94587SAlexey Charkov 
7*96f94587SAlexey Charkov #include <linux/dev_printk.h>
8*96f94587SAlexey Charkov #include <linux/device.h>
9*96f94587SAlexey Charkov #include <linux/io.h>
10*96f94587SAlexey Charkov #include <linux/of.h>
11*96f94587SAlexey Charkov #include <linux/platform_device.h>
12*96f94587SAlexey Charkov #include <linux/sys_soc.h>
13*96f94587SAlexey Charkov 
14*96f94587SAlexey Charkov static const struct {
15*96f94587SAlexey Charkov 	const char *name;
16*96f94587SAlexey Charkov 	const u32 id;
17*96f94587SAlexey Charkov } chip_id_table[] = {
18*96f94587SAlexey Charkov 	/* VIA */
19*96f94587SAlexey Charkov 	{ "VT8420", 0x3300 },
20*96f94587SAlexey Charkov 	{ "VT8430", 0x3357 },
21*96f94587SAlexey Charkov 	{ "VT8500", 0x3400 },
22*96f94587SAlexey Charkov 
23*96f94587SAlexey Charkov 	/* WonderMedia */
24*96f94587SAlexey Charkov 	{ "WM8425", 0x3429 },
25*96f94587SAlexey Charkov 	{ "WM8435", 0x3437 },
26*96f94587SAlexey Charkov 	{ "WM8440", 0x3451 },
27*96f94587SAlexey Charkov 	{ "WM8505", 0x3426 },
28*96f94587SAlexey Charkov 	{ "WM8650", 0x3465 },
29*96f94587SAlexey Charkov 	{ "WM8750", 0x3445 },
30*96f94587SAlexey Charkov 	{ "WM8850", 0x3481 },
31*96f94587SAlexey Charkov 	{ "WM8880", 0x3498 },
32*96f94587SAlexey Charkov };
33*96f94587SAlexey Charkov 
sccid_to_name(u32 sccid)34*96f94587SAlexey Charkov static const char *sccid_to_name(u32 sccid)
35*96f94587SAlexey Charkov {
36*96f94587SAlexey Charkov 	u32 id = sccid >> 16;
37*96f94587SAlexey Charkov 	unsigned int i;
38*96f94587SAlexey Charkov 
39*96f94587SAlexey Charkov 	for (i = 0 ; i < ARRAY_SIZE(chip_id_table) ; ++i) {
40*96f94587SAlexey Charkov 		if (chip_id_table[i].id == id)
41*96f94587SAlexey Charkov 			return chip_id_table[i].name;
42*96f94587SAlexey Charkov 	}
43*96f94587SAlexey Charkov 
44*96f94587SAlexey Charkov 	return "Unknown";
45*96f94587SAlexey Charkov }
46*96f94587SAlexey Charkov 
wmt_socinfo_probe(struct platform_device * pdev)47*96f94587SAlexey Charkov static int wmt_socinfo_probe(struct platform_device *pdev)
48*96f94587SAlexey Charkov {
49*96f94587SAlexey Charkov 	struct device_node *np = pdev->dev.of_node;
50*96f94587SAlexey Charkov 	struct soc_device_attribute *attrs;
51*96f94587SAlexey Charkov 	struct soc_device *soc_dev;
52*96f94587SAlexey Charkov 	char letter, digit;
53*96f94587SAlexey Charkov 	void __iomem *reg;
54*96f94587SAlexey Charkov 	u32 sccid;
55*96f94587SAlexey Charkov 
56*96f94587SAlexey Charkov 	reg = devm_of_iomap(&pdev->dev, np, 0, NULL);
57*96f94587SAlexey Charkov 	if (IS_ERR(reg))
58*96f94587SAlexey Charkov 		return PTR_ERR(reg);
59*96f94587SAlexey Charkov 
60*96f94587SAlexey Charkov 	sccid = readl(reg);
61*96f94587SAlexey Charkov 
62*96f94587SAlexey Charkov 	attrs = devm_kzalloc(&pdev->dev, sizeof(*attrs), GFP_KERNEL);
63*96f94587SAlexey Charkov 	if (!attrs)
64*96f94587SAlexey Charkov 		return -ENOMEM;
65*96f94587SAlexey Charkov 
66*96f94587SAlexey Charkov 	/*
67*96f94587SAlexey Charkov 	 * Machine: VIA APC Rock
68*96f94587SAlexey Charkov 	 * Family: WM8850
69*96f94587SAlexey Charkov 	 * Revision: A2
70*96f94587SAlexey Charkov 	 * SoC ID: raw silicon revision id (34810103 in hexadecimal)
71*96f94587SAlexey Charkov 	 */
72*96f94587SAlexey Charkov 
73*96f94587SAlexey Charkov 	attrs->family = sccid_to_name(sccid);
74*96f94587SAlexey Charkov 
75*96f94587SAlexey Charkov 	letter = (sccid >> 8) & 0xf;
76*96f94587SAlexey Charkov 	letter = (letter - 1) + 'A';
77*96f94587SAlexey Charkov 	digit = sccid & 0xff;
78*96f94587SAlexey Charkov 	digit = (digit - 1) + '0';
79*96f94587SAlexey Charkov 	attrs->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL,
80*96f94587SAlexey Charkov 					 "%c%c", letter, digit);
81*96f94587SAlexey Charkov 
82*96f94587SAlexey Charkov 	attrs->soc_id = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%08x", sccid);
83*96f94587SAlexey Charkov 
84*96f94587SAlexey Charkov 	if (!attrs->revision || !attrs->soc_id)
85*96f94587SAlexey Charkov 		return -ENOMEM;
86*96f94587SAlexey Charkov 
87*96f94587SAlexey Charkov 	soc_dev = soc_device_register(attrs);
88*96f94587SAlexey Charkov 	if (IS_ERR(soc_dev))
89*96f94587SAlexey Charkov 		return PTR_ERR(soc_dev);
90*96f94587SAlexey Charkov 
91*96f94587SAlexey Charkov 	dev_info(&pdev->dev,
92*96f94587SAlexey Charkov 		 "VIA/WonderMedia %s rev %s (%s)\n",
93*96f94587SAlexey Charkov 		 attrs->family,
94*96f94587SAlexey Charkov 		 attrs->revision,
95*96f94587SAlexey Charkov 		 attrs->soc_id);
96*96f94587SAlexey Charkov 
97*96f94587SAlexey Charkov 	platform_set_drvdata(pdev, soc_dev);
98*96f94587SAlexey Charkov 	return 0;
99*96f94587SAlexey Charkov }
100*96f94587SAlexey Charkov 
wmt_socinfo_remove(struct platform_device * pdev)101*96f94587SAlexey Charkov static void wmt_socinfo_remove(struct platform_device *pdev)
102*96f94587SAlexey Charkov {
103*96f94587SAlexey Charkov 	struct soc_device *soc_dev = platform_get_drvdata(pdev);
104*96f94587SAlexey Charkov 
105*96f94587SAlexey Charkov 	soc_device_unregister(soc_dev);
106*96f94587SAlexey Charkov }
107*96f94587SAlexey Charkov 
108*96f94587SAlexey Charkov static const struct of_device_id wmt_socinfo_ids[] = {
109*96f94587SAlexey Charkov 	{ .compatible = "via,vt8500-scc-id" },
110*96f94587SAlexey Charkov 	{ /* Sentinel */ },
111*96f94587SAlexey Charkov };
112*96f94587SAlexey Charkov 
113*96f94587SAlexey Charkov static struct platform_driver wmt_socinfo = {
114*96f94587SAlexey Charkov 	.probe = wmt_socinfo_probe,
115*96f94587SAlexey Charkov 	.remove = wmt_socinfo_remove,
116*96f94587SAlexey Charkov 	.driver = {
117*96f94587SAlexey Charkov 		.name = "wmt-socinfo",
118*96f94587SAlexey Charkov 		.of_match_table = wmt_socinfo_ids,
119*96f94587SAlexey Charkov 	},
120*96f94587SAlexey Charkov };
121*96f94587SAlexey Charkov module_platform_driver(wmt_socinfo);
122*96f94587SAlexey Charkov 
123*96f94587SAlexey Charkov MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
124*96f94587SAlexey Charkov MODULE_DESCRIPTION("VIA/WonderMedia socinfo driver");
125*96f94587SAlexey Charkov MODULE_LICENSE("GPL");
126