env.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Based on Ocelot Linux port, which is
  4. * Copyright 2001 MontaVista Software Inc.
  5. * Author: [email protected] or [email protected]
  6. *
  7. * Copyright 2003 ICT CAS
  8. * Author: Michael Guo <[email protected]>
  9. *
  10. * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
  11. * Author: Fuxin Zhang, [email protected]
  12. *
  13. * Copyright (C) 2009 Lemote Inc.
  14. * Author: Wu Zhangjin, [email protected]
  15. */
  16. #include <linux/dma-map-ops.h>
  17. #include <linux/export.h>
  18. #include <linux/pci_ids.h>
  19. #include <asm/bootinfo.h>
  20. #include <loongson.h>
  21. #include <boot_param.h>
  22. #include <builtin_dtbs.h>
  23. #include <workarounds.h>
  24. #define HOST_BRIDGE_CONFIG_ADDR ((void __iomem *)TO_UNCAC(0x1a000000))
  25. u32 cpu_clock_freq;
  26. EXPORT_SYMBOL(cpu_clock_freq);
  27. struct efi_memory_map_loongson *loongson_memmap;
  28. struct loongson_system_configuration loongson_sysconf;
  29. struct board_devices *eboard;
  30. struct interface_info *einter;
  31. struct loongson_special_attribute *especial;
  32. u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
  33. u64 loongson_chiptemp[MAX_PACKAGES];
  34. u64 loongson_freqctrl[MAX_PACKAGES];
  35. unsigned long long smp_group[4];
  36. const char *get_system_type(void)
  37. {
  38. return "Generic Loongson64 System";
  39. }
  40. void __init prom_dtb_init_env(void)
  41. {
  42. if ((fw_arg2 < CKSEG0 || fw_arg2 > CKSEG1)
  43. && (fw_arg2 < XKPHYS || fw_arg2 > XKSEG))
  44. loongson_fdt_blob = __dtb_loongson64_2core_2k1000_begin;
  45. else
  46. loongson_fdt_blob = (void *)fw_arg2;
  47. }
  48. void __init prom_lefi_init_env(void)
  49. {
  50. struct boot_params *boot_p;
  51. struct loongson_params *loongson_p;
  52. struct system_loongson *esys;
  53. struct efi_cpuinfo_loongson *ecpu;
  54. struct irq_source_routing_table *eirq_source;
  55. u32 id;
  56. u16 vendor;
  57. /* firmware arguments are initialized in head.S */
  58. boot_p = (struct boot_params *)fw_arg2;
  59. loongson_p = &(boot_p->efi.smbios.lp);
  60. esys = (struct system_loongson *)
  61. ((u64)loongson_p + loongson_p->system_offset);
  62. ecpu = (struct efi_cpuinfo_loongson *)
  63. ((u64)loongson_p + loongson_p->cpu_offset);
  64. eboard = (struct board_devices *)
  65. ((u64)loongson_p + loongson_p->boarddev_table_offset);
  66. einter = (struct interface_info *)
  67. ((u64)loongson_p + loongson_p->interface_offset);
  68. especial = (struct loongson_special_attribute *)
  69. ((u64)loongson_p + loongson_p->special_offset);
  70. eirq_source = (struct irq_source_routing_table *)
  71. ((u64)loongson_p + loongson_p->irq_offset);
  72. loongson_memmap = (struct efi_memory_map_loongson *)
  73. ((u64)loongson_p + loongson_p->memory_offset);
  74. cpu_clock_freq = ecpu->cpu_clock_freq;
  75. loongson_sysconf.cputype = ecpu->cputype;
  76. switch (ecpu->cputype) {
  77. case Legacy_3A:
  78. case Loongson_3A:
  79. loongson_sysconf.cores_per_node = 4;
  80. loongson_sysconf.cores_per_package = 4;
  81. smp_group[0] = 0x900000003ff01000;
  82. smp_group[1] = 0x900010003ff01000;
  83. smp_group[2] = 0x900020003ff01000;
  84. smp_group[3] = 0x900030003ff01000;
  85. loongson_chipcfg[0] = 0x900000001fe00180;
  86. loongson_chipcfg[1] = 0x900010001fe00180;
  87. loongson_chipcfg[2] = 0x900020001fe00180;
  88. loongson_chipcfg[3] = 0x900030001fe00180;
  89. loongson_chiptemp[0] = 0x900000001fe0019c;
  90. loongson_chiptemp[1] = 0x900010001fe0019c;
  91. loongson_chiptemp[2] = 0x900020001fe0019c;
  92. loongson_chiptemp[3] = 0x900030001fe0019c;
  93. loongson_freqctrl[0] = 0x900000001fe001d0;
  94. loongson_freqctrl[1] = 0x900010001fe001d0;
  95. loongson_freqctrl[2] = 0x900020001fe001d0;
  96. loongson_freqctrl[3] = 0x900030001fe001d0;
  97. loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
  98. break;
  99. case Legacy_3B:
  100. case Loongson_3B:
  101. loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
  102. loongson_sysconf.cores_per_package = 8;
  103. smp_group[0] = 0x900000003ff01000;
  104. smp_group[1] = 0x900010003ff05000;
  105. smp_group[2] = 0x900020003ff09000;
  106. smp_group[3] = 0x900030003ff0d000;
  107. loongson_chipcfg[0] = 0x900000001fe00180;
  108. loongson_chipcfg[1] = 0x900020001fe00180;
  109. loongson_chipcfg[2] = 0x900040001fe00180;
  110. loongson_chipcfg[3] = 0x900060001fe00180;
  111. loongson_chiptemp[0] = 0x900000001fe0019c;
  112. loongson_chiptemp[1] = 0x900020001fe0019c;
  113. loongson_chiptemp[2] = 0x900040001fe0019c;
  114. loongson_chiptemp[3] = 0x900060001fe0019c;
  115. loongson_freqctrl[0] = 0x900000001fe001d0;
  116. loongson_freqctrl[1] = 0x900020001fe001d0;
  117. loongson_freqctrl[2] = 0x900040001fe001d0;
  118. loongson_freqctrl[3] = 0x900060001fe001d0;
  119. loongson_sysconf.workarounds = WORKAROUND_CPUHOTPLUG;
  120. break;
  121. default:
  122. loongson_sysconf.cores_per_node = 1;
  123. loongson_sysconf.cores_per_package = 1;
  124. loongson_chipcfg[0] = 0x900000001fe00180;
  125. }
  126. loongson_sysconf.nr_cpus = ecpu->nr_cpus;
  127. loongson_sysconf.boot_cpu_id = ecpu->cpu_startup_core_id;
  128. loongson_sysconf.reserved_cpus_mask = ecpu->reserved_cores_mask;
  129. if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
  130. loongson_sysconf.nr_cpus = NR_CPUS;
  131. loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
  132. loongson_sysconf.cores_per_node - 1) /
  133. loongson_sysconf.cores_per_node;
  134. loongson_sysconf.dma_mask_bits = eirq_source->dma_mask_bits;
  135. if (loongson_sysconf.dma_mask_bits < 32 ||
  136. loongson_sysconf.dma_mask_bits > 64) {
  137. loongson_sysconf.dma_mask_bits = 32;
  138. dma_default_coherent = true;
  139. } else {
  140. dma_default_coherent = !eirq_source->dma_noncoherent;
  141. }
  142. pr_info("Firmware: Coherent DMA: %s\n", dma_default_coherent ? "on" : "off");
  143. loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
  144. loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
  145. loongson_sysconf.suspend_addr = boot_p->reset_system.DoSuspend;
  146. loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
  147. pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
  148. loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
  149. loongson_sysconf.vgabios_addr);
  150. loongson_sysconf.workarounds |= esys->workarounds;
  151. pr_info("CpuClock = %u\n", cpu_clock_freq);
  152. /* Read the ID of PCI host bridge to detect bridge type */
  153. id = readl(HOST_BRIDGE_CONFIG_ADDR);
  154. vendor = id & 0xffff;
  155. switch (vendor) {
  156. case PCI_VENDOR_ID_LOONGSON:
  157. pr_info("The bridge chip is LS7A\n");
  158. loongson_sysconf.bridgetype = LS7A;
  159. loongson_sysconf.early_config = ls7a_early_config;
  160. break;
  161. case PCI_VENDOR_ID_AMD:
  162. case PCI_VENDOR_ID_ATI:
  163. pr_info("The bridge chip is RS780E or SR5690\n");
  164. loongson_sysconf.bridgetype = RS780E;
  165. loongson_sysconf.early_config = rs780e_early_config;
  166. break;
  167. default:
  168. pr_info("The bridge chip is VIRTUAL\n");
  169. loongson_sysconf.bridgetype = VIRTUAL;
  170. loongson_sysconf.early_config = virtual_early_config;
  171. loongson_fdt_blob = __dtb_loongson64v_4core_virtio_begin;
  172. break;
  173. }
  174. if ((read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64C) {
  175. switch (read_c0_prid() & PRID_REV_MASK) {
  176. case PRID_REV_LOONGSON3A_R1:
  177. case PRID_REV_LOONGSON3A_R2_0:
  178. case PRID_REV_LOONGSON3A_R2_1:
  179. case PRID_REV_LOONGSON3A_R3_0:
  180. case PRID_REV_LOONGSON3A_R3_1:
  181. switch (loongson_sysconf.bridgetype) {
  182. case LS7A:
  183. loongson_fdt_blob = __dtb_loongson64c_4core_ls7a_begin;
  184. break;
  185. case RS780E:
  186. loongson_fdt_blob = __dtb_loongson64c_4core_rs780e_begin;
  187. break;
  188. default:
  189. break;
  190. }
  191. break;
  192. case PRID_REV_LOONGSON3B_R1:
  193. case PRID_REV_LOONGSON3B_R2:
  194. if (loongson_sysconf.bridgetype == RS780E)
  195. loongson_fdt_blob = __dtb_loongson64c_8core_rs780e_begin;
  196. break;
  197. default:
  198. break;
  199. }
  200. } else if ((read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64G) {
  201. if (loongson_sysconf.bridgetype == LS7A)
  202. loongson_fdt_blob = __dtb_loongson64g_4core_ls7a_begin;
  203. }
  204. if (!loongson_fdt_blob)
  205. pr_err("Failed to determine built-in Loongson64 dtb\n");
  206. }