mpc52xx_common.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. /**
  26. * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device
  27. * @node: device node
  28. *
  29. * Returns IPB bus frequency, or 0 if the bus frequency cannot be found.
  30. */
  31. unsigned int
  32. mpc52xx_find_ipb_freq(struct device_node *node)
  33. {
  34. struct device_node *np;
  35. const unsigned int *p_ipb_freq = NULL;
  36. of_node_get(node);
  37. while (node) {
  38. p_ipb_freq = of_get_property(node, "bus-frequency", NULL);
  39. if (p_ipb_freq)
  40. break;
  41. np = of_get_parent(node);
  42. of_node_put(node);
  43. node = np;
  44. }
  45. if (node)
  46. of_node_put(node);
  47. return p_ipb_freq ? *p_ipb_freq : 0;
  48. }
  49. EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
  50. /*
  51. * Configure the XLB arbiter settings to match what Linux expects.
  52. */
  53. void __init
  54. mpc5200_setup_xlb_arbiter(void)
  55. {
  56. struct device_node *np;
  57. struct mpc52xx_xlb __iomem *xlb;
  58. np = of_find_compatible_node(NULL, NULL, "mpc5200-xlb");
  59. xlb = of_iomap(np, 0);
  60. of_node_put(np);
  61. if (!xlb) {
  62. printk(KERN_ERR __FILE__ ": "
  63. "Error mapping XLB in mpc52xx_setup_cpu(). "
  64. "Expect some abnormal behavior\n");
  65. return;
  66. }
  67. /* Configure the XLB Arbiter priorities */
  68. out_be32(&xlb->master_pri_enable, 0xff);
  69. out_be32(&xlb->master_priority, 0x11111111);
  70. /* Disable XLB pipelining
  71. * (cfr errate 292. We could do this only just before ATA PIO
  72. * transaction and re-enable it afterwards ...)
  73. */
  74. out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
  75. iounmap(xlb);
  76. }
  77. static struct of_device_id mpc52xx_bus_ids[] __initdata= {
  78. { .compatible = "fsl,mpc5200-immr", },
  79. { .compatible = "fsl,lpb", },
  80. /* depreciated matches; shouldn't be used in new device trees */
  81. { .type = "builtin", .compatible = "mpc5200", }, /* efika */
  82. { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
  83. {},
  84. };
  85. void __init
  86. mpc52xx_declare_of_platform_devices(void)
  87. {
  88. /* Find every child of the SOC node and add it to of_platform */
  89. if (of_platform_bus_probe(NULL, mpc52xx_bus_ids, NULL))
  90. printk(KERN_ERR __FILE__ ": "
  91. "Error while probing of_platform bus\n");
  92. }
  93. void __init
  94. mpc52xx_map_wdt(void)
  95. {
  96. const void *has_wdt;
  97. struct device_node *np;
  98. /* mpc52xx_wdt is mapped here and used in mpc52xx_restart,
  99. * possibly from a interrupt context. wdt is only implement
  100. * on a gpt0, so check has-wdt property before mapping.
  101. */
  102. for_each_compatible_node(np, NULL, "fsl,mpc5200-gpt") {
  103. has_wdt = of_get_property(np, "fsl,has-wdt", NULL);
  104. if (has_wdt) {
  105. mpc52xx_wdt = of_iomap(np, 0);
  106. of_node_put(np);
  107. return;
  108. }
  109. }
  110. for_each_compatible_node(np, NULL, "mpc5200-gpt") {
  111. has_wdt = of_get_property(np, "has-wdt", NULL);
  112. if (has_wdt) {
  113. mpc52xx_wdt = of_iomap(np, 0);
  114. of_node_put(np);
  115. return;
  116. }
  117. }
  118. }
  119. void
  120. mpc52xx_restart(char *cmd)
  121. {
  122. local_irq_disable();
  123. /* Turn on the watchdog and wait for it to expire.
  124. * It effectively does a reset. */
  125. if (mpc52xx_wdt) {
  126. out_be32(&mpc52xx_wdt->mode, 0x00000000);
  127. out_be32(&mpc52xx_wdt->count, 0x000000ff);
  128. out_be32(&mpc52xx_wdt->mode, 0x00009004);
  129. } else
  130. printk("mpc52xx_restart: Can't access wdt. "
  131. "Restart impossible, system halted.\n");
  132. while (1);
  133. }