1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/
4 *	Dave Gerlach <d-gerlach@ti.com>
5 */
6
7#include <dm.h>
8#include <soc.h>
9
10#include <asm/arch/hardware.h>
11#include <asm/io.h>
12
13struct soc_ti_k3_plat {
14	const char *family;
15	const char *revision;
16};
17
18static const char *get_family_string(u32 idreg)
19{
20	const char *family;
21	u32 soc;
22
23	soc = (idreg & JTAG_ID_PARTNO_MASK) >> JTAG_ID_PARTNO_SHIFT;
24
25	switch (soc) {
26	case JTAG_ID_PARTNO_AM65X:
27		family = "AM65X";
28		break;
29	case JTAG_ID_PARTNO_J721E:
30		family = "J721E";
31		break;
32	case JTAG_ID_PARTNO_J7200:
33		family = "J7200";
34		break;
35	case JTAG_ID_PARTNO_AM64X:
36		family = "AM64X";
37		break;
38	case JTAG_ID_PARTNO_J721S2:
39		family = "J721S2";
40		break;
41	case JTAG_ID_PARTNO_AM62X:
42		family = "AM62X";
43		break;
44	case JTAG_ID_PARTNO_AM62AX:
45		family = "AM62AX";
46		break;
47	case JTAG_ID_PARTNO_J784S4:
48		family = "J784S4";
49		break;
50	case JTAG_ID_PARTNO_AM62PX:
51		family = "AM62PX";
52		break;
53	default:
54		family = "Unknown Silicon";
55	};
56
57	return family;
58}
59
60static char *j721e_rev_string_map[] = {
61	"1.0", "1.1",
62};
63
64static char *typical_rev_string_map[] = {
65	"1.0", "2.0", "3.0",
66};
67
68static const char *get_rev_string(u32 idreg)
69{
70	u32 rev;
71	u32 soc;
72
73	rev = (idreg & JTAG_ID_VARIANT_MASK) >> JTAG_ID_VARIANT_SHIFT;
74	soc = (idreg & JTAG_ID_PARTNO_MASK) >> JTAG_ID_PARTNO_SHIFT;
75
76	switch (soc) {
77	case JTAG_ID_PARTNO_J721E:
78		if (rev >= ARRAY_SIZE(j721e_rev_string_map))
79			goto bail;
80		return j721e_rev_string_map[rev];
81
82	default:
83		if (rev >= ARRAY_SIZE(typical_rev_string_map))
84			goto bail;
85		return typical_rev_string_map[rev];
86	};
87
88bail:
89	return "Unknown Revision";
90}
91
92static int soc_ti_k3_get_family(struct udevice *dev, char *buf, int size)
93{
94	struct soc_ti_k3_plat *plat = dev_get_plat(dev);
95
96	snprintf(buf, size, "%s", plat->family);
97
98	return 0;
99}
100
101static int soc_ti_k3_get_revision(struct udevice *dev, char *buf, int size)
102{
103	struct soc_ti_k3_plat *plat = dev_get_plat(dev);
104
105	snprintf(buf, size, "SR%s", plat->revision);
106
107	return 0;
108}
109
110static const struct soc_ops soc_ti_k3_ops = {
111	.get_family = soc_ti_k3_get_family,
112	.get_revision = soc_ti_k3_get_revision,
113};
114
115int soc_ti_k3_probe(struct udevice *dev)
116{
117	struct soc_ti_k3_plat *plat = dev_get_plat(dev);
118	u32 idreg;
119	void *idreg_addr;
120
121	idreg_addr = dev_read_addr_ptr(dev);
122	if (!idreg_addr)
123		return -EINVAL;
124
125	idreg = readl(idreg_addr);
126
127	plat->family = get_family_string(idreg);
128	plat->revision = get_rev_string(idreg);
129
130	return 0;
131}
132
133static const struct udevice_id soc_ti_k3_ids[] = {
134	{ .compatible = "ti,am654-chipid" },
135	{ }
136};
137
138U_BOOT_DRIVER(soc_ti_k3) = {
139	.name           = "soc_ti_k3",
140	.id             = UCLASS_SOC,
141	.ops		= &soc_ti_k3_ops,
142	.of_match       = soc_ti_k3_ids,
143	.probe          = soc_ti_k3_probe,
144	.plat_auto	= sizeof(struct soc_ti_k3_plat),
145};
146