1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) ST-Ericsson SA 2010 4 * 5 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/init.h> 10 #include <linux/io.h> 11 #include <linux/module.h> 12 #include <linux/random.h> 13 #include <linux/slab.h> 14 #include <linux/of.h> 15 #include <linux/of_address.h> 16 #include <linux/sys_soc.h> 17 18 #include <asm/cputype.h> 19 #include <asm/tlbflush.h> 20 #include <asm/cacheflush.h> 21 #include <asm/mach/map.h> 22 23 /** 24 * struct dbx500_asic_id - fields of the ASIC ID 25 * @process: the manufacturing process, 0x40 is 40 nm 0x00 is "standard" 26 * @partnumber: hithereto 0x8500 for DB8500 27 * @revision: version code in the series 28 */ 29 struct dbx500_asic_id { 30 u16 partnumber; 31 u8 revision; 32 u8 process; 33 }; 34 35 static struct dbx500_asic_id dbx500_id; 36 37 static unsigned int __init ux500_read_asicid(phys_addr_t addr) 38 { 39 void __iomem *virt = ioremap(addr, 4); 40 unsigned int asicid; 41 42 if (!virt) 43 return 0; 44 45 asicid = readl(virt); 46 iounmap(virt); 47 48 return asicid; 49 } 50 51 static void ux500_print_soc_info(unsigned int asicid) 52 { 53 unsigned int rev = dbx500_id.revision; 54 55 pr_info("DB%4x ", dbx500_id.partnumber); 56 57 if (rev == 0x01) 58 pr_cont("Early Drop"); 59 else if (rev >= 0xA0) 60 pr_cont("v%d.%d" , (rev >> 4) - 0xA + 1, rev & 0xf); 61 else 62 pr_cont("Unknown"); 63 64 pr_cont(" [%#010x]\n", asicid); 65 } 66 67 static unsigned int partnumber(unsigned int asicid) 68 { 69 return (asicid >> 8) & 0xffff; 70 } 71 72 /* 73 * SOC MIDR ASICID ADDRESS ASICID VALUE 74 * DB8500ed 0x410fc090 0x9001FFF4 0x00850001 75 * DB8500v1 0x411fc091 0x9001FFF4 0x008500A0 76 * DB8500v1.1 0x411fc091 0x9001FFF4 0x008500A1 77 * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0 78 * DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2 79 * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0 80 * DB9540 0x413fc090 0xFFFFDBF4 0x009540xx 81 */ 82 83 static void __init ux500_setup_id(void) 84 { 85 unsigned int cpuid = read_cpuid_id(); 86 unsigned int asicid = 0; 87 phys_addr_t addr = 0; 88 89 switch (cpuid) { 90 case 0x410fc090: /* DB8500ed */ 91 case 0x411fc091: /* DB8500v1 */ 92 addr = 0x9001FFF4; 93 break; 94 95 case 0x412fc091: /* DB8520 / DB8500v2 / DB5500v1 */ 96 asicid = ux500_read_asicid(0x9001DBF4); 97 if (partnumber(asicid) == 0x8500 || 98 partnumber(asicid) == 0x8520) 99 /* DB8500v2 */ 100 break; 101 102 /* DB5500v1 */ 103 addr = 0x9001FFF4; 104 break; 105 106 case 0x413fc090: /* DB9540 */ 107 addr = 0xFFFFDBF4; 108 break; 109 } 110 111 if (addr) 112 asicid = ux500_read_asicid(addr); 113 114 if (!asicid) { 115 pr_err("Unable to identify SoC\n"); 116 BUG(); 117 } 118 119 dbx500_id.process = asicid >> 24; 120 dbx500_id.partnumber = partnumber(asicid); 121 dbx500_id.revision = asicid & 0xff; 122 123 ux500_print_soc_info(asicid); 124 } 125 126 static const char * __init ux500_get_machine(void) 127 { 128 return kasprintf(GFP_KERNEL, "DB%4x", dbx500_id.partnumber); 129 } 130 131 static const char * __init ux500_get_family(void) 132 { 133 return kasprintf(GFP_KERNEL, "ux500"); 134 } 135 136 static const char * __init ux500_get_revision(void) 137 { 138 unsigned int rev = dbx500_id.revision; 139 140 if (rev == 0x01) 141 return kasprintf(GFP_KERNEL, "%s", "ED"); 142 else if (rev >= 0xA0) 143 return kasprintf(GFP_KERNEL, "%d.%d", 144 (rev >> 4) - 0xA + 1, rev & 0xf); 145 146 return kasprintf(GFP_KERNEL, "%s", "Unknown"); 147 } 148 149 static ssize_t 150 process_show(struct device *dev, struct device_attribute *attr, char *buf) 151 { 152 if (dbx500_id.process == 0x00) 153 return sprintf(buf, "Standard\n"); 154 155 return sprintf(buf, "%02xnm\n", dbx500_id.process); 156 } 157 158 static DEVICE_ATTR_RO(process); 159 160 static struct attribute *ux500_soc_attrs[] = { 161 &dev_attr_process.attr, 162 NULL 163 }; 164 165 ATTRIBUTE_GROUPS(ux500_soc); 166 167 static const char *db8500_read_soc_id(struct device_node *backupram) 168 { 169 void __iomem *base; 170 void __iomem *uid; 171 const char *retstr; 172 173 base = of_iomap(backupram, 0); 174 if (!base) 175 return NULL; 176 uid = base + 0x1fc0; 177 178 /* Throw these device-specific numbers into the entropy pool */ 179 add_device_randomness(uid, 0x14); 180 retstr = kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x", 181 readl((u32 *)uid+0), 182 readl((u32 *)uid+1), readl((u32 *)uid+2), 183 readl((u32 *)uid+3), readl((u32 *)uid+4)); 184 iounmap(base); 185 return retstr; 186 } 187 188 static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr, 189 struct device_node *backupram) 190 { 191 soc_dev_attr->soc_id = db8500_read_soc_id(backupram); 192 soc_dev_attr->machine = ux500_get_machine(); 193 soc_dev_attr->family = ux500_get_family(); 194 soc_dev_attr->revision = ux500_get_revision(); 195 soc_dev_attr->custom_attr_group = ux500_soc_groups[0]; 196 } 197 198 static int __init ux500_soc_device_init(void) 199 { 200 struct soc_device *soc_dev; 201 struct soc_device_attribute *soc_dev_attr; 202 struct device_node *backupram; 203 204 backupram = of_find_compatible_node(NULL, NULL, "ste,dbx500-backupram"); 205 if (!backupram) 206 return 0; 207 208 ux500_setup_id(); 209 210 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 211 if (!soc_dev_attr) { 212 of_node_put(backupram); 213 return -ENOMEM; 214 } 215 216 soc_info_populate(soc_dev_attr, backupram); 217 of_node_put(backupram); 218 219 soc_dev = soc_device_register(soc_dev_attr); 220 if (IS_ERR(soc_dev)) { 221 kfree(soc_dev_attr); 222 return PTR_ERR(soc_dev); 223 } 224 225 return 0; 226 } 227 subsys_initcall(ux500_soc_device_init); 228