Initial import of NFC GNSS SDK project

This commit is contained in:
chenjintao
2026-09-15 16:10:12 +08:00
commit 2746cc3d4e
3070 changed files with 892062 additions and 0 deletions
@@ -0,0 +1,3 @@
MODULE = cpu
include $(RIOTBASE)/Makefile.base
@@ -0,0 +1,3 @@
export CPU_ARCH = cortex-r5
include $(RIOTMAKE)/arch/cortexr.inc.mk
@@ -0,0 +1,270 @@
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "freq.h"
#include "reg.h"
#include "syscall-arom.h"
#include "cpu.h"
#include "log.h"
#define LOG_MODULE "Freq"
#define LOG_LEVEL LOG_LEVEL_MAIN
/*---------------------------------------------------------------------------*/
/* PMU AP register offset */
#define PMUA_CP_CPU_CLK_CTRL 0x10C
#define PMUA_ACLK_CTRL 0x144
/* CP CPU CLK Control register bit */
#define CP_CORE_ACLK_DIV_SHIFT 9
#define CP_CORE_MC_CLK_DIV_SHIFT 6
#define CP_CORE_PCLK_DIV_SHIFT 3
#define CP_CORE_PCLK_SEL_SHIFT 0
#define CP_CORE_CLK_FC_REQ (1 << 12)
/* ACLK Control register bit */
#define ACLK_FC_REQ (1 << 4)
#define ACLK_SEL_LEGACY (1 << 0)
#define ACLK_SEL (3 << 0)
/* PLL1 SW control register 2 */
#define APB_SPARE2_REG 0xD4090104
#define CLK_SEL_MASK 0x7
#define CLK_DIV_MASK 0x7
/* PLL1 SW control register 3 for watch1 cr5 */
#define SYS_PLL1_CTL3_REG (0x41000000 + 0x88)
/*---------------------------------------------------------------------------*/
void
cr5_freq_change(unsigned pclk_sel, unsigned pclk_div)
{
unsigned val, mask;
unsigned aclk_div = 1, mc_clk_div = 1;
int i;
/* Enable PPL1 307, 350, 409, 491, 614, 819 */
writel(readl(APB_SPARE2_REG) | (0x3F), APB_SPARE2_REG);
mask = (CLK_SEL_MASK << CP_CORE_PCLK_SEL_SHIFT) |
(CLK_DIV_MASK << CP_CORE_MC_CLK_DIV_SHIFT) |
(CLK_DIV_MASK << CP_CORE_PCLK_DIV_SHIFT) |
(CLK_DIV_MASK << CP_CORE_ACLK_DIV_SHIFT);
val = readl(PMU_BASE + PMUA_CP_CPU_CLK_CTRL);
val &= ~mask;
val |= (pclk_sel << CP_CORE_PCLK_SEL_SHIFT) |
(pclk_div << CP_CORE_PCLK_DIV_SHIFT) |
(mc_clk_div << CP_CORE_MC_CLK_DIV_SHIFT) |
(aclk_div << CP_CORE_ACLK_DIV_SHIFT) |
CP_CORE_CLK_FC_REQ;
writel(val, PMU_BASE + PMUA_CP_CPU_CLK_CTRL);
for(i = 0; i < 100000; i++) {
val = readl(PMU_BASE + PMUA_CP_CPU_CLK_CTRL);
if((val & CP_CORE_CLK_FC_REQ) == 0) {
break;
}
}
if(val & CP_CORE_CLK_FC_REQ) {
LOG_ERR("CR5 freq change failed\n");
}
}
/*---------------------------------------------------------------------------*/
void
axi_freq_change(unsigned int aclk_sel)
{
unsigned val;
int i;
val = readl(PMU_BASE + PMUA_ACLK_CTRL);
val &= ~ACLK_SEL;
val |= (aclk_sel & ACLK_SEL) | ACLK_FC_REQ;
writel(val, PMU_BASE + PMUA_ACLK_CTRL);
for(i = 0; i < 100000; i++) {
val = readl(PMU_BASE + PMUA_ACLK_CTRL);
if((val & ACLK_FC_REQ) == 0) {
break;
}
}
if(val & ACLK_FC_REQ) {
LOG_ERR("AXI freq change failed\n");
}
}
/*---------------------------------------------------------------------------*/
static bool
cr5_clk_legacy(void)
{
unsigned int chip_id = hw_chip_id();
return chip_id == CHIP_ID_CRANE ||
chip_id == CHIP_ID_CRANEG ||
chip_id == CHIP_ID_CRANEM ||
chip_id == CHIP_ID_CRANEL;
}
/*---------------------------------------------------------------------------*/
static bool
axi_clk_legacy(void)
{
unsigned int chip_id = hw_chip_id();
return chip_id == CHIP_ID_CRANE ||
chip_id == CHIP_ID_CRANEG ||
chip_id == CHIP_ID_CRANEM ||
chip_id == CHIP_ID_CRANEL;
}
/*---------------------------------------------------------------------------*/
/* pclk: CR5 clk; aclk AXI clk */
static const unsigned _cr5_clk[5] = { 409, 307, 491, 614, 819 };
static const unsigned _axi_clk[4] = { 154, 205, 189, 223 };
static const unsigned _cr5_clk_legacy[5] = { 416, 312, 499, 624, 832 };
static const unsigned _axi_clk_legacy[2] = { 156, 208 };
/* craneGT/craneLRH/CraneGD axi clock config are different from craneLS/LR/LG/LB etc. */
static const unsigned _axi_clk_cranelrh_gt[4] = { 223, 189, 154, 205 };
/* Lapwing axi clock config. */
static const unsigned _axi_clk_lapwing[4] = { 156, 208, 192, 312 };
/*---------------------------------------------------------------------------*/
int
get_curr_freq(unsigned *ppclk, unsigned *paclk)
{
unsigned cr5_val, axi_val, clk_sel, pclk_div;
const unsigned *cr5_clk, *axi_clk;
cr5_clk = cr5_clk_legacy() ? _cr5_clk_legacy : _cr5_clk;
cr5_val = readl(PMU_BASE + PMUA_CP_CPU_CLK_CTRL);
clk_sel = cr5_val & CLK_SEL_MASK;
pclk_div = (cr5_val >> CP_CORE_PCLK_DIV_SHIFT) & CLK_DIV_MASK;
if(clk_sel > 4) {
LOG_ERR("get_curr_freq failed, Invalid clk_sel, 0x%x = 0x%x \n",
PMU_BASE + PMUA_CP_CPU_CLK_CTRL, cr5_val);
return -1;
} else if(clk_sel == 4) {
*ppclk = cr5_clk[clk_sel];
} else {
*ppclk = cr5_clk[clk_sel] / (1 + pclk_div);
}
axi_val = readl(PMU_BASE + PMUA_ACLK_CTRL);
unsigned int chipid = hw_chip_id();
if(chipid == CHIP_ID_CRANELRH || chipid == CHIP_ID_CRANEGT
|| chipid == CHIP_ID_CRANEGD) {
axi_clk = _axi_clk_cranelrh_gt;
*paclk = axi_clk[axi_val & ACLK_SEL];
} else if(chipid == CHIP_ID_LAPWING) {
axi_clk = _axi_clk_lapwing;
*paclk = axi_clk[axi_val & ACLK_SEL];
} else if(axi_clk_legacy()) {
axi_clk = _axi_clk_legacy;
*paclk = axi_clk[axi_val & ACLK_SEL_LEGACY];
} else {
axi_clk = _axi_clk;
*paclk = axi_clk[axi_val & ACLK_SEL];
}
return 0;
}
/*---------------------------------------------------------------------------*/
#define CR5_PCLK_SEL_DEFAULT 0
#define AXI_FREQ_DEFAULT 0
/*---------------------------------------------------------------------------*/
void
cr5_axi_set_default_freq(void)
{
unsigned pclk_old, aclk_old, pclk, aclk;
if(get_curr_freq(&pclk_old, &aclk_old) < 0) {
goto error;
}
/*
* axi_clk_legacy(): CraneG/M/L
*/
unsigned int chip_id = hw_chip_id();
if(axi_clk_legacy() || chip_id == CHIP_ID_CRANELRH) {
/*
* keep max freq with 20240223 version, and don't restore default value.
*
* CraneG/M/L: 208MHz
* CraneLRH: 223MHz
*/
} else if(chip_id == CHIP_ID_CRANELR || chip_id == CHIP_ID_CRANELS) {
/*
* keep max freq with 20240223 version
*
* CraneLR/LS: 205MHz
*/
axi_freq_change(AXI_FREQ_208M);
} else if(chip_id == CHIP_ID_CRANELG) {
/*
* keep max freq with 20240223 version
*
* CraneLG 154MHz
*/
axi_freq_change(AXI_FREQ_156M);
} else {
cr5_freq_change(CR5_PCLK_SEL_DEFAULT, CR5_PCLK_DIV_0);
axi_freq_change(AXI_FREQ_DEFAULT);
}
if(get_curr_freq(&pclk, &aclk) < 0) {
goto error;
}
LOG_INFO("Freq change restore done: CR5 %uMHz -> %uMHz, AXI %uMHz -> %uMHz\n",
pclk_old, pclk, aclk_old, aclk);
return;
error:
LOG_ERR("%s failed\n", __func__);
}
/*---------------------------------------------------------------------------*/
void
cr5_axi_set_max_freq(void)
{
unsigned pclk_old, aclk_old, pclk, aclk;
if(get_curr_freq(&pclk_old, &aclk_old) < 0) {
goto error;
}
cr5_freq_change(CR5_PCLK_SEL_624, CR5_PCLK_DIV_0); /* CR5 624MHz or 614MHZ for newer chip */
unsigned freq_max;
unsigned int chipid = hw_chip_id();
if(chipid == CHIP_ID_CRANELRH || chipid == CHIP_ID_CRANEGT
|| chipid == CHIP_ID_CRANEGD) {
freq_max = AXI_FREQ_223M_LRH_GT;
} else if((chipid == CHIP_ID_LAPWING)) {
/* enable PLL1 DIV2, DIV23, DIV13, DIV11 */
writel(readl(APB_SPARE12_REG) | (1 << 16 | 1 << 17 | 1 << 18 | 1 << 19), APB_SPARE12_REG);
freq_max = AXI_FREQ_312M;
} else if(axi_clk_legacy()) {
freq_max = AXI_FREQ_208M;
} else if(chipid == CHIP_ID_WATCH1 || chipid == CHIP_ID_WATCH_TWO) {
/* enable PLL1 DIV11, DIV13, DIV23 for watch1, watch2 cr5*/
writel(readl(SYS_PLL1_CTL3_REG) | (0x7 << 13), SYS_PLL1_CTL3_REG);
freq_max = AXI_FREQ_223M;
} else {
/* enable PLL1 DIV11, DIV13, DIV23 */
writel(readl(APB_SPARE12_REG) | 0x7, APB_SPARE12_REG);
freq_max = AXI_FREQ_223M;
}
axi_freq_change(freq_max);
if(get_curr_freq(&pclk, &aclk) < 0) {
goto error;
}
LOG_INFO("Freq change done: CR5 %uMHz -> %uMHz, AXI %uMHz -> %uMHz\n",
pclk_old, pclk, aclk_old, aclk);
return;
error:
LOG_ERR("cr5_axi_set_max_freq failed\n");
}
/*---------------------------------------------------------------------------*/
@@ -0,0 +1,37 @@
#ifndef __FREQ_H__
#define __FREQ_H__
/* pclk_sel */
#define CR5_PCLK_SEL_416 0
#define CR5_PCLK_SEL_312 1
#define CR5_PCLK_SEL_499 2
#define CR5_PCLK_SEL_624 3
#define CR5_PCLK_SEL_832 4
/* pclk_div */
#define CR5_PCLK_DIV_0 0
#define CR5_PCLK_DIV_1 1
#define CR5_PCLK_DIV_2 2
#define CR5_PCLK_DIV_3 3
void cr5_freq_change(unsigned pclk_sel, unsigned pclk_div);
/* aclk_sel */
#define AXI_FREQ_156M 0
#define AXI_FREQ_208M 1
/*for craneLRH and craneGT A0 */
#define AXI_FREQ_223M_LRH_GT 0
/*for craneLS/LR/LG/LB and later chip */
#define AXI_FREQ_223M 3
/*for Lapwing */
#define AXI_FREQ_312M 3
void axi_freq_change(unsigned int aclk_sel);
/* pclk: CR5 clk; aclk AXI clk */
int get_curr_freq(unsigned *ppclk, unsigned *paclk);
void cr5_axi_set_default_freq(void);
void cr5_axi_set_max_freq(void);
#endif
@@ -0,0 +1,9 @@
#ifndef _MFP_DRV_H_
#define _MFP_DRV_H_
void spi_mfp_config(void);
void qspi_mfp_config(void);
void qspi_mfp_config_mx(void);
int uart_rx_gpio_config(void);
#endif
@@ -0,0 +1,61 @@
#ifndef _MPU_H_
#define _MPU_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
* Region number 0 has the lowest priority.
* Region number 15 is reserved for ROM code
*/
#define AROM_CODE_REGION_NUM 15 /* For AROM code */
#define SRAM_CODE_REGION_NUM 14 /* For SRAM code */
#define SQU_CODE_REGION_NUM 13 /* For SQU code */
#define SHMEM_CODE_REGION_NUM 12 /* For SHMEM code */
#define ATCM_CODE_REGION_NUM 11 /* For ATCM code */
#define PSRAM_DDR_REGION_NUM_RWX 10 /* For PSRAM or DDR RAM */
#define PSRAM_DDR_REGION_NUM_NONE 9 /* For PSRAM or DDR RAM */
#define L2SRAM_REGION_NUM 8 /* For L2SRAM */
#define SYS_APB_GROUP_REGION_NUM 7 /* For MCU SYS AHB/APB periperals */
#define MAX_USER_REGION_NUM 6
/* The MPU region access control definitions */
#define MPU_REGION_ACCESS_CTRL_B (1 << 0) /* Bufferable */
#define MPU_REGION_ACCESS_CTRL_C (1 << 1) /* Cacheable */
#define MPU_REGION_ACCESS_CTRL_S (1 << 2) /* Shared */
/*
* TEX: 0x1, non-cacheable
*/
#define MPU_REGION_ACCESS_CTRL_TEX(x) (((x) & 0x7) << 3) /* Type Extensions */
/*
* AP: 0, Permission fault
* 1, Privileged Access only
* 2, No user-mode write
* 3, Full access
*/
#define MPU_REGION_ACCESS_CTRL_AP(x) (((x) & 0x7) << 8) /* Access Permissions */
#define MPU_REGION_ACCESS_CTRL_XN (1 << 12) /* Execute Never */
#define MPU_ATTR_RWX (MPU_REGION_ACCESS_CTRL_AP(3) | \
MPU_REGION_ACCESS_CTRL_TEX(1))
#define MPU_ATTR_NONE (MPU_REGION_ACCESS_CTRL_XN | \
MPU_REGION_ACCESS_CTRL_AP(0))
/* The MPU region base address should be aligned with the size and the max size is 4GB */
int mpu_region_config(unsigned num, unsigned base, unsigned size, unsigned acc_ctrl);
int mpu_enable_max_priority_region(unsigned base, unsigned size, unsigned acc_ctrl);
void mpu_disable_max_priority_region(void);
int mpu_get_next_empty_region(void);
void mpu_disable_all_user_region(void);
void mpu_disable_user_used_region(void);
void mpu_clear(unsigned index);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,45 @@
#ifndef _SYSTEM_H_
#define _SYSTEM_H_
/*---------------------------------------------------------------------------*/
#define MPU_REGION_ACCESS_CTRL_TEX(x) (((x) & 0x7) << 3) /* Type Extensions */
#define MPU_REGION_ACCESS_CTRL_AP(x) (((x) & 0x7) << 8) /* Access Permissions */
/*---------------------------------------------------------------------------*/
#define isb() __asm__ volatile ("isb" : : : "memory")
#define dsb() __asm__ volatile ("dsb" : : : "memory")
/*---------------------------------------------------------------------------*/
#define SCTLR_M (1 << 0) /* Enable the MPU */
#define SCTLR_A (1 << 1) /* Alignment check enable bit */
#define SCTLR_C (1 << 2) /* Cache enable bit */
#define SCTLR_SW (1 << 10) /* SWP/SWPB enable bit */
#define SCTLR_Z (1 << 11) /* Branch prediction enable bit */
#define SCTLR_I (1 << 12) /* Instruction cache enable bit */
#define SCTLR_V (1 << 13) /* Vectors relocated to 0xffff0000 */
#define SCTLR_RR (1 << 14) /* Not on Cortex-R7 processor. Round Robin bit for cache implementation policy */
#define SCTLR_BR (1 << 17) /* Background region bit */
#define SCTLR_DZ (1 << 19) /* Divide by zero fault bit */
#define SCTLR_FI (1 << 21) /* Fast interrupts configuration enable */
#define SCTLR_U (1 << 22) /* Not on Cortex-R7 processor. Indicates use of the alignment model */
#define SCTLR_EE (1 << 25) /* Exception endianness */
#define SCTLR_NMFI (1 << 27) /* Non-maskable FIQ(NMFI) support */
#define SCTLR_TE (1 << 30) /* Thumb exception enable */
#define SCTLR_IE (1 << 31) /* Instruction Endianness */
/*---------------------------------------------------------------------------*/
static inline unsigned int
sctlr_get(void)
{
unsigned int val;
__asm__ __volatile__ ("mrc p15, 0, %0, c1, c0, 0" : "=r" (val) : : "memory", "cc");
return val;
}
/*---------------------------------------------------------------------------*/
static inline void
sctlr_set(unsigned int val)
{
__asm__ __volatile__ ("mcr p15, 0, %0, c1, c0, 0" : : "r" (val) : "memory", "cc");
isb();
}
/*---------------------------------------------------------------------------*/
#endif /* _SYSTEM_H_ */
@@ -0,0 +1,19 @@
__min_heap_size = 3K;
__stack_size = 0;
/*
* btcm space *
* ptable : btcm 0 K ~ 3 K, length 3 K
* asr property: btcm 3 K ~ 4 K, length 1 K
* lzma decode : btcm 4 K ~ 20K, length 16K
* user defined: btcm 20K ~ 32K, length 12K
* bootrom : btcm 32K ~ 64K, length 32K
*/
__btcm_user_offset = 20K;
/**
* psram space when boot *
* boot33 lzma decode space: 0x7e000000 ~ 0x7e100000, length 1M
* boot33 load space : 0x7e100000 ~ 0x7e200000, length 1M
*/
#include "crane_base.lds"
@@ -0,0 +1,188 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
__scratch_start = 0x00000080;
__scratch_end = 0x00010000;
__scratch2_start = 0xb0020000;
__scratch2_end = 0xb0028000;
#define AROM_HAS_SRAM (AROM_VERSION == 20200730 || \
AROM_VERSION == 20211016 || \
AROM_VERSION == 20221106 || \
AROM_VERSION == 20240430 || \
AROM_VERSION == 20221111)
#if AROM_VERSION == 20200730 /* CraneG/CraneM */
__arom_patch_start = 0xd100e508;
__arom_patch_end = 0xd1010000;
__aram_ctext_start = 0xd1f10000;
#elif AROM_VERSION == 20211016 /* CraneL */
__aram_ctext_start = 0xd1f10000;
#elif AROM_VERSION == 20221106 /* CraneL(X)/CraneGD */
__aram_ctext_start = 0xf0000000;
#elif AROM_VERSION == 20221111 /* CraneGT */
__aram_ctext_start = 0xd1f14000;
#elif AROM_VERSION == 20240430 /* Lapwing */
__aram_ctext_start = 0xa4050000;
#endif
#if AROM_HAS_SRAM
__aram_ctext_size = 0x8000;
#endif
#if AROM_VERSION == 20221111 /* CraneGT */
__ddr_base = 0x78000000;
__ddr_max_size = 0x08000000; /* 128MB, get real ddr size depends on efuse ddr type */
PROVIDE (__scratch3_start = __ddr_base);
PROVIDE (__scratch3_end = __ddr_base + 0x00800000); /* DDR 8M */
#elif AROM_VERSION == 20240430 /* Lapwing */
__ddr_base = 0x07800000;
__ddr_max_size = 0x00800000; /* Only 8MB(0x07800000 ~ 0x08000000) is used by Lapwing boot2 and flasher. */
PROVIDE (__scratch3_start = __ddr_base);
PROVIDE (__scratch3_end = __ddr_base + 8M); /* DDR 8MB */
#else
__psram_base = 0x7E000000;
__psram_max_size = 0x02000000; /* 32MB, get real psram size depends on efuse(pram has phy) or auto detect(psram no phy) */
PROVIDE (__scratch3_start = __psram_base);
PROVIDE (__scratch3_end = __psram_base + 0x00800000); /* psram 8M */
#endif
__btcm_user_start = __scratch2_start + __btcm_user_offset;
__btcm_user_end = __scratch2_end;
__lzma_decode_start = __scratch3_start;
__lzma_decode_size = (__scratch3_end - __scratch3_start) / 4;
__lzma_alloc_base = __scratch2_start;
__lzma_alloc_size = __btcm_user_offset;
MEMORY{
atcm : ORIGIN = __scratch_start, LENGTH = __scratch_end - __scratch_start + 64K
#if AROM_HAS_SRAM
sram : ORIGIN = __aram_ctext_start, LENGTH = __aram_ctext_size
#endif
#if AROM_VERSION == 20200730
patch : ORIGIN = __arom_patch_start, LENGTH = __arom_patch_end - __arom_patch_start
#endif
}
SECTIONS
{
.boot : {
__code_start = .;
*startup.o(.text .text.*)
. = ALIGN(64);
} > atcm
.text : {
KEEP(*(.ro.loadtable))
KEEP(*(.init))
*(.text.*syscall_register)
*lzma.o(.text .text.*)
*LzmaDec.o(.text .text.*)
*syscall.o(.text .text.*)
*decompress.o(.text .text.*)
*cinit.o(.text .text.*)
#ifdef MODULE_LOADTABLE
*loadtable.o(.text .text.*)
#endif
. = ALIGN(4);
__code_end = .;
} > atcm
.ctext : ALIGN(4) {
_ctext = .;
*(.text)
*(SORT(.text.*))
*(.gnu.linkonce.t.*)
. = ALIGN(4);
} > atcm
. = ALIGN(4);
_ctext_load_addr = LOADADDR(.ctext);
_ctext_offset = _ctext_load_addr - _start;
_ctext_size = SIZEOF(.ctext);
.rodata : ALIGN(4) {
_rodata = .;
*(.rodata)
*(SORT(.rodata.*))
*(.gnu.linkonce.r.*)
. = ALIGN(4);
__ctor_list = .;
KEEP(*(.ctors .init_array))
__ctor_end = .;
__dtor_list = .;
KEEP(*(.dtors .fini_array))
__dtor_end = .;
. = ALIGN(4);
#if AROM_HAS_SRAM && defined(APPLICATION_FLASHER)
} > sram AT > atcm
#else
} > atcm
#endif
. = ALIGN(4);
_rodata_loadaddr = LOADADDR(.rodata);
_rodata_offset = _rodata_loadaddr - _start;
_rodata_size = SIZEOF(.rodata);
.data : ALIGN(4) {
_data = .;
*(.data)
*(SORT(.data.*))
*(.gnu.linkonce.d.*)
. = ALIGN(4);
_edata = .;
#if AROM_HAS_SRAM && defined(APPLICATION_FLASHER)
} > sram AT > atcm
#else
} > atcm
#endif
. = ALIGN(4);
_data_load_addr = LOADADDR(.data);
_data_offset = _data_load_addr - _start;
_data_size = SIZEOF(.data);
#if AROM_VERSION != 20200730
_end = _data_load_addr + _data_size;
#endif
.bss (NOLOAD) : ALIGN(4) {
__bss_start = .;
*(.bss)
*(SORT(.bss.*))
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
#if AROM_HAS_SRAM && defined(APPLICATION_FLASHER)
} > sram AT > atcm
#else
} > atcm
#endif
. = __btcm_user_start;
/* heap section */
__heap_start = . ;
__heap_end = __btcm_user_end - __stack_size;
ASSERT(__heap_end > __heap_start + __min_heap_size, "error: heap size too small")
. = __heap_end;
__stack_start = .;
__stack_end = __stack_start + __stack_size;
#if AROM_VERSION == 20200730
.patch : {
_patch = .;
*(.patch)
*(SORT(.patch.*))
. = ALIGN(4);
} > patch AT > atcm
_patch_load_addr = LOADADDR(.patch);
_patch_offset = _patch_load_addr - _start;
_patch_size = SIZEOF(.patch);
_end = _patch_load_addr + _patch_size;
ASSERT(__arom_patch_end > __arom_patch_start + _patch_size, "error: patch code size exceeded the limit")
#endif
/DISCARD/ : { *(.comment .note.* .eh_frame .ARM.exidx* .ARM.extab*) }
}
@@ -0,0 +1,20 @@
__min_heap_size = 3K;
__stack_size = 0;
/*
* btcm space *
* ptable : btcm 0 K ~ 3 K, length 3 K
* asr property: btcm 3 K ~ 4 K, length 1 K
* lzma decode : btcm 4 K ~ 20K, length 16K
* user defined: btcm 20K ~ 32K, length 12K
* bootrom : btcm 32K ~ 64K, length 32K
*/
__btcm_user_offset = 20K;
/**
* psram space when downloading *
* lzma decode space: 0x7e000000 ~ 0x7e100000, length 1M
* download scratch : 0x7e100000 ~ 0x7e800000, length 7M,
* if psram is 4M : 0x7e100000 ~ 0x7e400000, length 3M,
*/
#include "crane_base.lds"
@@ -0,0 +1,14 @@
__min_heap_size = 3K;
__stack_size = 0;
/*
* btcm space *
* ptable : btcm 0 K ~ 3 K, length 3 K
* asr property: btcm 3 K ~ 4 K, length 1 K
* lzma decode : btcm 4 K ~ 20K, length 16K
* user defined: btcm 20K ~ 32K, length 12K
* bootrom : btcm 32K ~ 64K, length 32K
*/
__btcm_user_offset = 20K;
#include "crane_base.lds"
@@ -0,0 +1,103 @@
#include "mfp-drv.h"
#include "mfp.h"
#include "syscall-arom.h"
#include "cpu.h"
/* Pin register definitions */
/* --------------------------------------------------------------- */
#define QSPI_DAT3_MPFI (0x2C4)
#define QSPI_DAT2_MPFI (0x2C8)
#define QSPI_DAT1_MPFI (0x2CC)
#define QSPI_DAT0_MPFI (0x2D0)
#define QSPI_CLK_MPFI (0x2D4)
#define QSPI_CS1_MPFI (0x2D8)
#define QSPI_CS2_MPFI (0x2DC)
#define QSPI_DQM_MPFI (0x2E0)
/* --------------------------------------------------------------- */
#define AP_UART1_CRANEGML_RXD 0x150
#define AP_UART1_CRANELR_RXD 0x1BC
#define AP_UART1_CRANELS_RXD 0x148
/* --------------------------------------------------------------- */
#if AROM_VERSION == AROM_VER_2020_07_30_CRANEGM_A0
/*
* eg: MX25U12835F, DAT3 has other function(WP/Hold pin) when spi mode. mx need always pull up dat3 when quad read.
* bootrom use standard spi mode, so use Dat0 and Dat1.
* bootrom need pull up Dat2 and Dat3 to disable other function of the pins.
* bootloader will read device id to judge whether the flash is common, can recover Dat2 and Dat3 to pull down mode(hardware default).
*/
static const uint32_t mfp_cfgs_spi[] = {
MFP_REG(QSPI_DAT3_MPFI) | MFP_DRIVE_MEDIUM | MFP_AF0 | MFP_PULL_HIGH,
MFP_REG(QSPI_DAT2_MPFI) | MFP_DRIVE_MEDIUM | MFP_AF0 | MFP_PULL_HIGH,
MFP_EOC
};
#endif
/* --------------------------------------------------------------- */
/* recover default mode(hardware default is pull down mode) for common flashes */
static const uint32_t mfp_cfgs_quad_spi[] = {
MFP_REG(QSPI_DAT3_MPFI) | MFP_DRIVE_MEDIUM | MFP_AF0,
MFP_REG(QSPI_DAT2_MPFI) | MFP_DRIVE_MEDIUM | MFP_AF0,
MFP_EOC
};
/* --------------------------------------------------------------- */
static const uint32_t mfp_cfgs_mx[] = {
MFP_REG(QSPI_DAT3_MPFI) | MFP_DRIVE_MEDIUM | MFP_AF0 | MFP_PULL_HIGH,
MFP_EOC
};
/* --------------------------------------------------------------- */
/* if AROM_NEXT_DELIVER, mfp_cfgs_spi can be removed.
* pull up Dat3 and Dat2 for read id always successfully for speacial flash. eg mx
*/
void
spi_mfp_config(void)
{
#if AROM_VERSION == AROM_VER_2020_07_30_CRANEGM_A0
mfp_config((uint32_t *)mfp_cfgs_spi);
#endif
}
/* --------------------------------------------------------------- */
void
qspi_mfp_config(void)
{
mfp_config((uint32_t *)mfp_cfgs_quad_spi);
}
/* --------------------------------------------------------------- */
void
qspi_mfp_config_mx(void)
{
mfp_config((uint32_t *)mfp_cfgs_mx);
}
/* --------------------------------------------------------------- */
static const uint32_t uart1_mfp_cranelr_cfgs[] = {
MFP_REG(AP_UART1_CRANELR_RXD) | MFP_DRIVE_MEDIUM | MFP_PULL_NONE | MFP_AF0,
MFP_EOC
};
/* --------------------------------------------------------------- */
static const uint32_t uart1_mfp_cranels_cfgs[] = {
MFP_REG(AP_UART1_CRANELS_RXD) | MFP_DRIVE_MEDIUM | MFP_PULL_NONE | MFP_AF0,
MFP_EOC
};
/* --------------------------------------------------------------- */
static const uint32_t uart1_mfp_cranegml_cfgs[] = {
MFP_REG(AP_UART1_CRANEGML_RXD) | MFP_DRIVE_MEDIUM | MFP_PULL_NONE | MFP_AF0,
MFP_EOC
};
/* --------------------------------------------------------------- */
int
uart_rx_gpio_config(void)
{
switch(hw_chip_id()) {
case CHIP_ID_CRANELR:
mfp_config((uint32_t *)uart1_mfp_cranelr_cfgs);
return 1;
case CHIP_ID_CRANELS:
mfp_config((uint32_t *)uart1_mfp_cranels_cfgs);
return 1;
case CHIP_ID_CRANEG:
case CHIP_ID_CRANEM:
case CHIP_ID_CRANEL:
mfp_config((uint32_t *)uart1_mfp_cranegml_cfgs);
return 1;
}
return 0;
}
/* --------------------------------------------------------------- */
@@ -0,0 +1,234 @@
#include <stdio.h>
#include "mpu.h"
#include "system.h"
/*---------------------------------------------------------------------------*/
#define MPU_REGION_SIZE_MASK (0x1f << 1) /* Region size mask */
#define MPU_REGION_ENABLE (1 << 0) /* Region Enable */
/*---------------------------------------------------------------------------*/
static inline unsigned int
_mpu_get_region_num(void)
{
unsigned int val;
__asm__ __volatile__ ("mrc p15, 0, %0, c6, c2, 0" : "=r" (val) : : "memory", "cc");
return val;
}
/*---------------------------------------------------------------------------*/
static inline void
_mpu_set_region_num(unsigned int val)
{
__asm__ __volatile__ ("mcr p15, 0, %0, c6, c2, 0" : : "r" (val) : "memory", "cc");
isb();
}
/*---------------------------------------------------------------------------*/
static inline unsigned int
_mpu_get_region_base_addr(void)
{
unsigned int val;
__asm__ __volatile__ ("mrc p15, 0, %0, c6, c1, 0" : "=r" (val) : : "memory", "cc");
return val;
}
/*---------------------------------------------------------------------------*/
static inline void
_mpu_set_region_base_addr(unsigned int val)
{
__asm__ __volatile__ ("mcr p15, 0, %0, c6, c1, 0" : : "r" (val) : "cc");
isb();
}
/*---------------------------------------------------------------------------*/
static inline unsigned int
_mpu_get_region_size(void)
{
unsigned int val;
__asm__ __volatile__ ("mrc p15, 0, %0, c6, c1, 2" : "=r" (val) : : "memory", "cc");
return (val & MPU_REGION_SIZE_MASK) >> 1;
}
/*---------------------------------------------------------------------------*/
static inline void
_mpu_set_region_size(unsigned int size)
{
unsigned val;
__asm__ __volatile__ ("mrc p15, 0, %0, c6, c1, 2" : "=r" (val) : : "memory", "cc");
val = (val & ~MPU_REGION_SIZE_MASK) | (size << 1);
__asm__ __volatile__ ("mcr p15, 0, %0, c6, c1, 2" : : "r" (val) : "cc");
isb();
}
/*---------------------------------------------------------------------------*/
static inline unsigned int
_mpu_get_region_size_enable(void)
{
unsigned int val;
__asm__ __volatile__ ("mrc p15, 0, %0, c6, c1, 2" : "=r" (val) : : "memory", "cc");
return val;
}
/*---------------------------------------------------------------------------*/
static inline unsigned int
_mpu_get_region_access_ctrl(void)
{
unsigned int acc_ctrl;
__asm__ __volatile__ ("mrc p15, 0, %0, c6, c1, 4" : "=r" (acc_ctrl) : : "memory", "cc");
return acc_ctrl;
}
/*---------------------------------------------------------------------------*/
static inline void
_mpu_set_region_access_ctrl(unsigned int acc_ctrl)
{
__asm__ __volatile__ ("mcr p15, 0, %0, c6, c1, 4" : : "r" (acc_ctrl) : "cc");
isb();
}
/*---------------------------------------------------------------------------*/
static inline void
_mpu_enable_region(unsigned int num, unsigned int enable)
{
unsigned val;
_mpu_set_region_num(num);
__asm__ __volatile__ ("mrc p15, 0, %0, c6, c1, 2" : "=r" (val) : : "memory", "cc");
if(enable) {
val |= MPU_REGION_ENABLE;
} else {
val &= ~MPU_REGION_ENABLE;
}
__asm__ __volatile__ ("mcr p15, 0, %0, c6, c1, 2" : : "r" (val) : "cc");
isb();
}
/*---------------------------------------------------------------------------*/
static unsigned next_empty_region_num;
/*---------------------------------------------------------------------------*/
/* Base address should be aligned with the size, the max size is 4GB */
static unsigned int
convert_region_size(unsigned long long size, unsigned int base)
{
unsigned val;
if(size < 32 || (size & (size - 1))) {
printf("Size should be power of two between 32 Bytes and 4GB\n");
goto error;
}
if(base & (size - 1)) {
printf("Base must be aligned to the size\n");
goto error;
}
val = 0;
while(size) {
val++;
size >>= 1;
}
val -= 2; /* 32 bytes-> 0x4, 4GB -> 0x1F */
return val;
error:
return 0;
}
/*---------------------------------------------------------------------------*/
static int
_mpu_region_config(unsigned region_num, unsigned base, unsigned size, unsigned acc_ctrl)
{
unsigned int region_size;
region_size = convert_region_size(size, base);
if(region_size == 0) {
printf("region size is 0\n");
goto error;
}
_mpu_set_region_num(region_num);
_mpu_set_region_base_addr(base);
_mpu_set_region_access_ctrl(acc_ctrl);
_mpu_set_region_size(region_size);
_mpu_enable_region(region_num, 1);
return 0;
error:
printf("_mpu_region_config failed\n");
return -1;
}
/*---------------------------------------------------------------------------*/
int
mpu_region_config(unsigned region_num, unsigned base, unsigned size, unsigned acc_ctrl)
{
if(_mpu_region_config(region_num, base, size, acc_ctrl) < 0) {
goto error;
}
if(region_num < MAX_USER_REGION_NUM) {
if(region_num >= next_empty_region_num) {
next_empty_region_num = region_num + 1;
}
}
return 0;
error:
printf("%s failed\n", __func__);
return -1;
}
/*---------------------------------------------------------------------------*/
int
mpu_get_next_empty_region(void)
{
return next_empty_region_num;
}
/*---------------------------------------------------------------------------*/
void
mpu_disable_all_user_region(void)
{
unsigned i;
for(i = 0; i <= MAX_USER_REGION_NUM; i++) {
_mpu_enable_region(i, 0);
}
next_empty_region_num = 0;
}
/*---------------------------------------------------------------------------*/
void
mpu_disable_user_used_region(void)
{
unsigned i;
for(i = 0; i < next_empty_region_num; i++) {
_mpu_enable_region(i, 0);
}
next_empty_region_num = 0;
}
/*---------------------------------------------------------------------------*/
int
mpu_config(unsigned index, unsigned base, unsigned size, unsigned acc_ctrl)
{
return mpu_region_config(index, base, size, acc_ctrl);
}
/*---------------------------------------------------------------------------*/
void
mpu_clear(unsigned index)
{
_mpu_enable_region(index, 0);
}
/*---------------------------------------------------------------------------*/
int
mpu_get_next(void)
{
return mpu_get_next_empty_region();
}
/*---------------------------------------------------------------------------*/
void
mpu_clear_used(void)
{
mpu_disable_user_used_region();
}
/*---------------------------------------------------------------------------*/
@@ -0,0 +1,54 @@
#include <stdint.h>
#include "cinit.h"
#include "syscall-arom.h"
#include "log.h"
#include "bl2_arg.h"
#ifdef MODULE_LOADTABLE
#include "loadtable.h"
#endif
#include "pmu.h"
#ifdef MODULE_NVCTR_SYSCALL
#include "nvctr_syscall.h"
#endif
/*---------------------------------------------------------------------------*/
extern int main(void);
/*---------------------------------------------------------------------------*/
__attribute__((target("arm"), section(".text.boot")))
int
_start(bl2_arg_t *arg)
{
#ifdef MODULE_LOADTABLE
if(process_loadtable() < 0) {
return -1;
}
#endif
cinit_clear_bss();
syscall_init();
#ifdef MODULE_NVCTR_SYSCALL
/*
* Can not put it in the syscall_init() because syscall_init()
* may be invoked in process_loadtable() for compressed image
* and the code is not ready at that time.
*/
nvctr_arom_refs_init();
#endif
bl2_arg_init(arg);
arg = bl2_arg_get();
if(arg && arg->disable_log) {
log_set_level("main", LOG_LEVEL_ERR);
} else {
if(usb_connect() == 0) {
log_set_level("main", LOG_LEVEL_PRINT);
}
}
cinit_call_constructors();
int rc = main();
return rc;
}