mpc52xx_common.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. *
  3. * Utility functions for the Freescale MPC52xx.
  4. *
  5. * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
  6. *
  7. * This file is licensed under the terms of the GNU General Public License
  8. * version 2. This program is licensed "as is" without any warranty of any
  9. * kind, whether express or implied.
  10. *
  11. */
  12. #undef DEBUG
  13. #include <linux/kernel.h>
  14. #include <linux/of_platform.h>
  15. #include <asm/io.h>
  16. #include <asm/prom.h>
  17. #include <asm/mpc52xx.h>
  18. /*
  19. * This variable is mapped in mpc52xx_map_wdt() and used in mpc52xx_restart().
  20. * Permanent mapping is required because mpc52xx_restart() can be called
  21. * from interrupt context while node mapping (which calls ioremap())
  22. * cannot be used at such point.
  23. */
  24. static volatile struct mpc52xx_gpt *mpc52xx_wdt = NULL;
  25. static void __iomem *
  26. mpc52xx_map_node(struct device_node *ofn)
  27. {
  28. const u32 *regaddr_p;
  29. u64 regaddr64, size64;
  30. if (!ofn)
  31. return NULL;
  32. regaddr_p = of_get_address(ofn, 0, &size64, NULL);
  33. if (!regaddr_p) {
  34. of_node_put(ofn);
  35. return NULL;
  36. }
  37. regaddr64 = of_translate_address(ofn, regaddr_p);
  38. of_node_put(ofn);
  39. return ioremap((u32)regaddr64, (u32)size64);
  40. }
  41. void __iomem *
  42. mpc52xx_find_and_map(const char *compatible)
  43. {
  44. return mpc52xx_map_node(
  45. of_find_compatible_node(NULL, NULL, compatible));
  46. }
  47. EXPORT_SYMBOL(mpc52xx_find_and_map);
  48. void __iomem *
  49. mpc52xx_find_and_map_path(const char *path)
  50. {
  51. return mpc52xx_map_node(of_find_node_by_path(path));
  52. }
  53. EXPORT_SYMBOL(mpc52xx_find_and_map_path);
  54. /**
  55. * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device
  56. * @node: device node
  57. *
  58. * Returns IPB bus frequency, or 0 if the bus frequency cannot be found.
  59. */
  60. unsigned int
  61. mpc52xx_find_ipb_freq(struct device_node *node)
  62. {
  63. struct device_node *np;
  64. const unsigned int *p_ipb_freq = NULL;
  65. of_node_get(node);
  66. while (node) {
  67. p_ipb_freq = of_get_property(node, "bus-frequency", NULL);
  68. if (p_ipb_freq)
  69. break;
  70. np = of_get_parent(node);
  71. of_node_put(node);
  72. node = np;
  73. }
  74. if (node)
  75. of_node_put(node);
  76. return p_ipb_freq ? *p_ipb_freq : 0;
  77. }
  78. EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
  79. /*
  80. * Configure the XLB arbiter settings to match what Linux expects.
  81. */
  82. void __init
  83. mpc5200_setup_xlb_arbiter(void)
  84. {
  85. struct mpc52xx_xlb __iomem *xlb;
  86. xlb = mpc52xx_find_and_map("mpc5200-xlb");
  87. if (!xlb) {
  88. printk(KERN_ERR __FILE__ ": "
  89. "Error mapping XLB in mpc52xx_setup_cpu(). "
  90. "Expect some abnormal behavior\n");
  91. return;
  92. }
  93. /* Configure the XLB Arbiter priorities */
  94. out_be32(&xlb->master_pri_enable, 0xff);
  95. out_be32(&xlb->master_priority, 0x11111111);
  96. /* Disable XLB pipelining
  97. * (cfr errate 292. We could do this only just before ATA PIO
  98. * transaction and re-enable it afterwards ...)
  99. */
  100. out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
  101. iounmap(xlb);
  102. }
  103. void __init
  104. mpc52xx_declare_of_platform_devices(void)
  105. {
  106. /* Find every child of the SOC node and add it to of_platform */
  107. if (of_platform_bus_probe(NULL, NULL, NULL))
  108. printk(KERN_ERR __FILE__ ": "
  109. "Error while probing of_platform bus\n");
  110. }
  111. void __init
  112. mpc52xx_map_wdt(void)
  113. {
  114. const void *has_wdt;
  115. struct device_node *np;
  116. /* mpc52xx_wdt is mapped here and used in mpc52xx_restart,
  117. * possibly from a interrupt context. wdt is only implement
  118. * on a gpt0, so check has-wdt property before mapping.
  119. */
  120. for_each_compatible_node(np, NULL, "fsl,mpc5200-gpt") {
  121. has_wdt = of_get_property(np, "fsl,has-wdt", NULL);
  122. if (has_wdt) {
  123. mpc52xx_wdt = mpc52xx_map_node(np);
  124. return;
  125. }
  126. }
  127. for_each_compatible_node(np, NULL, "mpc5200-gpt") {
  128. has_wdt = of_get_property(np, "has-wdt", NULL);
  129. if (has_wdt) {
  130. mpc52xx_wdt = mpc52xx_map_node(np);
  131. return;
  132. }
  133. }
  134. }
  135. void
  136. mpc52xx_restart(char *cmd)
  137. {
  138. local_irq_disable();
  139. /* Turn on the watchdog and wait for it to expire.
  140. * It effectively does a reset. */
  141. if (mpc52xx_wdt) {
  142. out_be32(&mpc52xx_wdt->mode, 0x00000000);
  143. out_be32(&mpc52xx_wdt->count, 0x000000ff);
  144. out_be32(&mpc52xx_wdt->mode, 0x00009004);
  145. } else
  146. printk("mpc52xx_restart: Can't access wdt. "
  147. "Restart impossible, system halted.\n");
  148. while (1);
  149. }