mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-21 10:36:04 +08:00
[libcpu][aarch64] 使用设备树对CPU进行初始化 (#8221)
This commit is contained in:
@@ -8,6 +8,9 @@ cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*.S')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
if GetDepend('RT_USING_OFW') == False:
|
||||
SrcRemove(src, ['setup.c', 'cpu_psci.c', 'psci.c'])
|
||||
|
||||
group = DefineGroup('common', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
# build for sub-directory
|
||||
|
||||
+14
-197
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -7,37 +7,33 @@
|
||||
* Date Author Notes
|
||||
* 2011-09-15 Bernard first version
|
||||
* 2019-07-28 zdzn add smp support
|
||||
* 2023-02-21 GuEe-GUI mov cpu ofw init to setup
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
#include "cp15.h"
|
||||
#include <rtdevice.h>
|
||||
#include <cpu.h>
|
||||
|
||||
#define DBG_TAG "libcpu.aarch64.cpu"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
#include <string.h>
|
||||
#include "cpu.h"
|
||||
#include "psci_api.h"
|
||||
|
||||
void (*system_off)(void);
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
|
||||
#ifdef RT_USING_FDT
|
||||
#include "dtb_node.h"
|
||||
struct dtb_node *_cpu_node[RT_CPUS_NR];
|
||||
#endif /* RT_USING_FDT */
|
||||
|
||||
#define MPIDR_AFF_MASK 0x000000FF00FFFFFFul
|
||||
#define REPORT_ERR(retval) LOG_E("got error code %d in %s(), %s:%d", (retval), __func__, __FILE__, __LINE__)
|
||||
#define CHECK_RETVAL(retval) if (retval) {REPORT_ERR(retval);}
|
||||
#define cpuid_to_hwid(cpuid) \
|
||||
((((cpuid) >= 0) && ((cpuid) < RT_CPUS_NR)) ? rt_cpu_mpidr_early[cpuid] : ID_ERROR)
|
||||
#define set_hwid(cpuid, hwid) \
|
||||
((((cpuid) >= 0) && ((cpuid) < RT_CPUS_NR)) ? (rt_cpu_mpidr_early[cpuid] = (hwid)) : ID_ERROR)
|
||||
#define get_cpu_node(cpuid) \
|
||||
((((cpuid) >= 0) && ((cpuid) < RT_CPUS_NR)) ? _cpu_node[cpuid] : NULL)
|
||||
#define set_cpu_node(cpuid, node) \
|
||||
((((cpuid) >= 0) && ((cpuid) < RT_CPUS_NR)) ? (_cpu_node[cpuid] = node) : NULL)
|
||||
|
||||
/**
|
||||
* cpu_ops_tbl contains cpu_ops_t for each cpu kernel observed,
|
||||
* given cpu logical id 'i', its cpu_ops_t is 'cpu_ops_tbl[i]'
|
||||
*/
|
||||
typedef rt_hw_spinlock_t arch_spinlock_t;
|
||||
struct cpu_ops_t *cpu_ops_tbl[RT_CPUS_NR];
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
@@ -59,8 +55,6 @@ rt_weak rt_uint64_t rt_cpu_mpidr_early[] =
|
||||
};
|
||||
#endif /* RT_USING_SMART */
|
||||
|
||||
typedef rt_hw_spinlock_t arch_spinlock_t;
|
||||
|
||||
static inline void arch_spin_lock(arch_spinlock_t *lock)
|
||||
{
|
||||
unsigned int tmp;
|
||||
@@ -138,115 +132,6 @@ static int _cpus_init_data_hardcoded(int num_cpus, rt_uint64_t *cpu_hw_ids, stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_FDT
|
||||
|
||||
/** read ('size' * 4) bytes number from start, big-endian format */
|
||||
static rt_uint64_t _read_be_number(void *start, int size)
|
||||
{
|
||||
rt_uint64_t buf = 0;
|
||||
for (; size > 0; size--)
|
||||
{
|
||||
buf = (buf << 32) | fdt32_to_cpu(*(uint32_t *)start);
|
||||
start = (uint32_t *)start + 1;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** check device-type of the node, */
|
||||
static bool _node_is_cpu(struct dtb_node *node)
|
||||
{
|
||||
char *device_type = dtb_node_get_dtb_node_property_value(node, "device_type", NULL);
|
||||
if (device_type)
|
||||
{
|
||||
return !strcmp(device_type, "cpu");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int _read_and_set_hwid(struct dtb_node *cpu, int *id_pool, int *pcpuid)
|
||||
{
|
||||
// size/address_cells is number of elements in reg array
|
||||
int size;
|
||||
static int address_cells, size_cells;
|
||||
if (!address_cells && !size_cells)
|
||||
dtb_node_get_dtb_node_cells(cpu, &address_cells, &size_cells);
|
||||
|
||||
void *id_start = dtb_node_get_dtb_node_property_value(cpu, "reg", &size);
|
||||
rt_uint64_t mpid = _read_be_number(id_start, address_cells);
|
||||
|
||||
*pcpuid = *id_pool;
|
||||
*id_pool = *id_pool + 1;
|
||||
set_hwid(*pcpuid, mpid);
|
||||
|
||||
LOG_I("Using MPID 0x%lx as cpu %d", mpid, *pcpuid);
|
||||
|
||||
// setting _cpu_node for cpu_init use
|
||||
_cpu_node[*pcpuid] = cpu;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _read_and_set_cpuops(struct dtb_node *cpu, int cpuid)
|
||||
{
|
||||
char *method = dtb_node_get_dtb_node_property_value(cpu, "enable-method", NULL);
|
||||
if (!method)
|
||||
{
|
||||
LOG_E("Cannot read method from cpu node");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct cpu_ops_t *cpu_ops;
|
||||
if (!strcmp(method, cpu_ops_psci.method))
|
||||
{
|
||||
cpu_ops = &cpu_ops_psci;
|
||||
}
|
||||
else if (!strcmp(method, cpu_ops_spin_tbl.method))
|
||||
{
|
||||
cpu_ops = &cpu_ops_spin_tbl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_ops = RT_NULL;
|
||||
LOG_E("Not supported cpu_ops: %s", method);
|
||||
}
|
||||
cpu_ops_tbl[cpuid] = cpu_ops;
|
||||
|
||||
LOG_D("Using boot method [%s] for cpu %d", cpu_ops->method, cpuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _cpus_init_data_fdt()
|
||||
{
|
||||
// cpuid_to_hwid and cpu_ops_tbl with fdt
|
||||
void *root = get_dtb_node_head();
|
||||
int id_pool = 0;
|
||||
int cpuid;
|
||||
struct dtb_node *cpus = dtb_node_get_dtb_node_by_path(root, "/cpus");
|
||||
|
||||
// for each cpu node (device-type is cpu), read its mpid and set its cpuid_to_hwid
|
||||
for_each_node_child(cpus)
|
||||
{
|
||||
if (!_node_is_cpu(cpus))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id_pool > RT_CPUS_NR)
|
||||
{
|
||||
LOG_W("Reading more cpus from FDT than RT_CPUS_NR"
|
||||
"\n Parsing will not continue and only %d cpus will be used.", RT_CPUS_NR);
|
||||
break;
|
||||
}
|
||||
|
||||
_read_and_set_hwid(cpus, &id_pool, &cpuid);
|
||||
|
||||
_read_and_set_cpuops(cpus, cpuid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* RT_USING_FDT */
|
||||
|
||||
/** init cpu with hardcoded infomation or parsing from FDT */
|
||||
static int _cpus_init(int num_cpus, rt_uint64_t *cpu_hw_ids, struct cpu_ops_t *cpu_ops[])
|
||||
{
|
||||
@@ -258,9 +143,6 @@ static int _cpus_init(int num_cpus, rt_uint64_t *cpu_hw_ids, struct cpu_ops_t *c
|
||||
else
|
||||
{
|
||||
retval = -1;
|
||||
#ifdef RT_USING_FDT
|
||||
retval = _cpus_init_data_fdt();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (retval)
|
||||
@@ -278,7 +160,7 @@ static int _cpus_init(int num_cpus, rt_uint64_t *cpu_hw_ids, struct cpu_ops_t *c
|
||||
|
||||
if (cpu_ops_tbl[i] && cpu_ops_tbl[i]->cpu_init)
|
||||
{
|
||||
retval = cpu_ops_tbl[i]->cpu_init(i);
|
||||
retval = cpu_ops_tbl[i]->cpu_init(i, RT_NULL);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
else
|
||||
@@ -290,30 +172,6 @@ static int _cpus_init(int num_cpus, rt_uint64_t *cpu_hw_ids, struct cpu_ops_t *c
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _boot_secondary(void)
|
||||
{
|
||||
for (int i = 1; i < RT_CPUS_NR; i++)
|
||||
{
|
||||
int retval = -0xbad0; // mark no support operation
|
||||
if (cpu_ops_tbl[i] && cpu_ops_tbl[i]->cpu_boot)
|
||||
retval = cpu_ops_tbl[i]->cpu_boot(i);
|
||||
if (retval)
|
||||
{
|
||||
if (retval == -0xbad0)
|
||||
LOG_E("No cpu_ops was probed for CPU %d. Try to configure it or use fdt", i);
|
||||
else
|
||||
LOG_E("Failed to boot secondary CPU %d, error code %d", i, retval);
|
||||
} else {
|
||||
LOG_I("Secondary CPU %d booted", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rt_weak void rt_hw_secondary_cpu_up(void)
|
||||
{
|
||||
_boot_secondary();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief boot cpu with hardcoded data
|
||||
*
|
||||
@@ -334,29 +192,6 @@ int rt_hw_cpu_boot_secondary(int num_cpus, rt_uint64_t *cpu_hw_ids, struct cpu_o
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define CPU_INIT_USING_FDT 0,0,0
|
||||
|
||||
/**
|
||||
* @brief Initialize cpu infomation from fdt
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int rt_hw_cpu_init()
|
||||
{
|
||||
#ifdef RT_USING_FDT
|
||||
return _cpus_init(CPU_INIT_USING_FDT);
|
||||
#else
|
||||
LOG_E("CPU init failed since RT_USING_FDT was not defined");
|
||||
return -0xa; /* no fdt support */
|
||||
#endif /* RT_USING_FDT */
|
||||
}
|
||||
|
||||
rt_weak void rt_hw_secondary_cpu_idle_exec(void)
|
||||
{
|
||||
asm volatile("wfe" ::
|
||||
: "memory", "cc");
|
||||
}
|
||||
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
/**
|
||||
@@ -369,24 +204,6 @@ const char *rt_hw_cpu_arch(void)
|
||||
return "aarch64";
|
||||
}
|
||||
|
||||
/** shutdown CPU */
|
||||
void rt_hw_cpu_shutdown(void)
|
||||
{
|
||||
rt_uint32_t level;
|
||||
rt_kprintf("shutdown...\n");
|
||||
|
||||
if (system_off)
|
||||
system_off();
|
||||
LOG_E("system shutdown failed");
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
while (level)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
}
|
||||
MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_shutdown, shutdown, shutdown machine);
|
||||
|
||||
#ifdef RT_USING_CPU_FFS
|
||||
/**
|
||||
* This function finds the first bit set (beginning with the least significant bit)
|
||||
|
||||
+15
-39
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -9,49 +9,25 @@
|
||||
#ifndef __RT_HW_CPU_H__
|
||||
#define __RT_HW_CPU_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <rtdef.h>
|
||||
#include <cpuport.h>
|
||||
#include <mm_aspace.h>
|
||||
|
||||
#ifdef RT_USING_OFW
|
||||
#include <drivers/ofw.h>
|
||||
#endif
|
||||
|
||||
#define ID_ERROR __INT64_MAX__
|
||||
#define MPIDR_AFFINITY_MASK 0x000000ff00ffffffUL
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
struct cpu_ops_t
|
||||
{
|
||||
const char *method;
|
||||
int (*cpu_init)(rt_uint32_t id);
|
||||
int (*cpu_boot)(rt_uint32_t id);
|
||||
int (*cpu_init)(rt_uint32_t id, void *param);
|
||||
int (*cpu_boot)(rt_uint32_t id, rt_uint64_t entry);
|
||||
void (*cpu_shutdown)(void);
|
||||
};
|
||||
|
||||
/**
|
||||
* Identifier to mark a wrong CPU MPID.
|
||||
* All elements in rt_cpu_mpidr_early[] should be initialized with this value
|
||||
*/
|
||||
#define ID_ERROR __INT64_MAX__
|
||||
extern rt_uint64_t rt_cpu_mpidr_table[];
|
||||
|
||||
extern rt_uint64_t rt_cpu_mpidr_early[];
|
||||
extern struct dtb_node *_cpu_node[];
|
||||
|
||||
#define cpuid_to_hwid(cpuid) \
|
||||
((((cpuid) >= 0) && ((cpuid) < RT_CPUS_NR)) ? rt_cpu_mpidr_early[cpuid] : ID_ERROR)
|
||||
#define set_hwid(cpuid, hwid) \
|
||||
((((cpuid) >= 0) && ((cpuid) < RT_CPUS_NR)) ? (rt_cpu_mpidr_early[cpuid] = (hwid)) : ID_ERROR)
|
||||
#define get_cpu_node(cpuid) \
|
||||
((((cpuid) >= 0) && ((cpuid) < RT_CPUS_NR)) ? _cpu_node[cpuid] : NULL)
|
||||
#define set_cpu_node(cpuid, node) \
|
||||
((((cpuid) >= 0) && ((cpuid) < RT_CPUS_NR)) ? (_cpu_node[cpuid] = node) : NULL)
|
||||
|
||||
extern int rt_hw_cpu_init();
|
||||
|
||||
extern int rt_hw_cpu_boot_secondary(int num_cpus, rt_uint64_t *cpu_hw_ids, struct cpu_ops_t *cpu_ops[]);
|
||||
|
||||
extern void rt_hw_secondary_cpu_idle_exec(void);
|
||||
|
||||
extern struct cpu_ops_t cpu_ops_psci;
|
||||
|
||||
extern struct cpu_ops_t cpu_ops_spin_tbl;
|
||||
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
extern void (*system_off)(void);
|
||||
|
||||
#endif /* __RT_HW_CPU_H__ */
|
||||
#endif /* __RT_HW_CPU_H__ */
|
||||
|
||||
@@ -5,66 +5,36 @@
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-02-21 GuEe-GUI replace with drivers/psci
|
||||
*/
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
|
||||
#define DBG_TAG "libcpu.aarch64.cpu_psci"
|
||||
#define DBG_TAG "cpu.aa64"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
#include "cpu_ops_common.h"
|
||||
|
||||
#include "cpu.h"
|
||||
#include "errno.h"
|
||||
#include "psci.h"
|
||||
#include "psci_api.h"
|
||||
#include <cpu.h>
|
||||
#include <cpuport.h>
|
||||
#include <psci.h>
|
||||
|
||||
static int (*_psci_init)(void) = psci_init;
|
||||
|
||||
static int __call_method_init()
|
||||
static int psci_cpu_boot(rt_uint32_t cpuid, rt_uint64_t entry)
|
||||
{
|
||||
int (*init)(void) = _psci_init;
|
||||
_psci_init = RT_NULL;
|
||||
|
||||
return init();
|
||||
return rt_psci_cpu_on(cpuid, entry);
|
||||
}
|
||||
|
||||
/** return 0 on success, otherwise failed */
|
||||
#define _call_method_init() ((_psci_init) ? __call_method_init() : 0);
|
||||
|
||||
static int cpu_psci_cpu_init(rt_uint32_t cpuid)
|
||||
static void psci_cpu_shutdown(void)
|
||||
{
|
||||
// init psci only once
|
||||
return _call_method_init();
|
||||
rt_uint32_t state, state_id = PSCI_POWER_STATE_ID(0, 0, 0, PSCI_POWER_STATE_ID_POWERDOWN);
|
||||
|
||||
state = PSCI_POWER_STATE(PSCI_POWER_STATE_LEVEL_CORES, PSCI_POWER_STATE_TYPE_STANDBY, state_id);
|
||||
|
||||
rt_psci_cpu_off(state);
|
||||
}
|
||||
|
||||
static int cpu_psci_cpu_boot(rt_uint32_t cpuid)
|
||||
struct cpu_ops_t cpu_psci_ops =
|
||||
{
|
||||
rt_uint64_t secondary_entry_pa = get_secondary_entry_pa();
|
||||
|
||||
if (!secondary_entry_pa)
|
||||
return -1;
|
||||
|
||||
if (!psci_ops.cpu_on) {
|
||||
LOG_E("Uninitialized psci operation");
|
||||
return -1;
|
||||
}
|
||||
return psci_ops.cpu_on(cpuid_to_hwid(cpuid), secondary_entry_pa);
|
||||
}
|
||||
|
||||
static void cpu_psci_cpu_shutdown()
|
||||
{
|
||||
psci_ops.cpu_off(cpuid_to_hwid(rt_hw_cpu_id()));
|
||||
}
|
||||
|
||||
struct cpu_ops_t cpu_ops_psci = {
|
||||
.method = "psci",
|
||||
.cpu_boot = cpu_psci_cpu_boot,
|
||||
.cpu_init = cpu_psci_cpu_init,
|
||||
.cpu_shutdown = cpu_psci_cpu_shutdown,
|
||||
.cpu_boot = psci_cpu_boot,
|
||||
.cpu_shutdown = psci_cpu_shutdown,
|
||||
};
|
||||
|
||||
#endif /* RT_USING_SMP */
|
||||
@@ -5,76 +5,61 @@
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-02-21 GuEe-GUI replace with ofw
|
||||
*/
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
#include <ioremap.h>
|
||||
#else
|
||||
#define rt_ioremap(x, ...) (x)
|
||||
#define rt_iounmap(x)
|
||||
#endif
|
||||
|
||||
#define DBG_TAG "libcpu.aarch64.cpu_spin_table"
|
||||
#define DBG_TAG "cpu.aa64"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
#include "cpu_ops_common.h"
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
#ifdef RT_USING_FDT
|
||||
#include <dtb_node.h>
|
||||
#include <cpu.h>
|
||||
#include <cpuport.h>
|
||||
|
||||
#include <ioremap.h>
|
||||
#include <drivers/core/dm.h>
|
||||
|
||||
#ifdef RT_USING_OFW
|
||||
|
||||
static rt_uint64_t cpu_release_addr[RT_CPUS_NR];
|
||||
|
||||
static int spin_table_cpu_init(rt_uint32_t cpuid)
|
||||
static int spin_table_cpu_init(rt_uint32_t cpuid, void *param)
|
||||
{
|
||||
struct dtb_node *cpu = get_cpu_node(cpuid);
|
||||
if (!cpu)
|
||||
return -1; /* uninitialized cpu node in fdt */
|
||||
struct rt_ofw_node *cpu_np = param;
|
||||
|
||||
int size;
|
||||
rt_uint64_t *phead = (rt_uint64_t*)dtb_node_get_dtb_node_property_value(cpu, "cpu-release-addr", &size);
|
||||
cpu_release_addr[cpuid] = fdt64_to_cpu(*phead);
|
||||
rt_ofw_prop_read_u64(cpu_np, "cpu-release-addr", &cpu_release_addr[cpuid]);
|
||||
|
||||
LOG_D("Using release address 0x%p for CPU %d", cpu_release_addr[cpuid], cpuid);
|
||||
return 0;
|
||||
LOG_D("Using release address 0x%p for CPU %d", cpu_release_addr[cpuid], cpuid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spin_table_cpu_boot(rt_uint32_t cpuid)
|
||||
static int spin_table_cpu_boot(rt_uint32_t cpuid, rt_uint64_t entry)
|
||||
{
|
||||
rt_uint64_t secondary_entry_pa = get_secondary_entry_pa();
|
||||
if (!secondary_entry_pa)
|
||||
return -1;
|
||||
void *cpu_release_vaddr;
|
||||
|
||||
// map release_addr to addressable place
|
||||
void *rel_va = (void *)cpu_release_addr[cpuid];
|
||||
cpu_release_vaddr = rt_ioremap((void *)cpu_release_addr[cpuid], sizeof(cpu_release_addr[0]));
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
rel_va = rt_ioremap(rel_va, sizeof(cpu_release_addr[0]));
|
||||
#endif
|
||||
if (!rel_va)
|
||||
if (!cpu_release_vaddr)
|
||||
{
|
||||
LOG_E("IO remap failing");
|
||||
return -1;
|
||||
}
|
||||
|
||||
__asm__ volatile("str %0, [%1]" ::"rZ"(secondary_entry_pa), "r"(rel_va));
|
||||
__asm__ volatile("dsb sy");
|
||||
__asm__ volatile("sev");
|
||||
rt_iounmap(rel_va);
|
||||
__asm__ volatile ("str %0, [%1]" ::"rZ"(entry), "r"(cpu_release_vaddr));
|
||||
rt_hw_barrier(dsb, sy);
|
||||
rt_hw_sev();
|
||||
|
||||
rt_iounmap(cpu_release_vaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* RT_USING_FDT */
|
||||
|
||||
struct cpu_ops_t cpu_ops_spin_tbl = {
|
||||
struct cpu_ops_t cpu_spin_table_ops =
|
||||
{
|
||||
.method = "spin-table",
|
||||
#ifdef RT_USING_FDT
|
||||
.cpu_init = spin_table_cpu_init,
|
||||
.cpu_boot = spin_table_cpu_boot,
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* RT_USING_SMP */
|
||||
#endif
|
||||
|
||||
+367
-249
File diff suppressed because it is too large
Load Diff
+102
-54
@@ -5,21 +5,26 @@
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09-09 GuEe-GUI The first version
|
||||
*/
|
||||
|
||||
#ifndef __PSCI_H__
|
||||
#define __PSCI_H__
|
||||
|
||||
/**
|
||||
* PSCI protocol content
|
||||
* For PSCI v0.1, only return values below are protocol defined
|
||||
#include <rtdef.h>
|
||||
|
||||
/*
|
||||
* Non-Confidential PSCI 1.0 release (30 January 2015), and errata fix for PSCI 0.2, unsupport PSCI 0.1
|
||||
*/
|
||||
|
||||
/* PSCI v0.2 interface */
|
||||
/* PSCI 0.2 interface */
|
||||
#define PSCI_0_2_FN_BASE 0x84000000
|
||||
#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n))
|
||||
#define PSCI_0_2_64BIT 0x40000000
|
||||
#define PSCI_0_2_FN64_BASE (PSCI_0_2_FN_BASE + PSCI_0_2_64BIT)
|
||||
#define PSCI_0_2_FN_END 0x8400001F
|
||||
|
||||
#define PSCI_0_2_FN64_BASE 0xC4000000
|
||||
#define PSCI_0_2_FN64(n) (PSCI_0_2_FN64_BASE + (n))
|
||||
#define PSCI_0_2_FN64_END 0xC400001F
|
||||
|
||||
#define PSCI_0_2_FN_PSCI_VERSION PSCI_0_2_FN(0)
|
||||
#define PSCI_0_2_FN_CPU_SUSPEND PSCI_0_2_FN(1)
|
||||
@@ -35,69 +40,112 @@
|
||||
#define PSCI_0_2_FN64_CPU_SUSPEND PSCI_0_2_FN64(1)
|
||||
#define PSCI_0_2_FN64_CPU_ON PSCI_0_2_FN64(3)
|
||||
#define PSCI_0_2_FN64_AFFINITY_INFO PSCI_0_2_FN64(4)
|
||||
#define PSCI_0_2_FN64_MIGRATE (5)
|
||||
#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5)
|
||||
#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7)
|
||||
|
||||
/* PSCI 1.0 interface */
|
||||
#define PSCI_1_0_FN_PSCI_FEATURES PSCI_0_2_FN(10)
|
||||
#define PSCI_1_0_FN_CPU_FREEZE PSCI_0_2_FN(11)
|
||||
#define PSCI_1_0_FN_CPU_DEFAULT_SUSPEND PSCI_0_2_FN(12)
|
||||
#define PSCI_1_0_FN_NODE_HW_STATE PSCI_0_2_FN(13)
|
||||
#define PSCI_1_0_FN_SYSTEM_SUSPEND PSCI_0_2_FN(14)
|
||||
#define PSCI_1_0_FN_SET_SUSPEND_MODE PSCI_0_2_FN(15)
|
||||
#define PSCI_1_0_FN_STAT_RESIDENCY PSCI_0_2_FN(16)
|
||||
#define PSCI_1_0_FN_STAT_COUNT PSCI_0_2_FN(17)
|
||||
#define PSCI_1_1_FN_SYSTEM_RESET2 PSCI_0_2_FN(18)
|
||||
|
||||
#define PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND PSCI_0_2_FN64(12)
|
||||
#define PSCI_1_0_FN64_NODE_HW_STATE PSCI_0_2_FN64(13)
|
||||
#define PSCI_1_0_FN64_SYSTEM_SUSPEND PSCI_0_2_FN64(14)
|
||||
#define PSCI_1_0_FN64_STAT_RESIDENCY PSCI_0_2_FN64(16)
|
||||
#define PSCI_1_0_FN64_STAT_COUNT PSCI_0_2_FN64(17)
|
||||
#define PSCI_1_1_FN64_SYSTEM_RESET2 PSCI_0_2_FN64(18)
|
||||
|
||||
/* PSCI v0.2 power state encoding for CPU_SUSPEND function */
|
||||
#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff
|
||||
#define PSCI_0_2_POWER_STATE_ID_SHIFT 0
|
||||
#define PSCI_0_2_POWER_STATE_TYPE_SHIFT 16
|
||||
#define PSCI_0_2_POWER_STATE_TYPE_MASK (0x1 << PSCI_0_2_POWER_STATE_TYPE_SHIFT)
|
||||
#define PSCI_0_2_POWER_STATE_AFFL_SHIFT 24
|
||||
#define PSCI_0_2_POWER_STATE_AFFL_MASK (0x3 << PSCI_0_2_POWER_STATE_AFFL_SHIFT)
|
||||
|
||||
/* PSCI extended power state encoding for CPU_SUSPEND function */
|
||||
#define PSCI_1_0_EXT_POWER_STATE_ID_MASK 0xfffffff
|
||||
#define PSCI_1_0_EXT_POWER_STATE_ID_SHIFT 0
|
||||
#define PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT 30
|
||||
#define PSCI_1_0_EXT_POWER_STATE_TYPE_MASK (0x1 << PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT)
|
||||
|
||||
/* PSCI v0.2 affinity level state returned by AFFINITY_INFO */
|
||||
#define PSCI_0_2_AFFINITY_LEVEL_ON 0
|
||||
#define PSCI_0_2_AFFINITY_LEVEL_OFF 1
|
||||
#define PSCI_0_2_AFFINITY_LEVEL_ON_PENDING 2
|
||||
|
||||
/* PSCI v0.2 multicore support in Trusted OS returned by MIGRATE_INFO_TYPE */
|
||||
#define PSCI_0_2_TOS_UP_MIGRATE 0
|
||||
#define PSCI_0_2_TOS_UP_NO_MIGRATE 1
|
||||
#define PSCI_0_2_TOS_MP 2
|
||||
|
||||
/* PSCI version decoding (independent of PSCI version) */
|
||||
#define PSCI_VERSION_MAJOR_SHIFT 16
|
||||
#define PSCI_VERSION_MINOR_MASK ((1U << PSCI_VERSION_MAJOR_SHIFT) - 1)
|
||||
#define PSCI_VERSION_MAJOR_MASK ~PSCI_VERSION_MINOR_MASK
|
||||
#define PSCI_VERSION_MAJOR(ver) (((ver) & PSCI_VERSION_MAJOR_MASK) >> PSCI_VERSION_MAJOR_SHIFT)
|
||||
#define PSCI_VERSION_MINOR(ver) ((ver) & PSCI_VERSION_MINOR_MASK)
|
||||
#define PSCI_VERSION(maj, min) \
|
||||
((((maj) << PSCI_VERSION_MAJOR_SHIFT) & PSCI_VERSION_MAJOR_MASK) | \
|
||||
((min) & PSCI_VERSION_MINOR_MASK))
|
||||
#define PSCI_VERSION_MAJOR(version) (((version) & PSCI_VERSION_MAJOR_MASK) >> PSCI_VERSION_MAJOR_SHIFT)
|
||||
#define PSCI_VERSION_MINOR(version) ((version) & PSCI_VERSION_MINOR_MASK)
|
||||
#define PSCI_VERSION(major, min) ((((major) << PSCI_VERSION_MAJOR_SHIFT) & PSCI_VERSION_MAJOR_MASK) | \
|
||||
((min) & PSCI_VERSION_MINOR_MASK))
|
||||
|
||||
/* PSCI features decoding (>=1.0) */
|
||||
#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT 1
|
||||
#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK (0x1 << PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT)
|
||||
/* PSCI affinity level state returned by AFFINITY_INFO */
|
||||
#define PSCI_AFFINITY_LEVEL_ON 0
|
||||
#define PSCI_AFFINITY_LEVEL_OFF 1
|
||||
#define PSCI_AFFINITY_LEVEL_ON_PENDING 2
|
||||
|
||||
#define PSCI_1_0_OS_INITIATED BIT(0)
|
||||
#define PSCI_1_0_SUSPEND_MODE_PC 0
|
||||
#define PSCI_1_0_SUSPEND_MODE_OSI 1
|
||||
/*
|
||||
* PSCI power state
|
||||
* power_level:
|
||||
* Level 0: cores
|
||||
* Level 1: clusters
|
||||
* Level 2: system
|
||||
* state_type:
|
||||
* value 0: standby or retention state
|
||||
* value 1: powerdown state(entry and context_id is valid)
|
||||
* state_id:
|
||||
* StateID
|
||||
*/
|
||||
#define PSCI_POWER_STATE_LEVEL_CORES 0
|
||||
#define PSCI_POWER_STATE_LEVEL_CLUSTERS 1
|
||||
#define PSCI_POWER_STATE_LEVEL_SYSTEM 2
|
||||
|
||||
/* PSCI return values (inclusive of all PSCI versions) */
|
||||
#define PSCI_RET_SUCCESS 0
|
||||
#define PSCI_RET_NOT_SUPPORTED -1
|
||||
#define PSCI_RET_INVALID_PARAMS -2
|
||||
#define PSCI_RET_DENIED -3
|
||||
#define PSCI_RET_ALREADY_ON -4
|
||||
#define PSCI_RET_ON_PENDING -5
|
||||
#define PSCI_RET_INTERNAL_FAILURE -6
|
||||
#define PSCI_RET_NOT_PRESENT -7
|
||||
#define PSCI_RET_DISABLED -8
|
||||
#define PSCI_RET_INVALID_ADDRESS -9
|
||||
#define PSCI_POWER_STATE_TYPE_STANDBY 0
|
||||
#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
|
||||
|
||||
#endif /*__PSCI_H__*/
|
||||
#define PSCI_POWER_LEVEL_SHIFT 24
|
||||
#define PSCI_POWER_STATE_TYPE_SHIFT 16
|
||||
#define PSCI_POWER_STATE_ID_SHIFT 0
|
||||
#define PSCI_POWER_STATE(power_level, state_type, state_id) \
|
||||
( \
|
||||
((power_level) << PSCI_POWER_LEVEL_SHIFT) | \
|
||||
((state_type) << PSCI_POWER_STATE_TYPE_SHIFT) | \
|
||||
((state_id) << PSCI_POWER_STATE_ID_SHIFT) \
|
||||
)
|
||||
#define PSCI_POWER_LEVEL_VAL(state) (((state) >> PSCI_POWER_LEVEL_SHIFT) & 0x3)
|
||||
#define PSCI_POWER_STATE_TYPE_VAL(state) (((state) >> PSCI_POWER_STATE_TYPE_SHIFT) & 0x1)
|
||||
#define PSCI_POWER_STATE_ID_VAL(state) (((state) >> PSCI_POWER_STATE_ID_SHIFT) & 0xffff)
|
||||
|
||||
/*
|
||||
* For system, cluster, core
|
||||
* 0: run
|
||||
* 1: standby(only core)
|
||||
* 2: retention
|
||||
* 3: powerdown
|
||||
*/
|
||||
#define PSCI_POWER_STATE_ID_RUN 0
|
||||
#define PSCI_POWER_STATE_ID_STANDBY 1
|
||||
#define PSCI_POWER_STATE_ID_RETENTION 2
|
||||
#define PSCI_POWER_STATE_ID_POWERDOWN 3
|
||||
|
||||
#define PSCI_POWER_STATE_ID(state_id_power_level, system, cluster, core) \
|
||||
( \
|
||||
((state_id_power_level) << 12) | \
|
||||
((system) << 8) | \
|
||||
((cluster) << 4) | \
|
||||
(core) \
|
||||
)
|
||||
|
||||
#define PSCI_RET_SUCCESS 0
|
||||
#define PSCI_RET_NOT_SUPPORTED (-1)
|
||||
#define PSCI_RET_INVALID_PARAMETERS (-2)
|
||||
#define PSCI_RET_DENIED (-3)
|
||||
#define PSCI_RET_ALREADY_ON (-4)
|
||||
#define PSCI_RET_ON_PENDING (-5)
|
||||
#define PSCI_RET_INTERNAL_FAILURE (-6)
|
||||
#define PSCI_RET_NOT_PRESENT (-7)
|
||||
#define PSCI_RET_DISABLED (-8)
|
||||
#define PSCI_RET_INVALID_ADDRESS (-9)
|
||||
|
||||
void psci_system_off(void);
|
||||
void psci_system_reboot(void);
|
||||
rt_uint32_t rt_psci_get_version(void);
|
||||
rt_uint32_t rt_psci_cpu_on(int cpuid, rt_ubase_t entry_point);
|
||||
rt_uint32_t rt_psci_cpu_off(rt_uint32_t state);
|
||||
rt_uint32_t rt_psci_cpu_suspend(rt_uint32_t power_state, rt_ubase_t entry_point);
|
||||
rt_uint32_t rt_psci_migrate(int cpuid);
|
||||
rt_uint32_t rt_psci_get_affinity_info(rt_ubase_t target_affinity, rt_ubase_t lowest_affinity_level);
|
||||
rt_uint32_t rt_psci_migrate_info_type(void);
|
||||
|
||||
#endif /* __PSCI_H__ */
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
#ifndef __PSCI_API_H__
|
||||
#define __PSCI_API_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <stdint.h>
|
||||
#include "psci_api.h"
|
||||
|
||||
/** generic psci ops supported v0.1 v0.2 v1.0 v1.1 */
|
||||
struct psci_ops_t
|
||||
{
|
||||
uint32_t (*get_version)(void);
|
||||
int32_t (*cpu_suspend)(uint32_t state, unsigned long entry_point);
|
||||
int32_t (*cpu_off)(uint32_t state);
|
||||
int32_t (*cpu_on)(unsigned long cpuid, unsigned long entry_point);
|
||||
int32_t (*migrate)(unsigned long cpuid);
|
||||
|
||||
void (*system_off)(void);
|
||||
void (*system_reset)(void);
|
||||
};
|
||||
|
||||
extern struct psci_ops_t psci_ops;
|
||||
|
||||
extern int psci_init(void);
|
||||
|
||||
#endif // __PSCI_API_H__
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-02-21 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#define DBG_TAG "cpu.aa64"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include <cpu.h>
|
||||
#include <mmu.h>
|
||||
#include <cpuport.h>
|
||||
#include <interrupt.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ioremap.h>
|
||||
#include <drivers/ofw.h>
|
||||
#include <drivers/ofw_fdt.h>
|
||||
#include <drivers/ofw_raw.h>
|
||||
#include <drivers/core/dm.h>
|
||||
|
||||
#define rt_sysreg_write(sysreg, val) \
|
||||
__asm__ volatile ("msr "RT_STRINGIFY(sysreg)", %0"::"r"((rt_uint64_t)(val)))
|
||||
|
||||
#define rt_sysreg_read(sysreg, val) \
|
||||
__asm__ volatile ("mrs %0, "RT_STRINGIFY(sysreg)"":"=r"((val)))
|
||||
|
||||
extern void _secondary_cpu_entry(void);
|
||||
extern size_t MMUTable[];
|
||||
extern void *system_vectors;
|
||||
|
||||
static void *fdt_ptr = RT_NULL;
|
||||
static rt_size_t fdt_size = 0;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
extern struct cpu_ops_t cpu_psci_ops;
|
||||
extern struct cpu_ops_t cpu_spin_table_ops;
|
||||
#else
|
||||
extern int rt_hw_cpu_id(void);
|
||||
#endif
|
||||
|
||||
rt_uint64_t rt_cpu_mpidr_table[] =
|
||||
{
|
||||
[RT_CPUS_NR] = 0,
|
||||
};
|
||||
|
||||
static struct cpu_ops_t *cpu_ops[] =
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
&cpu_psci_ops,
|
||||
&cpu_spin_table_ops,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct rt_ofw_node *cpu_np[RT_CPUS_NR] = { };
|
||||
|
||||
void rt_hw_fdt_install_early(void *fdt)
|
||||
{
|
||||
void *fdt_vaddr = fdt - PV_OFFSET;
|
||||
|
||||
if (fdt != RT_NULL && !fdt_check_header(fdt_vaddr))
|
||||
{
|
||||
fdt_ptr = fdt_vaddr;
|
||||
fdt_size = fdt_totalsize(fdt_vaddr);
|
||||
}
|
||||
}
|
||||
|
||||
static void system_vectors_init(void)
|
||||
{
|
||||
rt_hw_set_current_vbar((rt_ubase_t)&system_vectors);
|
||||
}
|
||||
|
||||
rt_inline void cpu_info_init(void)
|
||||
{
|
||||
int i = 0;
|
||||
rt_uint64_t mpidr;
|
||||
struct rt_ofw_node *np;
|
||||
|
||||
/* get boot cpu info */
|
||||
rt_sysreg_read(mpidr_el1, mpidr);
|
||||
|
||||
rt_ofw_foreach_cpu_node(np)
|
||||
{
|
||||
rt_uint64_t hwid = rt_ofw_get_cpu_hwid(np, 0);
|
||||
|
||||
if ((mpidr & MPIDR_AFFINITY_MASK) != hwid)
|
||||
{
|
||||
/* Only save affinity and res make smp boot can check */
|
||||
hwid |= 1ULL << 31;
|
||||
}
|
||||
else
|
||||
{
|
||||
hwid = mpidr;
|
||||
}
|
||||
|
||||
cpu_np[i] = np;
|
||||
rt_cpu_mpidr_table[i] = hwid;
|
||||
|
||||
rt_ofw_data(np) = (void *)hwid;
|
||||
|
||||
for (int idx = 0; idx < RT_ARRAY_SIZE(cpu_ops); ++idx)
|
||||
{
|
||||
struct cpu_ops_t *ops = cpu_ops[idx];
|
||||
|
||||
if (ops->cpu_init)
|
||||
{
|
||||
ops->cpu_init(i, np);
|
||||
}
|
||||
}
|
||||
|
||||
if (++i >= RT_CPUS_NR)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, rt_cpu_mpidr_table, sizeof(rt_cpu_mpidr_table));
|
||||
}
|
||||
|
||||
void rt_hw_common_setup(void)
|
||||
{
|
||||
if (rt_fdt_prefetch(fdt_ptr))
|
||||
{
|
||||
/* Platform cannot be initialized */
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
|
||||
rt_fdt_unflatten();
|
||||
|
||||
cpu_info_init();
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_weak void rt_hw_secondary_cpu_up(void)
|
||||
{
|
||||
int cpu_id = rt_hw_cpu_id();
|
||||
rt_uint64_t entry = (rt_uint64_t)rt_kmem_v2p(_secondary_cpu_entry);
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
LOG_E("Failed to translate '_secondary_cpu_entry' to physical address");
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
|
||||
/* Maybe we are no in the first cpu */
|
||||
for (int i = 0; i < RT_ARRAY_SIZE(cpu_np); ++i)
|
||||
{
|
||||
int err;
|
||||
const char *enable_method;
|
||||
|
||||
if (!cpu_np[i] || i == cpu_id)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
err = rt_ofw_prop_read_string(cpu_np[i], "enable-method", &enable_method);
|
||||
|
||||
for (int idx = 0; !err && idx < RT_ARRAY_SIZE(cpu_ops); ++idx)
|
||||
{
|
||||
struct cpu_ops_t *ops = cpu_ops[idx];
|
||||
|
||||
if (ops->method && !rt_strcmp(ops->method, enable_method) && ops->cpu_boot)
|
||||
{
|
||||
err = ops->cpu_boot(i, entry);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
LOG_W("Call cpu %d on %s", i, "failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rt_weak void rt_hw_secondary_cpu_bsp_start(void)
|
||||
{
|
||||
int cpu_id = rt_hw_cpu_id();
|
||||
|
||||
system_vectors_init();
|
||||
|
||||
rt_hw_spin_lock(&_cpus_lock);
|
||||
|
||||
/* Save all mpidr */
|
||||
rt_sysreg_read(mpidr_el1, rt_cpu_mpidr_table[cpu_id]);
|
||||
|
||||
rt_hw_mmu_ktbl_set((unsigned long)MMUTable);
|
||||
|
||||
rt_hw_interrupt_init();
|
||||
|
||||
rt_dm_secondary_cpu_init();
|
||||
rt_hw_interrupt_umask(RT_SCHEDULE_IPI);
|
||||
rt_hw_interrupt_umask(RT_STOP_IPI);
|
||||
|
||||
LOG_I("Call cpu %d on %s", cpu_id, "success");
|
||||
|
||||
#ifdef RT_USING_HWTIMER
|
||||
if (rt_device_hwtimer_us_delay == &cpu_us_delay)
|
||||
{
|
||||
cpu_loops_per_tick_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
rt_system_scheduler_start();
|
||||
}
|
||||
|
||||
rt_weak void rt_hw_secondary_cpu_idle_exec(void)
|
||||
{
|
||||
rt_hw_wfe();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-02-21 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#ifndef __SETUP_H__
|
||||
#define __SETUP_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
#include <mm_aspace.h>
|
||||
#ifdef RT_USING_OFW
|
||||
#include <drivers/ofw_fdt.h>
|
||||
#endif
|
||||
|
||||
void rt_hw_common_setup(void);
|
||||
|
||||
#endif /* __SETUP_H__ */
|
||||
@@ -209,6 +209,11 @@ after_mmu_enable:
|
||||
adr x1, .el_stack_top
|
||||
mov sp, x1 /* sp_el1 set to _start */
|
||||
|
||||
#ifdef RT_USING_OFW
|
||||
/* Save devicetree info */
|
||||
mov x0, dtb_paddr
|
||||
bl rt_hw_fdt_install_early
|
||||
#endif
|
||||
b rtthread_startup
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
|
||||
Reference in New Issue
Block a user