mvme5100.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Board setup routines for the Motorola/Emerson MVME5100.
  4. *
  5. * Copyright 2013 CSC Australia Pty. Ltd.
  6. *
  7. * Based on earlier code by:
  8. *
  9. * Matt Porter, MontaVista Software Inc.
  10. * Copyright 2001 MontaVista Software Inc.
  11. *
  12. * Author: Stephen Chivers <[email protected]>
  13. */
  14. #include <linux/of_irq.h>
  15. #include <linux/of_platform.h>
  16. #include <asm/i8259.h>
  17. #include <asm/pci-bridge.h>
  18. #include <asm/mpic.h>
  19. #include <mm/mmu_decl.h>
  20. #include <asm/udbg.h>
  21. #define HAWK_MPIC_SIZE 0x00040000U
  22. #define MVME5100_PCI_MEM_OFFSET 0x00000000
  23. /* Board register addresses. */
  24. #define BOARD_STATUS_REG 0xfef88080
  25. #define BOARD_MODFAIL_REG 0xfef88090
  26. #define BOARD_MODRST_REG 0xfef880a0
  27. #define BOARD_TBEN_REG 0xfef880c0
  28. #define BOARD_SW_READ_REG 0xfef880e0
  29. #define BOARD_GEO_ADDR_REG 0xfef880e8
  30. #define BOARD_EXT_FEATURE1_REG 0xfef880f0
  31. #define BOARD_EXT_FEATURE2_REG 0xfef88100
  32. static phys_addr_t pci_membase;
  33. static u_char *restart;
  34. static void mvme5100_8259_cascade(struct irq_desc *desc)
  35. {
  36. struct irq_chip *chip = irq_desc_get_chip(desc);
  37. unsigned int cascade_irq = i8259_irq();
  38. if (cascade_irq)
  39. generic_handle_irq(cascade_irq);
  40. chip->irq_eoi(&desc->irq_data);
  41. }
  42. static void __init mvme5100_pic_init(void)
  43. {
  44. struct mpic *mpic;
  45. struct device_node *np;
  46. struct device_node *cp = NULL;
  47. unsigned int cirq;
  48. unsigned long intack = 0;
  49. const u32 *prop = NULL;
  50. np = of_find_node_by_type(NULL, "open-pic");
  51. if (!np) {
  52. pr_err("Could not find open-pic node\n");
  53. return;
  54. }
  55. mpic = mpic_alloc(np, pci_membase, 0, 16, 256, " OpenPIC ");
  56. BUG_ON(mpic == NULL);
  57. of_node_put(np);
  58. mpic_assign_isu(mpic, 0, pci_membase + 0x10000);
  59. mpic_init(mpic);
  60. cp = of_find_compatible_node(NULL, NULL, "chrp,iic");
  61. if (cp == NULL) {
  62. pr_warn("mvme5100_pic_init: couldn't find i8259\n");
  63. return;
  64. }
  65. cirq = irq_of_parse_and_map(cp, 0);
  66. if (!cirq) {
  67. pr_warn("mvme5100_pic_init: no cascade interrupt?\n");
  68. return;
  69. }
  70. np = of_find_compatible_node(NULL, "pci", "mpc10x-pci");
  71. if (np) {
  72. prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
  73. if (prop)
  74. intack = prop[0];
  75. of_node_put(np);
  76. }
  77. if (intack)
  78. pr_debug("mvme5100_pic_init: PCI 8259 intack at 0x%016lx\n",
  79. intack);
  80. i8259_init(cp, intack);
  81. of_node_put(cp);
  82. irq_set_chained_handler(cirq, mvme5100_8259_cascade);
  83. }
  84. static int __init mvme5100_add_bridge(struct device_node *dev)
  85. {
  86. const int *bus_range;
  87. int len;
  88. struct pci_controller *hose;
  89. unsigned short devid;
  90. pr_info("Adding PCI host bridge %pOF\n", dev);
  91. bus_range = of_get_property(dev, "bus-range", &len);
  92. hose = pcibios_alloc_controller(dev);
  93. if (hose == NULL)
  94. return -ENOMEM;
  95. hose->first_busno = bus_range ? bus_range[0] : 0;
  96. hose->last_busno = bus_range ? bus_range[1] : 0xff;
  97. setup_indirect_pci(hose, 0xfe000cf8, 0xfe000cfc, 0);
  98. pci_process_bridge_OF_ranges(hose, dev, 1);
  99. early_read_config_word(hose, 0, 0, PCI_DEVICE_ID, &devid);
  100. if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK) {
  101. pr_err("HAWK PHB not present?\n");
  102. return 0;
  103. }
  104. early_read_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
  105. if (pci_membase == 0) {
  106. pr_err("HAWK PHB mibar not correctly set?\n");
  107. return 0;
  108. }
  109. pr_info("mvme5100_pic_init: pci_membase: %x\n", pci_membase);
  110. return 0;
  111. }
  112. static const struct of_device_id mvme5100_of_bus_ids[] __initconst = {
  113. { .compatible = "hawk-bridge", },
  114. {},
  115. };
  116. /*
  117. * Setup the architecture
  118. */
  119. static void __init mvme5100_setup_arch(void)
  120. {
  121. if (ppc_md.progress)
  122. ppc_md.progress("mvme5100_setup_arch()", 0);
  123. restart = ioremap(BOARD_MODRST_REG, 4);
  124. }
  125. static void __init mvme5100_setup_pci(void)
  126. {
  127. struct device_node *np;
  128. for_each_compatible_node(np, "pci", "hawk-pci")
  129. mvme5100_add_bridge(np);
  130. }
  131. static void mvme5100_show_cpuinfo(struct seq_file *m)
  132. {
  133. seq_puts(m, "Vendor\t\t: Motorola/Emerson\n");
  134. seq_puts(m, "Machine\t\t: MVME5100\n");
  135. }
  136. static void __noreturn mvme5100_restart(char *cmd)
  137. {
  138. local_irq_disable();
  139. mtmsr(mfmsr() | MSR_IP);
  140. out_8((u_char *) restart, 0x01);
  141. while (1)
  142. ;
  143. }
  144. /*
  145. * Called very early, device-tree isn't unflattened
  146. */
  147. static int __init mvme5100_probe(void)
  148. {
  149. return of_machine_is_compatible("MVME5100");
  150. }
  151. static int __init probe_of_platform_devices(void)
  152. {
  153. of_platform_bus_probe(NULL, mvme5100_of_bus_ids, NULL);
  154. return 0;
  155. }
  156. machine_device_initcall(mvme5100, probe_of_platform_devices);
  157. define_machine(mvme5100) {
  158. .name = "MVME5100",
  159. .probe = mvme5100_probe,
  160. .setup_arch = mvme5100_setup_arch,
  161. .discover_phbs = mvme5100_setup_pci,
  162. .init_IRQ = mvme5100_pic_init,
  163. .show_cpuinfo = mvme5100_show_cpuinfo,
  164. .get_irq = mpic_get_irq,
  165. .restart = mvme5100_restart,
  166. .calibrate_decr = generic_calibrate_decr,
  167. .progress = udbg_progress,
  168. };