integrator_ap.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * linux/arch/arm/mach-integrator/integrator_ap.c
  4. *
  5. * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/init.h>
  9. #include <linux/syscore_ops.h>
  10. #include <linux/amba/bus.h>
  11. #include <linux/io.h>
  12. #include <linux/irqchip.h>
  13. #include <linux/of_irq.h>
  14. #include <linux/of_address.h>
  15. #include <linux/of_platform.h>
  16. #include <linux/termios.h>
  17. #include <linux/mfd/syscon.h>
  18. #include <linux/regmap.h>
  19. #include <asm/mach/arch.h>
  20. #include <asm/mach/map.h>
  21. #include "hardware.h"
  22. #include "cm.h"
  23. #include "common.h"
  24. /* Regmap to the AP system controller */
  25. static struct regmap *ap_syscon_map;
  26. /*
  27. * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
  28. * is the (PA >> 12).
  29. *
  30. * Setup a VA for the Integrator interrupt controller (for header #0,
  31. * just for now).
  32. */
  33. #define VA_IC_BASE __io_address(INTEGRATOR_IC_BASE)
  34. /*
  35. * Logical Physical
  36. * f1400000 14000000 Interrupt controller
  37. * f1600000 16000000 UART 0
  38. */
  39. static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
  40. {
  41. .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
  42. .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
  43. .length = SZ_4K,
  44. .type = MT_DEVICE
  45. }, {
  46. .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
  47. .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
  48. .length = SZ_4K,
  49. .type = MT_DEVICE
  50. }
  51. };
  52. static void __init ap_map_io(void)
  53. {
  54. iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
  55. }
  56. #ifdef CONFIG_PM
  57. static unsigned long ic_irq_enable;
  58. static int irq_suspend(void)
  59. {
  60. ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
  61. return 0;
  62. }
  63. static void irq_resume(void)
  64. {
  65. /* disable all irq sources */
  66. cm_clear_irqs();
  67. writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
  68. writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
  69. writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
  70. }
  71. #else
  72. #define irq_suspend NULL
  73. #define irq_resume NULL
  74. #endif
  75. static struct syscore_ops irq_syscore_ops = {
  76. .suspend = irq_suspend,
  77. .resume = irq_resume,
  78. };
  79. static int __init irq_syscore_init(void)
  80. {
  81. register_syscore_ops(&irq_syscore_ops);
  82. return 0;
  83. }
  84. device_initcall(irq_syscore_init);
  85. /*
  86. * For the PL010 found in the Integrator/AP some of the UART control is
  87. * implemented in the system controller and accessed using a callback
  88. * from the driver.
  89. */
  90. static void integrator_uart_set_mctrl(struct amba_device *dev,
  91. void __iomem *base, unsigned int mctrl)
  92. {
  93. unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
  94. u32 phybase = dev->res.start;
  95. int ret;
  96. if (phybase == INTEGRATOR_UART0_BASE) {
  97. /* UART0 */
  98. rts_mask = 1 << 4;
  99. dtr_mask = 1 << 5;
  100. } else {
  101. /* UART1 */
  102. rts_mask = 1 << 6;
  103. dtr_mask = 1 << 7;
  104. }
  105. if (mctrl & TIOCM_RTS)
  106. ctrlc |= rts_mask;
  107. else
  108. ctrls |= rts_mask;
  109. if (mctrl & TIOCM_DTR)
  110. ctrlc |= dtr_mask;
  111. else
  112. ctrls |= dtr_mask;
  113. ret = regmap_write(ap_syscon_map,
  114. INTEGRATOR_SC_CTRLS_OFFSET,
  115. ctrls);
  116. if (ret)
  117. pr_err("MODEM: unable to write PL010 UART CTRLS\n");
  118. ret = regmap_write(ap_syscon_map,
  119. INTEGRATOR_SC_CTRLC_OFFSET,
  120. ctrlc);
  121. if (ret)
  122. pr_err("MODEM: unable to write PL010 UART CRTLC\n");
  123. }
  124. struct amba_pl010_data ap_uart_data = {
  125. .set_mctrl = integrator_uart_set_mctrl,
  126. };
  127. void __init ap_init_early(void)
  128. {
  129. }
  130. static void __init ap_init_irq_of(void)
  131. {
  132. cm_init();
  133. irqchip_init();
  134. }
  135. /* For the Device Tree, add in the UART callbacks as AUXDATA */
  136. static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
  137. OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
  138. "uart0", &ap_uart_data),
  139. OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
  140. "uart1", &ap_uart_data),
  141. { /* sentinel */ },
  142. };
  143. static const struct of_device_id ap_syscon_match[] = {
  144. { .compatible = "arm,integrator-ap-syscon"},
  145. { },
  146. };
  147. static void __init ap_init_of(void)
  148. {
  149. struct device_node *syscon;
  150. of_platform_default_populate(NULL, ap_auxdata_lookup, NULL);
  151. syscon = of_find_matching_node(NULL, ap_syscon_match);
  152. if (!syscon)
  153. return;
  154. ap_syscon_map = syscon_node_to_regmap(syscon);
  155. if (IS_ERR(ap_syscon_map)) {
  156. pr_crit("could not find Integrator/AP system controller\n");
  157. return;
  158. }
  159. }
  160. static const char * ap_dt_board_compat[] = {
  161. "arm,integrator-ap",
  162. NULL,
  163. };
  164. DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
  165. .reserve = integrator_reserve,
  166. .map_io = ap_map_io,
  167. .init_early = ap_init_early,
  168. .init_irq = ap_init_irq_of,
  169. .init_machine = ap_init_of,
  170. .dt_compat = ap_dt_board_compat,
  171. MACHINE_END