cpu.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2014 - 2015 Xilinx, Inc.
  4. * Michal Simek <michal.simek@xilinx.com>
  5. */
  6. #include <common.h>
  7. #include <init.h>
  8. #include <time.h>
  9. #include <asm/arch/hardware.h>
  10. #include <asm/arch/sys_proto.h>
  11. #include <asm/armv8/mmu.h>
  12. #include <asm/cache.h>
  13. #include <asm/global_data.h>
  14. #include <asm/io.h>
  15. #include <zynqmp_firmware.h>
  16. #include <asm/cache.h>
  17. #include <dm/platdata.h>
  18. #define ZYNQ_SILICON_VER_MASK 0xF000
  19. #define ZYNQ_SILICON_VER_SHIFT 12
  20. DECLARE_GLOBAL_DATA_PTR;
  21. /*
  22. * Number of filled static entries and also the first empty
  23. * slot in zynqmp_mem_map.
  24. */
  25. #define ZYNQMP_MEM_MAP_USED 4
  26. #if !defined(CONFIG_ZYNQMP_NO_DDR)
  27. #define DRAM_BANKS CONFIG_NR_DRAM_BANKS
  28. #else
  29. #define DRAM_BANKS 0
  30. #endif
  31. #if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
  32. #define TCM_MAP 1
  33. #else
  34. #define TCM_MAP 0
  35. #endif
  36. /* +1 is end of list which needs to be empty */
  37. #define ZYNQMP_MEM_MAP_MAX (ZYNQMP_MEM_MAP_USED + DRAM_BANKS + TCM_MAP + 1)
  38. static struct mm_region zynqmp_mem_map[ZYNQMP_MEM_MAP_MAX] = {
  39. {
  40. .virt = 0x80000000UL,
  41. .phys = 0x80000000UL,
  42. .size = 0x70000000UL,
  43. .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
  44. PTE_BLOCK_NON_SHARE |
  45. PTE_BLOCK_PXN | PTE_BLOCK_UXN
  46. }, {
  47. .virt = 0xf8000000UL,
  48. .phys = 0xf8000000UL,
  49. .size = 0x07e00000UL,
  50. .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
  51. PTE_BLOCK_NON_SHARE |
  52. PTE_BLOCK_PXN | PTE_BLOCK_UXN
  53. }, {
  54. .virt = 0x400000000UL,
  55. .phys = 0x400000000UL,
  56. .size = 0x400000000UL,
  57. .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
  58. PTE_BLOCK_NON_SHARE |
  59. PTE_BLOCK_PXN | PTE_BLOCK_UXN
  60. }, {
  61. .virt = 0x1000000000UL,
  62. .phys = 0x1000000000UL,
  63. .size = 0xf000000000UL,
  64. .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
  65. PTE_BLOCK_NON_SHARE |
  66. PTE_BLOCK_PXN | PTE_BLOCK_UXN
  67. }
  68. };
  69. void mem_map_fill(void)
  70. {
  71. int banks = ZYNQMP_MEM_MAP_USED;
  72. #if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
  73. zynqmp_mem_map[banks].virt = 0xffe00000UL;
  74. zynqmp_mem_map[banks].phys = 0xffe00000UL;
  75. zynqmp_mem_map[banks].size = 0x00200000UL;
  76. zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
  77. PTE_BLOCK_INNER_SHARE;
  78. banks = banks + 1;
  79. #endif
  80. #if !defined(CONFIG_ZYNQMP_NO_DDR)
  81. for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
  82. /* Zero size means no more DDR that's this is end */
  83. if (!gd->bd->bi_dram[i].size)
  84. break;
  85. zynqmp_mem_map[banks].virt = gd->bd->bi_dram[i].start;
  86. zynqmp_mem_map[banks].phys = gd->bd->bi_dram[i].start;
  87. zynqmp_mem_map[banks].size = gd->bd->bi_dram[i].size;
  88. zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
  89. PTE_BLOCK_INNER_SHARE;
  90. banks = banks + 1;
  91. }
  92. #endif
  93. }
  94. struct mm_region *mem_map = zynqmp_mem_map;
  95. u64 get_page_table_size(void)
  96. {
  97. return 0x14000;
  98. }
  99. #if defined(CONFIG_SYS_MEM_RSVD_FOR_MMU) || defined(CONFIG_DEFINE_TCM_OCM_MMAP)
  100. void tcm_init(u8 mode)
  101. {
  102. puts("WARNING: Initializing TCM overwrites TCM content\n");
  103. initialize_tcm(mode);
  104. memset((void *)ZYNQMP_TCM_BASE_ADDR, 0, ZYNQMP_TCM_SIZE);
  105. }
  106. #endif
  107. #ifdef CONFIG_SYS_MEM_RSVD_FOR_MMU
  108. int arm_reserve_mmu(void)
  109. {
  110. tcm_init(TCM_LOCK);
  111. gd->arch.tlb_size = PGTABLE_SIZE;
  112. gd->arch.tlb_addr = ZYNQMP_TCM_BASE_ADDR;
  113. return 0;
  114. }
  115. #endif
  116. static unsigned int zynqmp_get_silicon_version_secure(void)
  117. {
  118. u32 ver;
  119. ver = readl(&csu_base->version);
  120. ver &= ZYNQMP_SILICON_VER_MASK;
  121. ver >>= ZYNQMP_SILICON_VER_SHIFT;
  122. return ver;
  123. }
  124. unsigned int zynqmp_get_silicon_version(void)
  125. {
  126. if (current_el() == 3)
  127. return zynqmp_get_silicon_version_secure();
  128. gd->cpu_clk = get_tbclk();
  129. switch (gd->cpu_clk) {
  130. case 50000000:
  131. return ZYNQMP_CSU_VERSION_QEMU;
  132. }
  133. return ZYNQMP_CSU_VERSION_SILICON;
  134. }
  135. static int zynqmp_mmio_rawwrite(const u32 address,
  136. const u32 mask,
  137. const u32 value)
  138. {
  139. u32 data;
  140. u32 value_local = value;
  141. int ret;
  142. ret = zynqmp_mmio_read(address, &data);
  143. if (ret)
  144. return ret;
  145. data &= ~mask;
  146. value_local &= mask;
  147. value_local |= data;
  148. writel(value_local, (ulong)address);
  149. return 0;
  150. }
  151. static int zynqmp_mmio_rawread(const u32 address, u32 *value)
  152. {
  153. *value = readl((ulong)address);
  154. return 0;
  155. }
  156. int zynqmp_mmio_write(const u32 address,
  157. const u32 mask,
  158. const u32 value)
  159. {
  160. if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3)
  161. return zynqmp_mmio_rawwrite(address, mask, value);
  162. #if defined(CONFIG_ZYNQMP_FIRMWARE)
  163. else
  164. return xilinx_pm_request(PM_MMIO_WRITE, address, mask,
  165. value, 0, NULL);
  166. #endif
  167. return -EINVAL;
  168. }
  169. int zynqmp_mmio_read(const u32 address, u32 *value)
  170. {
  171. u32 ret = -EINVAL;
  172. if (!value)
  173. return ret;
  174. if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
  175. ret = zynqmp_mmio_rawread(address, value);
  176. }
  177. #if defined(CONFIG_ZYNQMP_FIRMWARE)
  178. else {
  179. u32 ret_payload[PAYLOAD_ARG_CNT];
  180. ret = xilinx_pm_request(PM_MMIO_READ, address, 0, 0,
  181. 0, ret_payload);
  182. *value = ret_payload[1];
  183. }
  184. #endif
  185. return ret;
  186. }
  187. U_BOOT_DRVINFO(soc_xilinx_zynqmp) = {
  188. .name = "soc_xilinx_zynqmp",
  189. };