Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2020 Western Digital Corporation or its affiliates.
^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/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/libfdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <asm/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "efistub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * RISC-V requires the kernel image to placed 2 MB aligned base for 64 bit and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * 4MB for 32 bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define MIN_KIMG_ALIGN		SZ_2M
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define MIN_KIMG_ALIGN		SZ_4M
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) static u32 hartid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static int get_boot_hartid_from_fdt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	const void *fdt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	int chosen_node, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	const fdt32_t *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	fdt = get_efi_config_table(DEVICE_TREE_GUID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	if (!fdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	chosen_node = fdt_path_offset(fdt, "/chosen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	if (chosen_node < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	if (!prop || len != sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	hartid = fdt32_to_cpu(*prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) efi_status_t check_platform_features(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	ret = get_boot_hartid_from_fdt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		efi_err("/chosen/boot-hartid missing or invalid!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		return EFI_UNSUPPORTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	return EFI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 				 unsigned long fdt_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	unsigned long stext_offset = _start_kernel - _start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	unsigned long kernel_entry = entrypoint + stext_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	jump_kernel_func jump_kernel = (jump_kernel_func)kernel_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	 * Jump to real kernel here with following constraints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	 * 1. MMU should be disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	 * 2. a0 should contain hartid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	 * 3. a1 should DT address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	csr_write(CSR_SATP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	jump_kernel(hartid, fdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) efi_status_t handle_kernel_image(unsigned long *image_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 				 unsigned long *image_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 				 unsigned long *reserve_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 				 unsigned long *reserve_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 				 efi_loaded_image_t *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	unsigned long kernel_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	unsigned long preferred_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	kernel_size = _edata - _start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	*image_addr = (unsigned long)_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	*image_size = kernel_size + (_end - _edata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	 * RISC-V kernel maps PAGE_OFFSET virtual address to the same physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	 * address where kernel is booted. That's why kernel should boot from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	 * as low as possible to avoid wastage of memory. Currently, dram_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	 * is occupied by the firmware. So the preferred address for kernel to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	 * boot is next aligned address. If preferred address is not available,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	 * relocate_kernel will fall back to efi_low_alloc_above to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	 * lowest possible memory region as long as the address and size meets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	 * the alignment constraints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	preferred_addr = MIN_KIMG_ALIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	status = efi_relocate_kernel(image_addr, kernel_size, *image_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 				     preferred_addr, MIN_KIMG_ALIGN, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (status != EFI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		efi_err("Failed to relocate kernel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		*image_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }