soc-integrator.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Copyright (C) 2014 Linaro Ltd.
  3. *
  4. * Author: Linus Walleij <linus.walleij@linaro.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2, as
  8. * published by the Free Software Foundation.
  9. *
  10. */
  11. #include <linux/init.h>
  12. #include <linux/io.h>
  13. #include <linux/slab.h>
  14. #include <linux/sys_soc.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/mfd/syscon.h>
  17. #include <linux/regmap.h>
  18. #include <linux/of.h>
  19. #define INTEGRATOR_HDR_ID_OFFSET 0x00
  20. static u32 integrator_coreid;
  21. static const struct of_device_id integrator_cm_match[] = {
  22. { .compatible = "arm,core-module-integrator", },
  23. { }
  24. };
  25. static const char *integrator_arch_str(u32 id)
  26. {
  27. switch ((id >> 16) & 0xff) {
  28. case 0x00:
  29. return "ASB little-endian";
  30. case 0x01:
  31. return "AHB little-endian";
  32. case 0x03:
  33. return "AHB-Lite system bus, bi-endian";
  34. case 0x04:
  35. return "AHB";
  36. case 0x08:
  37. return "AHB system bus, ASB processor bus";
  38. default:
  39. return "Unknown";
  40. }
  41. }
  42. static const char *integrator_fpga_str(u32 id)
  43. {
  44. switch ((id >> 12) & 0xf) {
  45. case 0x01:
  46. return "XC4062";
  47. case 0x02:
  48. return "XC4085";
  49. case 0x03:
  50. return "XVC600";
  51. case 0x04:
  52. return "EPM7256AE (Altera PLD)";
  53. default:
  54. return "Unknown";
  55. }
  56. }
  57. static ssize_t integrator_get_manf(struct device *dev,
  58. struct device_attribute *attr,
  59. char *buf)
  60. {
  61. return sprintf(buf, "%02x\n", integrator_coreid >> 24);
  62. }
  63. static struct device_attribute integrator_manf_attr =
  64. __ATTR(manufacturer, S_IRUGO, integrator_get_manf, NULL);
  65. static ssize_t integrator_get_arch(struct device *dev,
  66. struct device_attribute *attr,
  67. char *buf)
  68. {
  69. return sprintf(buf, "%s\n", integrator_arch_str(integrator_coreid));
  70. }
  71. static struct device_attribute integrator_arch_attr =
  72. __ATTR(arch, S_IRUGO, integrator_get_arch, NULL);
  73. static ssize_t integrator_get_fpga(struct device *dev,
  74. struct device_attribute *attr,
  75. char *buf)
  76. {
  77. return sprintf(buf, "%s\n", integrator_fpga_str(integrator_coreid));
  78. }
  79. static struct device_attribute integrator_fpga_attr =
  80. __ATTR(fpga, S_IRUGO, integrator_get_fpga, NULL);
  81. static ssize_t integrator_get_build(struct device *dev,
  82. struct device_attribute *attr,
  83. char *buf)
  84. {
  85. return sprintf(buf, "%02x\n", (integrator_coreid >> 4) & 0xFF);
  86. }
  87. static struct device_attribute integrator_build_attr =
  88. __ATTR(build, S_IRUGO, integrator_get_build, NULL);
  89. static int __init integrator_soc_init(void)
  90. {
  91. static struct regmap *syscon_regmap;
  92. struct soc_device *soc_dev;
  93. struct soc_device_attribute *soc_dev_attr;
  94. struct device_node *np;
  95. struct device *dev;
  96. u32 val;
  97. int ret;
  98. np = of_find_matching_node(NULL, integrator_cm_match);
  99. if (!np)
  100. return -ENODEV;
  101. syscon_regmap = syscon_node_to_regmap(np);
  102. if (IS_ERR(syscon_regmap))
  103. return PTR_ERR(syscon_regmap);
  104. ret = regmap_read(syscon_regmap, INTEGRATOR_HDR_ID_OFFSET,
  105. &val);
  106. if (ret)
  107. return -ENODEV;
  108. integrator_coreid = val;
  109. soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
  110. if (!soc_dev_attr)
  111. return -ENOMEM;
  112. soc_dev_attr->soc_id = "Integrator";
  113. soc_dev_attr->machine = "Integrator";
  114. soc_dev_attr->family = "Versatile";
  115. soc_dev = soc_device_register(soc_dev_attr);
  116. if (IS_ERR(soc_dev)) {
  117. kfree(soc_dev_attr);
  118. return -ENODEV;
  119. }
  120. dev = soc_device_to_device(soc_dev);
  121. device_create_file(dev, &integrator_manf_attr);
  122. device_create_file(dev, &integrator_arch_attr);
  123. device_create_file(dev, &integrator_fpga_attr);
  124. device_create_file(dev, &integrator_build_attr);
  125. dev_info(dev, "Detected ARM core module:\n");
  126. dev_info(dev, " Manufacturer: %02x\n", (val >> 24));
  127. dev_info(dev, " Architecture: %s\n", integrator_arch_str(val));
  128. dev_info(dev, " FPGA: %s\n", integrator_fpga_str(val));
  129. dev_info(dev, " Build: %02x\n", (val >> 4) & 0xFF);
  130. dev_info(dev, " Rev: %c\n", ('A' + (val & 0x03)));
  131. return 0;
  132. }
  133. device_initcall(integrator_soc_init);