soc-realview.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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. /* System ID in syscon */
  20. #define REALVIEW_SYS_ID_OFFSET 0x00
  21. static const struct of_device_id realview_soc_of_match[] = {
  22. { .compatible = "arm,realview-eb-soc", },
  23. { .compatible = "arm,realview-pb1176-soc", },
  24. { .compatible = "arm,realview-pb11mp-soc", },
  25. { .compatible = "arm,realview-pba8-soc", },
  26. { .compatible = "arm,realview-pbx-soc", },
  27. { }
  28. };
  29. static u32 realview_coreid;
  30. static const char *realview_board_str(u32 id)
  31. {
  32. switch ((id >> 16) & 0xfff) {
  33. case 0x0147:
  34. return "HBI-0147";
  35. case 0x0159:
  36. return "HBI-0159";
  37. default:
  38. return "Unknown";
  39. }
  40. }
  41. static const char *realview_arch_str(u32 id)
  42. {
  43. switch ((id >> 8) & 0xf) {
  44. case 0x04:
  45. return "AHB";
  46. case 0x05:
  47. return "Multi-layer AXI";
  48. default:
  49. return "Unknown";
  50. }
  51. }
  52. static ssize_t realview_get_manf(struct device *dev,
  53. struct device_attribute *attr,
  54. char *buf)
  55. {
  56. return sprintf(buf, "%02x\n", realview_coreid >> 24);
  57. }
  58. static struct device_attribute realview_manf_attr =
  59. __ATTR(manufacturer, S_IRUGO, realview_get_manf, NULL);
  60. static ssize_t realview_get_board(struct device *dev,
  61. struct device_attribute *attr,
  62. char *buf)
  63. {
  64. return sprintf(buf, "%s\n", realview_board_str(realview_coreid));
  65. }
  66. static struct device_attribute realview_board_attr =
  67. __ATTR(board, S_IRUGO, realview_get_board, NULL);
  68. static ssize_t realview_get_arch(struct device *dev,
  69. struct device_attribute *attr,
  70. char *buf)
  71. {
  72. return sprintf(buf, "%s\n", realview_arch_str(realview_coreid));
  73. }
  74. static struct device_attribute realview_arch_attr =
  75. __ATTR(fpga, S_IRUGO, realview_get_arch, NULL);
  76. static ssize_t realview_get_build(struct device *dev,
  77. struct device_attribute *attr,
  78. char *buf)
  79. {
  80. return sprintf(buf, "%02x\n", (realview_coreid & 0xFF));
  81. }
  82. static struct device_attribute realview_build_attr =
  83. __ATTR(build, S_IRUGO, realview_get_build, NULL);
  84. static int realview_soc_probe(struct platform_device *pdev)
  85. {
  86. static struct regmap *syscon_regmap;
  87. struct soc_device *soc_dev;
  88. struct soc_device_attribute *soc_dev_attr;
  89. struct device_node *np = pdev->dev.of_node;
  90. int ret;
  91. syscon_regmap = syscon_regmap_lookup_by_phandle(np, "regmap");
  92. if (IS_ERR(syscon_regmap))
  93. return PTR_ERR(syscon_regmap);
  94. soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
  95. if (!soc_dev_attr)
  96. return -ENOMEM;
  97. ret = of_property_read_string(np, "compatible",
  98. &soc_dev_attr->soc_id);
  99. if (ret)
  100. return -EINVAL;
  101. soc_dev_attr->machine = "RealView";
  102. soc_dev_attr->family = "Versatile";
  103. soc_dev = soc_device_register(soc_dev_attr);
  104. if (IS_ERR(soc_dev)) {
  105. kfree(soc_dev_attr);
  106. return -ENODEV;
  107. }
  108. ret = regmap_read(syscon_regmap, REALVIEW_SYS_ID_OFFSET,
  109. &realview_coreid);
  110. if (ret)
  111. return -ENODEV;
  112. device_create_file(soc_device_to_device(soc_dev), &realview_manf_attr);
  113. device_create_file(soc_device_to_device(soc_dev), &realview_board_attr);
  114. device_create_file(soc_device_to_device(soc_dev), &realview_arch_attr);
  115. device_create_file(soc_device_to_device(soc_dev), &realview_build_attr);
  116. dev_info(&pdev->dev, "RealView Syscon Core ID: 0x%08x\n",
  117. realview_coreid);
  118. /* FIXME: add attributes for SoC to sysfs */
  119. return 0;
  120. }
  121. static struct platform_driver realview_soc_driver = {
  122. .probe = realview_soc_probe,
  123. .driver = {
  124. .name = "realview-soc",
  125. .of_match_table = realview_soc_of_match,
  126. },
  127. };
  128. builtin_platform_driver(realview_soc_driver);