cfe.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
  4. */
  5. #include <linux/init.h>
  6. #include <linux/kernel.h>
  7. #include <linux/linkage.h>
  8. #include <linux/mm.h>
  9. #include <linux/memblock.h>
  10. #include <linux/pm.h>
  11. #include <linux/smp.h>
  12. #include <asm/bootinfo.h>
  13. #include <asm/reboot.h>
  14. #include <asm/setup.h>
  15. #include <asm/sibyte/board.h>
  16. #include <asm/smp-ops.h>
  17. #include <asm/fw/cfe/cfe_api.h>
  18. #include <asm/fw/cfe/cfe_error.h>
  19. /* Max ram addressable in 32-bit segments */
  20. #ifdef CONFIG_64BIT
  21. #define MAX_RAM_SIZE (~0ULL)
  22. #else
  23. #ifdef CONFIG_HIGHMEM
  24. #ifdef CONFIG_PHYS_ADDR_T_64BIT
  25. #define MAX_RAM_SIZE (~0ULL)
  26. #else
  27. #define MAX_RAM_SIZE (0xffffffffULL)
  28. #endif
  29. #else
  30. #define MAX_RAM_SIZE (0x1fffffffULL)
  31. #endif
  32. #endif
  33. #define SIBYTE_MAX_MEM_REGIONS 8
  34. phys_addr_t board_mem_region_addrs[SIBYTE_MAX_MEM_REGIONS];
  35. phys_addr_t board_mem_region_sizes[SIBYTE_MAX_MEM_REGIONS];
  36. unsigned int board_mem_region_count;
  37. int cfe_cons_handle;
  38. #ifdef CONFIG_BLK_DEV_INITRD
  39. extern unsigned long initrd_start, initrd_end;
  40. #endif
  41. static void __noreturn cfe_linux_exit(void *arg)
  42. {
  43. int warm = *(int *)arg;
  44. if (smp_processor_id()) {
  45. static int reboot_smp;
  46. /* Don't repeat the process from another CPU */
  47. if (!reboot_smp) {
  48. /* Get CPU 0 to do the cfe_exit */
  49. reboot_smp = 1;
  50. smp_call_function(cfe_linux_exit, arg, 0);
  51. }
  52. } else {
  53. printk("Passing control back to CFE...\n");
  54. cfe_exit(warm, 0);
  55. printk("cfe_exit returned??\n");
  56. }
  57. while (1);
  58. }
  59. static void __noreturn cfe_linux_restart(char *command)
  60. {
  61. static const int zero;
  62. cfe_linux_exit((void *)&zero);
  63. }
  64. static void __noreturn cfe_linux_halt(void)
  65. {
  66. static const int one = 1;
  67. cfe_linux_exit((void *)&one);
  68. }
  69. static __init void prom_meminit(void)
  70. {
  71. u64 addr, size, type; /* regardless of PHYS_ADDR_T_64BIT */
  72. int mem_flags = 0;
  73. unsigned int idx;
  74. int rd_flag;
  75. #ifdef CONFIG_BLK_DEV_INITRD
  76. unsigned long initrd_pstart;
  77. unsigned long initrd_pend;
  78. initrd_pstart = CPHYSADDR(initrd_start);
  79. initrd_pend = CPHYSADDR(initrd_end);
  80. if (initrd_start &&
  81. ((initrd_pstart > MAX_RAM_SIZE)
  82. || (initrd_pend > MAX_RAM_SIZE))) {
  83. panic("initrd out of addressable memory");
  84. }
  85. #endif /* INITRD */
  86. for (idx = 0; cfe_enummem(idx, mem_flags, &addr, &size, &type) != CFE_ERR_NOMORE;
  87. idx++) {
  88. rd_flag = 0;
  89. if (type == CFE_MI_AVAILABLE) {
  90. /*
  91. * See if this block contains (any portion of) the
  92. * ramdisk
  93. */
  94. #ifdef CONFIG_BLK_DEV_INITRD
  95. if (initrd_start) {
  96. if ((initrd_pstart > addr) &&
  97. (initrd_pstart < (addr + size))) {
  98. memblock_add(addr,
  99. initrd_pstart - addr);
  100. rd_flag = 1;
  101. }
  102. if ((initrd_pend > addr) &&
  103. (initrd_pend < (addr + size))) {
  104. memblock_add(initrd_pend,
  105. (addr + size) - initrd_pend);
  106. rd_flag = 1;
  107. }
  108. }
  109. #endif
  110. if (!rd_flag) {
  111. if (addr > MAX_RAM_SIZE)
  112. continue;
  113. if (addr+size > MAX_RAM_SIZE)
  114. size = MAX_RAM_SIZE - (addr+size) + 1;
  115. /*
  116. * memcpy/__copy_user prefetch, which
  117. * will cause a bus error for
  118. * KSEG/KUSEG addrs not backed by RAM.
  119. * Hence, reserve some padding for the
  120. * prefetch distance.
  121. */
  122. if (size > 512)
  123. size -= 512;
  124. memblock_add(addr, size);
  125. }
  126. board_mem_region_addrs[board_mem_region_count] = addr;
  127. board_mem_region_sizes[board_mem_region_count] = size;
  128. board_mem_region_count++;
  129. if (board_mem_region_count ==
  130. SIBYTE_MAX_MEM_REGIONS) {
  131. /*
  132. * Too many regions. Need to configure more
  133. */
  134. while(1);
  135. }
  136. }
  137. }
  138. #ifdef CONFIG_BLK_DEV_INITRD
  139. if (initrd_start) {
  140. memblock_add(initrd_pstart, initrd_pend - initrd_pstart);
  141. memblock_reserve(initrd_pstart, initrd_pend - initrd_pstart);
  142. }
  143. #endif
  144. }
  145. #ifdef CONFIG_BLK_DEV_INITRD
  146. static int __init initrd_setup(char *str)
  147. {
  148. char rdarg[64];
  149. int idx;
  150. char *tmp, *endptr;
  151. unsigned long initrd_size;
  152. /* Make a copy of the initrd argument so we can smash it up here */
  153. for (idx = 0; idx < sizeof(rdarg)-1; idx++) {
  154. if (!str[idx] || (str[idx] == ' ')) break;
  155. rdarg[idx] = str[idx];
  156. }
  157. rdarg[idx] = 0;
  158. str = rdarg;
  159. /*
  160. *Initrd location comes in the form "<hex size of ramdisk in bytes>@<location in memory>"
  161. * e.g. initrd=3abfd@80010000. This is set up by the loader.
  162. */
  163. for (tmp = str; *tmp != '@'; tmp++) {
  164. if (!*tmp) {
  165. goto fail;
  166. }
  167. }
  168. *tmp = 0;
  169. tmp++;
  170. if (!*tmp) {
  171. goto fail;
  172. }
  173. initrd_size = simple_strtoul(str, &endptr, 16);
  174. if (*endptr) {
  175. *(tmp-1) = '@';
  176. goto fail;
  177. }
  178. *(tmp-1) = '@';
  179. initrd_start = simple_strtoul(tmp, &endptr, 16);
  180. if (*endptr) {
  181. goto fail;
  182. }
  183. initrd_end = initrd_start + initrd_size;
  184. printk("Found initrd of %lx@%lx\n", initrd_size, initrd_start);
  185. return 1;
  186. fail:
  187. printk("Bad initrd argument. Disabling initrd\n");
  188. initrd_start = 0;
  189. initrd_end = 0;
  190. return 1;
  191. }
  192. #endif
  193. extern const struct plat_smp_ops sb_smp_ops;
  194. extern const struct plat_smp_ops bcm1480_smp_ops;
  195. /*
  196. * prom_init is called just after the cpu type is determined, from setup_arch()
  197. */
  198. void __init prom_init(void)
  199. {
  200. uint64_t cfe_ept, cfe_handle;
  201. unsigned int cfe_eptseal;
  202. int argc = fw_arg0;
  203. char **envp = (char **) fw_arg2;
  204. int *prom_vec = (int *) fw_arg3;
  205. _machine_restart = cfe_linux_restart;
  206. _machine_halt = cfe_linux_halt;
  207. pm_power_off = cfe_linux_halt;
  208. /*
  209. * Check if a loader was used; if NOT, the 4 arguments are
  210. * what CFE gives us (handle, 0, EPT and EPTSEAL)
  211. */
  212. if (argc < 0) {
  213. cfe_handle = (uint64_t)(long)argc;
  214. cfe_ept = (long)envp;
  215. cfe_eptseal = (uint32_t)(unsigned long)prom_vec;
  216. } else {
  217. if ((int32_t)(long)prom_vec < 0) {
  218. /*
  219. * Old loader; all it gives us is the handle,
  220. * so use the "known" entrypoint and assume
  221. * the seal.
  222. */
  223. cfe_handle = (uint64_t)(long)prom_vec;
  224. cfe_ept = (uint64_t)((int32_t)0x9fc00500);
  225. cfe_eptseal = CFE_EPTSEAL;
  226. } else {
  227. /*
  228. * Newer loaders bundle the handle/ept/eptseal
  229. * Note: prom_vec is in the loader's useg
  230. * which is still alive in the TLB.
  231. */
  232. cfe_handle = (uint64_t)((int32_t *)prom_vec)[0];
  233. cfe_ept = (uint64_t)((int32_t *)prom_vec)[2];
  234. cfe_eptseal = (unsigned int)((uint32_t *)prom_vec)[3];
  235. }
  236. }
  237. if (cfe_eptseal != CFE_EPTSEAL) {
  238. /* too early for panic to do any good */
  239. printk("CFE's entrypoint seal doesn't match. Spinning.");
  240. while (1) ;
  241. }
  242. cfe_init(cfe_handle, cfe_ept);
  243. /*
  244. * Get the handle for (at least) prom_putchar, possibly for
  245. * boot console
  246. */
  247. cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
  248. if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, COMMAND_LINE_SIZE) < 0) {
  249. if (argc >= 0) {
  250. /* The loader should have set the command line */
  251. /* too early for panic to do any good */
  252. printk("LINUX_CMDLINE not defined in cfe.");
  253. while (1) ;
  254. }
  255. }
  256. #ifdef CONFIG_BLK_DEV_INITRD
  257. {
  258. char *ptr;
  259. /* Need to find out early whether we've got an initrd. So scan
  260. the list looking now */
  261. for (ptr = arcs_cmdline; *ptr; ptr++) {
  262. while (*ptr == ' ') {
  263. ptr++;
  264. }
  265. if (!strncmp(ptr, "initrd=", 7)) {
  266. initrd_setup(ptr+7);
  267. break;
  268. } else {
  269. while (*ptr && (*ptr != ' ')) {
  270. ptr++;
  271. }
  272. }
  273. }
  274. }
  275. #endif /* CONFIG_BLK_DEV_INITRD */
  276. /* Not sure this is needed, but it's the safe way. */
  277. arcs_cmdline[COMMAND_LINE_SIZE-1] = 0;
  278. prom_meminit();
  279. #if defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250)
  280. register_smp_ops(&sb_smp_ops);
  281. #endif
  282. #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
  283. register_smp_ops(&bcm1480_smp_ops);
  284. #endif
  285. }
  286. void prom_putchar(char c)
  287. {
  288. int ret;
  289. while ((ret = cfe_write(cfe_cons_handle, &c, 1)) == 0)
  290. ;
  291. }