0001
0002
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
0017 { "AST2400", 0x02000303 },
0018 { "AST1400", 0x02010103 },
0019 { "AST1250", 0x02010303 },
0020
0021 { "AST2500", 0x04000303 },
0022 { "AST2510", 0x04000103 },
0023 { "AST2520", 0x04000203 },
0024 { "AST2530", 0x04000403 },
0025
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
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
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
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
0118
0119
0120
0121
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);