ux500-soc-id.c 5.0 KB

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