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