Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* Copyright 2019 IBM Corp. */
0003 
0004 #include <linux/io.h>
0005 #include <linux/of.h>
0006 #include <linux/of_address.h>
0007 #include <linux/of_platform.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/slab.h>
0010 #include <linux/sys_soc.h>
0011 
0012 static struct {
0013     const char *name;
0014     const u32 id;
0015 } const rev_table[] = {
0016     /* AST2400 */
0017     { "AST2400", 0x02000303 },
0018     { "AST1400", 0x02010103 },
0019     { "AST1250", 0x02010303 },
0020     /* AST2500 */
0021     { "AST2500", 0x04000303 },
0022     { "AST2510", 0x04000103 },
0023     { "AST2520", 0x04000203 },
0024     { "AST2530", 0x04000403 },
0025     /* AST2600 */
0026     { "AST2600", 0x05000303 },
0027     { "AST2620", 0x05010203 },
0028     { "AST2605", 0x05030103 },
0029     { "AST2625", 0x05030403 },
0030 };
0031 
0032 static const char *siliconid_to_name(u32 siliconid)
0033 {
0034     unsigned int id = siliconid & 0xff00ffff;
0035     unsigned int i;
0036 
0037     for (i = 0 ; i < ARRAY_SIZE(rev_table) ; ++i) {
0038         if (rev_table[i].id == id)
0039             return rev_table[i].name;
0040     }
0041 
0042     return "Unknown";
0043 }
0044 
0045 static const char *siliconid_to_rev(u32 siliconid)
0046 {
0047     unsigned int rev = (siliconid >> 16) & 0xff;
0048     unsigned int gen = (siliconid >> 24) & 0xff;
0049 
0050     if (gen < 0x5) {
0051         /* AST2500 and below */
0052         switch (rev) {
0053         case 0:
0054             return "A0";
0055         case 1:
0056             return "A1";
0057         case 3:
0058             return "A2";
0059         }
0060     } else {
0061         /* AST2600 */
0062         switch (rev) {
0063         case 0:
0064             return "A0";
0065         case 1:
0066             return "A1";
0067         case 2:
0068             return "A2";
0069         case 3:
0070             return "A3";
0071         }
0072     }
0073 
0074     return "??";
0075 }
0076 
0077 static int __init aspeed_socinfo_init(void)
0078 {
0079     struct soc_device_attribute *attrs;
0080     struct soc_device *soc_dev;
0081     struct device_node *np;
0082     void __iomem *reg;
0083     bool has_chipid = false;
0084     u32 siliconid;
0085     u32 chipid[2];
0086     const char *machine = NULL;
0087 
0088     np = of_find_compatible_node(NULL, NULL, "aspeed,silicon-id");
0089     if (!of_device_is_available(np)) {
0090         of_node_put(np);
0091         return -ENODEV;
0092     }
0093 
0094     reg = of_iomap(np, 0);
0095     if (!reg) {
0096         of_node_put(np);
0097         return -ENODEV;
0098     }
0099     siliconid = readl(reg);
0100     iounmap(reg);
0101 
0102     /* This is optional, the ast2400 does not have it */
0103     reg = of_iomap(np, 1);
0104     if (reg) {
0105         has_chipid = true;
0106         chipid[0] = readl(reg);
0107         chipid[1] = readl(reg + 4);
0108         iounmap(reg);
0109     }
0110     of_node_put(np);
0111 
0112     attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
0113     if (!attrs)
0114         return -ENODEV;
0115 
0116     /*
0117      * Machine: Romulus BMC
0118      * Family: AST2500
0119      * Revision: A1
0120      * SoC ID: raw silicon revision id
0121      * Serial Number: 64-bit chipid
0122      */
0123 
0124     np = of_find_node_by_path("/");
0125     of_property_read_string(np, "model", &machine);
0126     if (machine)
0127         attrs->machine = kstrdup(machine, GFP_KERNEL);
0128     of_node_put(np);
0129 
0130     attrs->family = siliconid_to_name(siliconid);
0131     attrs->revision = siliconid_to_rev(siliconid);
0132     attrs->soc_id = kasprintf(GFP_KERNEL, "%08x", siliconid);
0133 
0134     if (has_chipid)
0135         attrs->serial_number = kasprintf(GFP_KERNEL, "%08x%08x",
0136                          chipid[1], chipid[0]);
0137 
0138     soc_dev = soc_device_register(attrs);
0139     if (IS_ERR(soc_dev)) {
0140         kfree(attrs->soc_id);
0141         kfree(attrs->serial_number);
0142         kfree(attrs);
0143         return PTR_ERR(soc_dev);
0144     }
0145 
0146     pr_info("ASPEED %s rev %s (%s)\n",
0147             attrs->family,
0148             attrs->revision,
0149             attrs->soc_id);
0150 
0151     return 0;
0152 }
0153 early_initcall(aspeed_socinfo_init);