0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/mfd/syscon.h>
0009 #include <linux/of.h>
0010 #include <linux/of_address.h>
0011 #include <linux/regmap.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/slab.h>
0014 #include <linux/string.h>
0015 #include <linux/sys_soc.h>
0016
0017 #define CTRLMMR_WKUP_JTAGID_REG 0
0018
0019
0020
0021
0022
0023
0024
0025 #define CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT (28)
0026 #define CTRLMMR_WKUP_JTAGID_VARIANT_MASK GENMASK(31, 28)
0027
0028 #define CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT (12)
0029 #define CTRLMMR_WKUP_JTAGID_PARTNO_MASK GENMASK(27, 12)
0030
0031 #define CTRLMMR_WKUP_JTAGID_MFG_SHIFT (1)
0032 #define CTRLMMR_WKUP_JTAGID_MFG_MASK GENMASK(11, 1)
0033
0034 #define CTRLMMR_WKUP_JTAGID_MFG_TI 0x17
0035
0036 static const struct k3_soc_id {
0037 unsigned int id;
0038 const char *family_name;
0039 } k3_soc_ids[] = {
0040 { 0xBB5A, "AM65X" },
0041 { 0xBB64, "J721E" },
0042 { 0xBB6D, "J7200" },
0043 { 0xBB38, "AM64X" },
0044 { 0xBB75, "J721S2"},
0045 { 0xBB7E, "AM62X" },
0046 };
0047
0048 static int
0049 k3_chipinfo_partno_to_names(unsigned int partno,
0050 struct soc_device_attribute *soc_dev_attr)
0051 {
0052 int i;
0053
0054 for (i = 0; i < ARRAY_SIZE(k3_soc_ids); i++)
0055 if (partno == k3_soc_ids[i].id) {
0056 soc_dev_attr->family = k3_soc_ids[i].family_name;
0057 return 0;
0058 }
0059
0060 return -EINVAL;
0061 }
0062
0063 static int k3_chipinfo_probe(struct platform_device *pdev)
0064 {
0065 struct device_node *node = pdev->dev.of_node;
0066 struct soc_device_attribute *soc_dev_attr;
0067 struct device *dev = &pdev->dev;
0068 struct soc_device *soc_dev;
0069 struct regmap *regmap;
0070 u32 partno_id;
0071 u32 variant;
0072 u32 jtag_id;
0073 u32 mfg;
0074 int ret;
0075
0076 regmap = device_node_to_regmap(node);
0077 if (IS_ERR(regmap))
0078 return PTR_ERR(regmap);
0079
0080 ret = regmap_read(regmap, CTRLMMR_WKUP_JTAGID_REG, &jtag_id);
0081 if (ret < 0)
0082 return ret;
0083
0084 mfg = (jtag_id & CTRLMMR_WKUP_JTAGID_MFG_MASK) >>
0085 CTRLMMR_WKUP_JTAGID_MFG_SHIFT;
0086
0087 if (mfg != CTRLMMR_WKUP_JTAGID_MFG_TI) {
0088 dev_err(dev, "Invalid MFG SoC\n");
0089 return -ENODEV;
0090 }
0091
0092 variant = (jtag_id & CTRLMMR_WKUP_JTAGID_VARIANT_MASK) >>
0093 CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT;
0094 variant++;
0095
0096 partno_id = (jtag_id & CTRLMMR_WKUP_JTAGID_PARTNO_MASK) >>
0097 CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT;
0098
0099 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
0100 if (!soc_dev_attr)
0101 return -ENOMEM;
0102
0103 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0", variant);
0104 if (!soc_dev_attr->revision) {
0105 ret = -ENOMEM;
0106 goto err;
0107 }
0108
0109 ret = k3_chipinfo_partno_to_names(partno_id, soc_dev_attr);
0110 if (ret) {
0111 dev_err(dev, "Unknown SoC JTAGID[0x%08X]\n", jtag_id);
0112 ret = -ENODEV;
0113 goto err_free_rev;
0114 }
0115
0116 node = of_find_node_by_path("/");
0117 of_property_read_string(node, "model", &soc_dev_attr->machine);
0118 of_node_put(node);
0119
0120 soc_dev = soc_device_register(soc_dev_attr);
0121 if (IS_ERR(soc_dev)) {
0122 ret = PTR_ERR(soc_dev);
0123 goto err_free_rev;
0124 }
0125
0126 dev_info(dev, "Family:%s rev:%s JTAGID[0x%08x] Detected\n",
0127 soc_dev_attr->family,
0128 soc_dev_attr->revision, jtag_id);
0129
0130 return 0;
0131
0132 err_free_rev:
0133 kfree(soc_dev_attr->revision);
0134 err:
0135 kfree(soc_dev_attr);
0136 return ret;
0137 }
0138
0139 static const struct of_device_id k3_chipinfo_of_match[] = {
0140 { .compatible = "ti,am654-chipid", },
0141 { },
0142 };
0143
0144 static struct platform_driver k3_chipinfo_driver = {
0145 .driver = {
0146 .name = "k3-chipinfo",
0147 .of_match_table = k3_chipinfo_of_match,
0148 },
0149 .probe = k3_chipinfo_probe,
0150 };
0151
0152 static int __init k3_chipinfo_init(void)
0153 {
0154 return platform_driver_register(&k3_chipinfo_driver);
0155 }
0156 subsys_initcall(k3_chipinfo_init);