soc-realview.c 3.7 KB

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