diff --git a/src/arch/xtensa/exc-dump.S b/src/arch/xtensa/exc-dump.S index cb9746c0af42..060cc9c4a829 100644 --- a/src/arch/xtensa/exc-dump.S +++ b/src/arch/xtensa/exc-dump.S @@ -100,8 +100,10 @@ dump_special_registers: s32i a6, a2, REG_OFFSET_EPC3 rsr a6, EPC4 s32i a6, a2, REG_OFFSET_EPC4 +#if XCHAL_INTLEVEL5_MASK rsr a6, EPC5 s32i a6, a2, REG_OFFSET_EPC5 +#endif #if XCHAL_INTLEVEL6_MASK rsr a6, EPC6 s32i a6, a2, REG_OFFSET_EPC6 @@ -116,8 +118,10 @@ dump_special_registers: s32i a6, a2, REG_OFFSET_EPS3 rsr a6, EPS4 s32i a6, a2, REG_OFFSET_EPS4 +#if XCHAL_INTLEVEL5_MASK rsr a6, EPS5 s32i a6, a2, REG_OFFSET_EPS5 +#endif #if XCHAL_INTLEVEL6_MASK rsr a6, EPS6 s32i a6, a2, REG_OFFSET_EPS6 diff --git a/src/arch/xtensa/include/arch/atomic.h b/src/arch/xtensa/include/arch/atomic.h index e66fbab25cf6..195a87fa5810 100644 --- a/src/arch/xtensa/include/arch/atomic.h +++ b/src/arch/xtensa/include/arch/atomic.h @@ -11,6 +11,10 @@ #define __ARCH_ATOMIC_H__ #include +#if XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__ +#include +#endif +#include typedef struct { volatile int32_t value; @@ -31,6 +35,42 @@ static inline void arch_atomic_init(atomic_t *a, int32_t value) arch_atomic_set(a, value); } +#if XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__ + +/* Use exclusive instructions */ +static inline int32_t arch_atomic_add(atomic_t *a, int32_t value) +{ + /*reference xtos : xipc_misc.h*/ + int32_t result = 0; + int32_t current; + + while (!result) { + current = XT_L32EX((int32_t *)a); + result = current + value; + XT_S32EX(result, (int32_t *)a); + XT_GETEX(result); + } + return current; +} + +static inline int32_t arch_atomic_sub(atomic_t *a, int32_t value) +{ + /*reference xtos : xipc_misc.h*/ + int32_t current; + int32_t result = 0; + + while (!result) { + current = XT_L32EX((int *)a); + result = current - value; + XT_S32EX(result, (int *)a); + XT_GETEX(result); + } + return current; +} + +#elif XCHAL_HAVE_S32C1I + +/* Use S32C1I instructions */ static inline int32_t arch_atomic_add(atomic_t *a, int32_t value) { int32_t result, current; @@ -65,6 +105,42 @@ static inline int32_t arch_atomic_sub(atomic_t *a, int32_t value) return current; } +#else + +#if CONFIG_CORE_COUNT > 1 + +#error No atomic ISA for SMP configuration + +#endif + +/* + * The ISA has no atomic operations so use integer arithmetic on uniprocessor systems. + * This helps support GCC and qemu emulation of certain targets. + */ + +/* integer arithmetic methods */ +static inline int32_t arch_atomic_add(atomic_t *a, int32_t value) +{ + int32_t result, current; + + current = arch_atomic_read(a); + result = current + value; + arch_atomic_set(a, result); + return current; +} + +static inline int32_t arch_atomic_sub(atomic_t *a, int32_t value) +{ + int32_t result, current; + + current = arch_atomic_read(a); + result = current - value; + arch_atomic_set(a, result); + return current; +} + +#endif /* XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__ */ + #endif /* __ARCH_ATOMIC_H__ */ #else diff --git a/src/arch/xtensa/include/arch/spinlock.h b/src/arch/xtensa/include/arch/spinlock.h index 6d5687b28649..afb23479f864 100644 --- a/src/arch/xtensa/include/arch/spinlock.h +++ b/src/arch/xtensa/include/arch/spinlock.h @@ -11,6 +11,7 @@ #define __ARCH_SPINLOCK_H__ #include +#include typedef struct { volatile uint32_t lock; @@ -24,6 +25,44 @@ static inline void arch_spinlock_init(spinlock_t *lock) lock->lock = 0; } +#if XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__ + +static inline void arch_spin_lock(spinlock_t *lock) +{ + uint32_t result; + + __asm__ __volatile__( + " movi %0, 0\n" + " l32ex %0, %1\n" + "1: movi %0, 1\n" + " s32ex %0, %1\n" + " getex %0\n" + " bnez %0, 1b\n" + : "=&a" (result) + : "a" (&lock->lock) + : "memory"); +} + +static inline int arch_try_lock(spinlock_t *lock) +{ + uint32_t result; + + __asm__ __volatile__( + " movi %0, 0\n" + " l32ex %0, %1\n" + " movi %0, 1\n" + " s32ex %0, %1\n" + " getex %0\n" + : "=&a" (result) + : "a" (&lock->lock) + : "memory"); + + /* return 0 for failed lock, 1 otherwise */ + return result ? 0 : 1; +} + +#elif XCHAL_HAVE_S32C1I + static inline void arch_spin_lock(spinlock_t *lock) { uint32_t result; @@ -60,6 +99,47 @@ static inline int arch_try_lock(spinlock_t *lock) return result ? 0 : 1; } +#else + +#if CONFIG_CORE_COUNT > 1 + +#error No atomic ISA for SMP configuration + +#endif /* CONFIG_CORE_COUNT > 1 */ + +/* + * The ISA has no atomic operations so use integer arithmetic on uniprocessor systems. + * This helps support GCC and qemu emulation of certain targets. + */ +static inline void arch_spin_lock(spinlock_t *lock) +{ + uint32_t result; + + do { + if (lock->lock == 0) { + lock->lock = 1; + result = 1; + } + } while (!result); +} + +static inline int arch_try_lock(spinlock_t *lock) +{ + uint32_t result; + + if (lock->lock == 0) { + lock->lock = 1; + result = 1; + } + + /* return 0 for failed lock, 1 otherwise */ + return result ? 0 : 1; +} + +#endif /* XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__ */ + +#if XCHAL_HAVE_EXCLUSIVE || XCHAL_HAVE_S32C1I + static inline void arch_spin_unlock(spinlock_t *lock) { uint32_t result; @@ -72,6 +152,28 @@ static inline void arch_spin_unlock(spinlock_t *lock) : "memory"); } +#else + +#if CONFIG_CORE_COUNT > 1 + +#error No atomic ISA for SMP configuration + +#endif /* CONFIG_CORE_COUNT > 1 */ + +/* + * The ISA has no atomic operations so use integer arithmetic on uniprocessor systems. + * This helps support GCC and qemu emulation of certain targets. + */ +static inline void arch_spin_unlock(spinlock_t *lock) +{ + uint32_t result; + + lock->lock = 0; + result = 1; +} + +#endif /* XCHAL_HAVE_EXCLUSIVE || XCHAL_HAVE_S32C1I */ + #endif /* __ARCH_SPINLOCK_H__ */ #else diff --git a/src/arch/xtensa/xtos/crt1-boards.S b/src/arch/xtensa/xtos/crt1-boards.S index eefb2fbd83a8..3e2ed583e8a3 100644 --- a/src/arch/xtensa/xtos/crt1-boards.S +++ b/src/arch/xtensa/xtos/crt1-boards.S @@ -159,9 +159,11 @@ xtos_per_core: writesr excsave 3 a4 movi a4, _Level4FromVector writesr excsave 4 a4 +#if XCHAL_INTLEVEL5_MASK movi a4, _Level5FromVector writesr excsave 5 a4 #endif +#endif #if CONFIG_MULTICORE get_prid a5 diff --git a/src/arch/xtensa/xtos/reset-vector.S b/src/arch/xtensa/xtos/reset-vector.S index 7ef0229ac13f..d74964c65497 100644 --- a/src/arch/xtensa/xtos/reset-vector.S +++ b/src/arch/xtensa/xtos/reset-vector.S @@ -37,6 +37,11 @@ #include #include "xtos-internal.h" +#if XCHAL_HAVE_MPU +/* for mpu_write_map opcode */ +#include +#endif + // The following reset vector avoids initializing certain registers already // initialized by processor reset. But it does initialize some of them // anyway, for minimal support of warm restart (restarting in software by @@ -360,6 +365,31 @@ _ResetHandler: * protection mechanism, the following code has no effect.) */ #if XCHAL_HAVE_MPU + // If there is a user-provided MPU table, then we will program the MPU + // with it now. Can't call xthal_write_map_raw() because code sections + // haven't been unpacked yet. For romable images, the MPU table values + // and the table size must reside in a section that does not need to be + // unpacked (.ResetHandler.text or .srom.text). + // NOTE: This will set CACHEADRDIS to all zeros, because computing a + // useful nonzero value from the user settings is too complex and slow + // to implement here. + + .weak __xt_mpu_init_table // Table of MPU entries + .weak __xt_mpu_init_table_size // Number of entries in table + + movi a2, __xt_mpu_init_table // non-zero if user defined + movi a3, __xt_mpu_init_table_size // non-zero if user defined + beqz a2, .Lno_user_mpu + beqz a3, .Lno_user_mpu + l32i a3, a3, 0 + beqz a3, .Lno_user_mpu // skip if size = 0 + mpu_write_map a2, a3, a12, a13, a14, a15 + j .Lno_default_mpu + +.Lno_user_mpu: + // If there's an empty background map, setup foreground maps to mimic + // region protection. + /* If there's an empty background map, setup foreground maps to mimic region protection: */ # if XCHAL_MPU_ENTRIES >= 8 && XCHAL_MPU_BACKGROUND_ENTRIES <= 2 // We assume reset state: all MPU entries zeroed and disabled. @@ -394,6 +424,7 @@ _ResetHandler: movi a9, XCHAL_MPU_BG_CACHEADRDIS // default value of CACHEADRDIS for bgnd map # endif wsr.cacheadrdis a9 // update cacheadrdis +.Lno_default_mpu: #elif XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR \ || (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) movi a2, _memmap_cacheattr_reset /* note: absolute symbol, not a ptr */ diff --git a/src/platform/Kconfig b/src/platform/Kconfig index 7ed63698e555..412964e26eba 100644 --- a/src/platform/Kconfig +++ b/src/platform/Kconfig @@ -458,4 +458,11 @@ config AGENT_PANIC_ON_DELAY If scheduler timing verification fails, SA will call a DSP panic. +config XTENSA_EXCLUSIVE + bool + default n + help + This has to be selected for xtensa exclusive instructions. + There is a definition for EXCLUSIVE option in xtensa-config.h + endmenu diff --git a/src/platform/mt8195/platform.c b/src/platform/mt8195/platform.c index ba0b082e4347..9964207f0c63 100644 --- a/src/platform/mt8195/platform.c +++ b/src/platform/mt8195/platform.c @@ -124,6 +124,39 @@ static SHARED_DATA struct timer timer = { .irq = IRQ_NUM_TIMER0, }; +/* Override the default MPU setup. This table matches the memory map + * of the 'sample_controller' core and will need to be modified for + * other cores. + * NOTE: This table sets up all of external memory as shared uncached. + * For best results, edit the LSP memory map to create a separate + * section in shared memory, place all sections that need to be uncached + * into that section, and only map that section uncached. See README + * for more details. + */ +const unsigned int __xt_mpu_init_table_size __attribute__((section(".ResetVector.text"))) = 10; + +const struct xthal_MPU_entry __xt_mpu_init_table[] __attribute__((section(".ResetVector.text"))) = { + XTHAL_MPU_ENTRY(0x00000000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ + XTHAL_MPU_ENTRY(0x0C000000, 1, XTHAL_AR_RWXrwx, + XTHAL_MEM_DEVICE), /* MCU & DBG Registers read/write/execute */ + XTHAL_MPU_ENTRY(0x0F000000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ + XTHAL_MPU_ENTRY(0x10000000, 1, XTHAL_AR_RWXrwx, + XTHAL_MEM_DEVICE), /* DSP register: read/write/execute */ + XTHAL_MPU_ENTRY(0x12000000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ + XTHAL_MPU_ENTRY(0x40000000, 1, XTHAL_AR_RWXrwx, + XTHAL_MEM_WRITEBACK), /* DSP SRAM: read/write/execute writeback */ + XTHAL_MPU_ENTRY(0x40040000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ + XTHAL_MPU_ENTRY(0x60000000, 1, XTHAL_AR_RWXrwx, + XTHAL_MEM_WRITEBACK), /* DRAM: read/write/execute writeback */ + XTHAL_MPU_ENTRY(0x61000000, 1, XTHAL_AR_RWXrwx, + XTHAL_MEM_DEVICE), /* DMA: read/write/execute writeback */ + XTHAL_MPU_ENTRY(0x61100000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ +}; int platform_boot_complete(uint32_t boot_message) {