1 /* 2 * Copyright (C) ST-Ericsson SA 2010 3 * 4 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson 5 * License terms: GNU General Public License (GPL) version 2 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 ux500_get_process(struct device *dev, 150 struct device_attribute *attr, 151 char *buf) 152 { 153 if (dbx500_id.process == 0x00) 154 return sprintf(buf, "Standard\n"); 155 156 return sprintf(buf, "%02xnm\n", dbx500_id.process); 157 } 158 159 static const char *db8500_read_soc_id(struct device_node *backupram) 160 { 161 void __iomem *base; 162 void __iomem *uid; 163 const char *retstr; 164 165 base = of_iomap(backupram, 0); 166 if (!base) 167 return NULL; 168 uid = base + 0x1fc0; 169 170 /* Throw these device-specific numbers into the entropy pool */ 171 add_device_randomness(uid, 0x14); 172 retstr = kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x", 173 readl((u32 *)uid+0), 174 readl((u32 *)uid+1), readl((u32 *)uid+2), 175 readl((u32 *)uid+3), readl((u32 *)uid+4)); 176 iounmap(base); 177 return retstr; 178 } 179 180 static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr, 181 struct device_node *backupram) 182 { 183 soc_dev_attr->soc_id = db8500_read_soc_id(backupram); 184 soc_dev_attr->machine = ux500_get_machine(); 185 soc_dev_attr->family = ux500_get_family(); 186 soc_dev_attr->revision = ux500_get_revision(); 187 } 188 189 static const struct device_attribute ux500_soc_attr = 190 __ATTR(process, S_IRUGO, ux500_get_process, NULL); 191 192 static int __init ux500_soc_device_init(void) 193 { 194 struct device *parent; 195 struct soc_device *soc_dev; 196 struct soc_device_attribute *soc_dev_attr; 197 struct device_node *backupram; 198 199 backupram = of_find_compatible_node(NULL, NULL, "ste,dbx500-backupram"); 200 if (!backupram) 201 return 0; 202 203 ux500_setup_id(); 204 205 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 206 if (!soc_dev_attr) 207 return -ENOMEM; 208 209 soc_info_populate(soc_dev_attr, backupram); 210 211 soc_dev = soc_device_register(soc_dev_attr); 212 if (IS_ERR(soc_dev)) { 213 kfree(soc_dev_attr); 214 return PTR_ERR(soc_dev); 215 } 216 217 parent = soc_device_to_device(soc_dev); 218 device_create_file(parent, &ux500_soc_attr); 219 220 return 0; 221 } 222 subsys_initcall(ux500_soc_device_init); 223