system-controller.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * System controller support for Armada 370, 375 and XP platforms.
  4. *
  5. * Copyright (C) 2012 Marvell
  6. *
  7. * Lior Amsalem <[email protected]>
  8. * Gregory CLEMENT <[email protected]>
  9. * Thomas Petazzoni <[email protected]>
  10. *
  11. * The Armada 370, 375 and Armada XP SoCs have a range of
  12. * miscellaneous registers, that do not belong to a particular device,
  13. * but rather provide system-level features. This basic
  14. * system-controller driver provides a device tree binding for those
  15. * registers, and implements utility functions offering various
  16. * features related to those registers.
  17. *
  18. * For now, the feature set is limited to restarting the platform by a
  19. * soft-reset, but it might be extended in the future.
  20. */
  21. #include <linux/kernel.h>
  22. #include <linux/init.h>
  23. #include <linux/of_address.h>
  24. #include <linux/io.h>
  25. #include <linux/reboot.h>
  26. #include "common.h"
  27. #include "mvebu-soc-id.h"
  28. #include "pmsu.h"
  29. #define ARMADA_375_CRYPT0_ENG_TARGET 41
  30. #define ARMADA_375_CRYPT0_ENG_ATTR 1
  31. static void __iomem *system_controller_base;
  32. static phys_addr_t system_controller_phys_base;
  33. struct mvebu_system_controller {
  34. u32 rstoutn_mask_offset;
  35. u32 system_soft_reset_offset;
  36. u32 rstoutn_mask_reset_out_en;
  37. u32 system_soft_reset;
  38. u32 resume_boot_addr;
  39. u32 dev_id;
  40. u32 rev_id;
  41. };
  42. static struct mvebu_system_controller *mvebu_sc;
  43. static const struct mvebu_system_controller armada_370_xp_system_controller = {
  44. .rstoutn_mask_offset = 0x60,
  45. .system_soft_reset_offset = 0x64,
  46. .rstoutn_mask_reset_out_en = 0x1,
  47. .system_soft_reset = 0x1,
  48. .dev_id = 0x38,
  49. .rev_id = 0x3c,
  50. };
  51. static const struct mvebu_system_controller armada_375_system_controller = {
  52. .rstoutn_mask_offset = 0x54,
  53. .system_soft_reset_offset = 0x58,
  54. .rstoutn_mask_reset_out_en = 0x1,
  55. .system_soft_reset = 0x1,
  56. .resume_boot_addr = 0xd4,
  57. .dev_id = 0x38,
  58. .rev_id = 0x3c,
  59. };
  60. static const struct mvebu_system_controller orion_system_controller = {
  61. .rstoutn_mask_offset = 0x108,
  62. .system_soft_reset_offset = 0x10c,
  63. .rstoutn_mask_reset_out_en = 0x4,
  64. .system_soft_reset = 0x1,
  65. };
  66. static const struct of_device_id of_system_controller_table[] = {
  67. {
  68. .compatible = "marvell,orion-system-controller",
  69. .data = (void *) &orion_system_controller,
  70. }, {
  71. .compatible = "marvell,armada-370-xp-system-controller",
  72. .data = (void *) &armada_370_xp_system_controller,
  73. }, {
  74. .compatible = "marvell,armada-375-system-controller",
  75. .data = (void *) &armada_375_system_controller,
  76. },
  77. { /* end of list */ },
  78. };
  79. void mvebu_restart(enum reboot_mode mode, const char *cmd)
  80. {
  81. if (!system_controller_base) {
  82. pr_err("Cannot restart, system-controller not available: check the device tree\n");
  83. } else {
  84. /*
  85. * Enable soft reset to assert RSTOUTn.
  86. */
  87. writel(mvebu_sc->rstoutn_mask_reset_out_en,
  88. system_controller_base +
  89. mvebu_sc->rstoutn_mask_offset);
  90. /*
  91. * Assert soft reset.
  92. */
  93. writel(mvebu_sc->system_soft_reset,
  94. system_controller_base +
  95. mvebu_sc->system_soft_reset_offset);
  96. }
  97. while (1)
  98. ;
  99. }
  100. int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev)
  101. {
  102. if (of_machine_is_compatible("marvell,armada380") &&
  103. system_controller_base) {
  104. *dev = readl(system_controller_base + mvebu_sc->dev_id) >> 16;
  105. *rev = (readl(system_controller_base + mvebu_sc->rev_id) >> 8)
  106. & 0xF;
  107. return 0;
  108. } else
  109. return -ENODEV;
  110. }
  111. #if defined(CONFIG_SMP) && defined(CONFIG_MACH_MVEBU_V7)
  112. static void mvebu_armada375_smp_wa_init(void)
  113. {
  114. u32 dev, rev;
  115. phys_addr_t resume_addr_reg;
  116. if (mvebu_get_soc_id(&dev, &rev) != 0)
  117. return;
  118. if (rev != ARMADA_375_Z1_REV)
  119. return;
  120. resume_addr_reg = system_controller_phys_base +
  121. mvebu_sc->resume_boot_addr;
  122. mvebu_setup_boot_addr_wa(ARMADA_375_CRYPT0_ENG_TARGET,
  123. ARMADA_375_CRYPT0_ENG_ATTR,
  124. resume_addr_reg);
  125. }
  126. void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr)
  127. {
  128. BUG_ON(system_controller_base == NULL);
  129. BUG_ON(mvebu_sc->resume_boot_addr == 0);
  130. if (of_machine_is_compatible("marvell,armada375"))
  131. mvebu_armada375_smp_wa_init();
  132. writel(__pa_symbol(boot_addr), system_controller_base +
  133. mvebu_sc->resume_boot_addr);
  134. }
  135. #endif
  136. static int __init mvebu_system_controller_init(void)
  137. {
  138. const struct of_device_id *match;
  139. struct device_node *np;
  140. np = of_find_matching_node_and_match(NULL, of_system_controller_table,
  141. &match);
  142. if (np) {
  143. struct resource res;
  144. system_controller_base = of_iomap(np, 0);
  145. of_address_to_resource(np, 0, &res);
  146. system_controller_phys_base = res.start;
  147. mvebu_sc = (struct mvebu_system_controller *)match->data;
  148. of_node_put(np);
  149. }
  150. return 0;
  151. }
  152. early_initcall(mvebu_system_controller_init);