Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * TI K3 SoC info driver
0004  *
0005  * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
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  * Bits:
0020  *  31-28 VARIANT   Device variant
0021  *  27-12 PARTNO    Part number
0022  *  11-1  MFG       Indicates TI as manufacturer (0x17)
0023  *  1           Always 1
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     { /* sentinel */ },
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);