diff --git a/hal/armv7a/imx6ull/interrupts.c b/hal/armv7a/imx6ull/interrupts.c index c76d78e5c..0f82257c5 100644 --- a/hal/armv7a/imx6ull/interrupts.c +++ b/hal/armv7a/imx6ull/interrupts.c @@ -20,8 +20,6 @@ #include "proc/userintr.h" #define SIZE_INTERRUPTS 159 -#define SIZE_HANDLERS 4 - enum { /* 1024 reserved */ ctlr = 0x400, typer, iidr, /* 29 reserved */ igroupr0 = 0x420, /* 16 registers */ /* 16 reserved */ isenabler0 = 0x440, /* 16 registers */ /* 16 reserved */ icenabler0 = 0x460, /* 16 registers */ diff --git a/hal/armv7a/zynq7000/interrupts.c b/hal/armv7a/zynq7000/interrupts.c index e602e7c65..c516645a2 100644 --- a/hal/armv7a/zynq7000/interrupts.c +++ b/hal/armv7a/zynq7000/interrupts.c @@ -24,7 +24,6 @@ #define SIZE_INTERRUPTS 95 -#define SIZE_HANDLERS 4 #define SPI_FIRST_IRQID 32 #define SGI_FLT_USE_LIST 0 /* Send SGI to CPUs according to targetList */ diff --git a/hal/armv7m/stm32/interrupts.c b/hal/armv7m/stm32/interrupts.c index a25ecedb2..844b3be19 100644 --- a/hal/armv7m/stm32/interrupts.c +++ b/hal/armv7m/stm32/interrupts.c @@ -30,9 +30,6 @@ #endif -#define SIZE_HANDLERS 4 - - struct { spinlock_t spinlock; intr_handler_t *handlers[SIZE_INTERRUPTS]; diff --git a/hal/armv8m/Makefile b/hal/armv8m/Makefile index 6aa9df387..832e5612a 100644 --- a/hal/armv8m/Makefile +++ b/hal/armv8m/Makefile @@ -8,6 +8,9 @@ ifneq (, $(findstring nrf, $(TARGET_SUBFAMILY))) include hal/armv8m/nrf/Makefile CFLAGS += -Ihal/armv8m +else ifneq (, $(findstring mcx, $(TARGET_SUBFAMILY))) + include hal/armv8m/mcx/Makefile + CFLAGS += -Ihal/armv8m endif OBJS += $(addprefix $(PREFIX_O)hal/armv8m/, string.o spinlock.o cpu.o hal.o pmap.o exceptions.o _memcpy.o _memset.o) diff --git a/hal/armv8m/arch/cpu.h b/hal/armv8m/arch/cpu.h index 0ee6e52ad..2ca964119 100644 --- a/hal/armv8m/arch/cpu.h +++ b/hal/armv8m/arch/cpu.h @@ -16,11 +16,6 @@ #ifndef _HAL_ARMV8M_CPU_H_ #define _HAL_ARMV8M_CPU_H_ - -#if defined(__CPU_NRF9160) -#define CPU_NRF91 -#endif - #include "hal/types.h" #define SIZE_PAGE 0x200 diff --git a/hal/armv8m/cpu.c b/hal/armv8m/cpu.c index fa6baa209..587a446c5 100644 --- a/hal/armv8m/cpu.c +++ b/hal/armv8m/cpu.c @@ -182,8 +182,10 @@ char *hal_cpuInfo(char *info) int i; unsigned int cpuinfo; -#ifdef CPU_NRF91 +#if defined(__CPU_NRF9160) cpuinfo = _nrf91_cpuid(); +#elif defined(__CPU_MCXN94X) + cpuinfo = _mcxn94x_cpuid(); #else hal_strcpy(info, "unknown"); return info; diff --git a/hal/armv8m/mcx/Makefile b/hal/armv8m/mcx/Makefile new file mode 100644 index 000000000..46e6c2439 --- /dev/null +++ b/hal/armv8m/mcx/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for Phoenix-RTOS kernel (ARMv8 HAL) +# +# Copyright 2016-2017, 2019-2020, 2022, 2024 Phoenix Systems +# + + +ifneq (, $(findstring mcxn94x, $(TARGET_SUBFAMILY))) + include hal/armv8m/mcx/n94x/Makefile +endif + +OBJS += $(addprefix $(PREFIX_O)hal/armv8m/mcx/, _init.o interrupts.o) diff --git a/hal/armv8m/mcx/_init.S b/hal/armv8m/mcx/_init.S new file mode 100644 index 000000000..0f956814c --- /dev/null +++ b/hal/armv8m/mcx/_init.S @@ -0,0 +1,355 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Low-level initialization for Cortex-M33 (ARMv8) architecture + * + * Copyright 2012, 2016-2017, 2022, 2024 Phoenix Systems + * Author: Jacek Popko, Pawel Pisarczyk, Jakub Sejdak, Aleksander Kaminski, Damian Loewnau + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#define __ASSEMBLY__ + +#include + +#define ADDR_SCB 0xe000ed00u + +.syntax unified +.cpu cortex-m33 + +.extern syscalls +.extern syspage + + +.section .init, "x" + +.globl _init_vectors +.type _init_vectors, %object +_init_vectors: +.word _end + 1024 + 256 +.word _start + +.word _exceptions_dispatch /* NMI */ +.word _exceptions_dispatch /* HardFault */ +.word _exceptions_dispatch /* MemMgtFault */ +.word _exceptions_dispatch /* BusFault */ +.word _exceptions_dispatch /* UsageFault */ +.word _exceptions_dispatch /* SecureFault */ +.word 0 +.word 0 +.word 0 +.word _syscall_dispatch /* SVC */ +.word _exceptions_dispatch /* Debug */ +.word 0 +.word _interrupts_dispatch /* PendSV */ +.word _interrupts_dispatch /* Systick */ + +.rept 156 /* Max number of ext interrupts - last peripheral id + 1 */ +.word _interrupts_dispatch +.endr +.size _init_vectors, .-_init_vectors + + +.thumb +.thumb_func + +.globl _start +.type _start, %function + +_start: + cpsid if + isb + + /* Point to syspage */ + ldr r8, =syspage + str r9, [r8] + + /* Init vector table pointer */ + ldr r0, =0xe000ed08u + ldr r1, =_init_vectors + str r1, [r0] + isb + dmb + + /* Init MSP to a first value in _init_vectors (.bss end + 1024 + 256) */ + ldr r0, [r1] + bic r0, 7 + msr msp, r0 + isb + + bl _mcxn94x_init + + b main +.size _start, .-_start +.ltorg + +.globl _syscall_dispatch +.type _syscall_dispatch, %function +.type _syscallend, %function + +_syscall_dispatch: + mov r0, #0 + msr control, r0 + isb + + mov r0, sp + + /* Prepare context on kernel stack */ + sub sp, sp, #((14 * 4) + (8 * 4)) + str sp, [sp] + + add r1, sp, #12 + mov r12, #0 + stmia r1!, {r4-r12} + str r0, [r1], #8 /* msp */ + mov r10, r1 /* addr to store hw-saved ctx */ + + mrs r0, psp + str r0, [sp, #8] + + /* Load hardware saved registers from user stack */ + ldmia r0!, {r1-r8} + + /* Fix PC LSB not being set */ + orr r7, r7, #1 + + /* Store hardware saved registers on kernel stack */ + add r10, r10, #(5 * 4) + stm r10, {r6-r8} /* lr, pc, psr */ + + /* Copy arguments back to the user stack */ + stmdb r0!, {r1-r4} + mov r1, r0 + ldrb r0, [r7, #-3] + + /* Prepare pseudo context */ + mov r7, #0x01000000 + ldr r6, =syscalls_dispatch + ldr r5, =_syscallend + stmdb sp!, {r0-r7} /* PSR, PC, LR, R12, R3, R2, R1, R0 */ + + /* Exit handler mode to kernel thread mode */ + ldr lr,=RET_THREAD_MSP + bx lr + +_syscallend: + /* return value in r0 */ + ldr lr, [sp, #8] /* psp */ + add lr, lr, #(8 * 4) + msr psp, lr + isb + + add r10, sp, #((14 * 4) + (5 * 4)) + ldm r10, {r2,r3} /* lr, pc */ + + add lr, sp, #12 + ldmia lr!, {r4-r11} + add lr, lr, #(11 * 4) + mov sp, lr + + /* Switch stacks */ + mov r1, #3 + msr control, r1 + isb + + mov lr, r2 + mov pc, r3 +.size _syscall_dispatch, .-_syscall_dispatch +.ltorg + +.globl _exceptions_dispatch +.type _exceptions_dispatch, %function + +_exceptions_dispatch: + cpsid if + isb + + mrs r0, psp + stmdb sp!, {r0, r4-r11, lr} + + mrs r0, ipsr + mov r1, sp + + b exceptions_dispatch +.size _exceptions_dispatch, .-_exceptions_dispatch +.ltorg + +.globl _interrupts_dispatch +.type _interrupts_dispatch, %function +_interrupts_dispatch: + mov r0, #0 + msr control, r0 + isb + + mov r0, sp + tst lr, #(1 << 2) + it ne + subne sp, sp, #(8 * 4) /* space for hw-saved ctx */ + str r0, [sp, #-8]! + + mrs r0, ipsr + mrs r3, psp + sub r1, sp, #48 + stmdb sp!, {r1-r11, lr} + + /* if we came from userspace, copy hw-saved regs to kstack + * in case of signal handling + */ + + beq _intd0 /* tst lr, #(1 << 2) */ + + /* psp in r3 - load hw-saved regs */ + ldm r3, {r4-r11} + add r12, sp, #(14 * 4) + stm r12, {r4-r11} + +_intd0: + bl interrupts_dispatch + ldr r1, [sp] + mov sp, r1 + isb +_intd1: + ldr lr, [sp, #(11 * 4)] + + tst lr, #(1 << 2) + beq _intd2 + + /* userspace return - restore registers in case of signal handling */ + ldr r3, [sp, #(2 * 4)] /* psp */ + add r1, sp, #(14 * 4) + ldm r1, {r4-r11} + stm r3, {r4-r11} + +_intd2: + ldmia sp!, {r1-r11} + ldr r0, [sp, #4] + mov sp, r0 + + msr psp, r3 + isb + + /* Check if we're returning to userspace */ + and r1, lr, #4 + ror r1, r1, #2 + msr control, r1 + isb + dsb + + bx lr +.size _interrupts_dispatch, .-_interrupts_dispatch +.ltorg + + +.globl _hal_invokePendSV +.type _hal_invokePendSV, %function +_hal_invokePendSV: + mov r1, #(1 << 28) + ldr r2, =ADDR_SCB + str r1, [r2, #4] + bx lr +.size _hal_invokePendSV, .-_hal_invokePendSV +.ltorg + + +.globl hal_cpuReschedule /* int hal_cpuReschedule(struct _spinlock_t *spinlock, spinlock_ctx_t *scp); */ +.type hal_cpuReschedule, %function +hal_cpuReschedule: + push {r4, lr} + movs r4, r0 + bl _hal_invokePendSV + cbz r4, .Lhal_cpuReschedule0 + adds r4, r4, #12 +.Lspinlock: + ldrexb r2, [r4] + adds r2, r2, #1 + dmb + strexb r3, r2, [r4] + cmp r3, #0 + bne .Lspinlock +.Lhal_cpuReschedule0: + pop {r4, lr} + movs r0, #0 /* default return value */ + cpsie if + isb + dmb + bx lr +.size hal_cpuReschedule, .-hal_cpuReschedule +.ltorg + + +.globl hal_jmp /* void hal_jmp(void *f, void *kstack, void *ustack, int kargc, const arg_t *kargs) */ +.type hal_jmp, %function +hal_jmp: + cpsid if + isb + + push {r0-r3} + pop {r4-r8} /* kargs has been passed on the stack */ + + cmp r6, #NULL + bne hal_jmp_user + + mov sp, r5 + isb + subs r7, #1 + bmi 1f + ldr r0, [r8] + subs r7, #1 + bmi 1f + ldr r1, [r8, #4] + subs r7, #1 + bmi 1f + ldr r2, [r8, #8] + subs r7, #1 + bmi 1f + ldr r3, [r8, #12] +1: + cpsie if + isb + dmb + bx r4 + +hal_jmp_user: + cpsid if + isb + msr msp, r5 + isb + msr psp, r6 + cpsie if + isb + mov r5, USERCONTROL + msr control, r5 + isb + dmb + bx r4 + +.size hal_jmp, .-hal_jmp +.ltorg + +.globl hal_exceptionJump /* void hal_exceptionJump(unsigned int n, exc_context_t *ctx, void (*handler)(unsigned int, exc_context_t *)) */ +.type hal_exceptionJump, %function +hal_exceptionJump: + push {r4-r11, lr} + ldr r7, =0x01000000 + mov r6, r2 + ldr r5, =1f + orr r5, #1 + push {r0-r7} + + mov lr, #0 + msr control, lr + mov lr, 0xfffffff9 + cpsie if + dsb + bx lr + +1: pop {r4-r11, lr} + bx lr + +.size hal_exceptionJump, .-hal_exceptionJump +.ltorg diff --git a/hal/armv8m/mcx/interrupts.c b/hal/armv8m/mcx/interrupts.c new file mode 100644 index 000000000..6a5a2a7d1 --- /dev/null +++ b/hal/armv8m/mcx/interrupts.c @@ -0,0 +1,197 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Interrupt handling + * + * Copyright 2017, 2020, 2022, 2024 Phoenix Systems + * Author: Pawel Pisarczyk, Hubert Buczynski, Damian Loewnau, Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "hal/interrupts.h" +#include "hal/spinlock.h" +#include "hal/cpu.h" +#include "hal/list.h" +#include "hal/armv8m/armv8m.h" +#include "hal/armv8m/mcx/n94x/mcxn94x.h" + +#include "proc/userintr.h" + +#include "config.h" + +static struct { + volatile u32 *nvic; + volatile u32 *scb; + spinlock_t spinlock; + intr_handler_t *handlers[SIZE_INTERRUPTS]; + unsigned int counters[SIZE_INTERRUPTS]; +} interrupts; + + +/* clang-format off */ +enum { nvic_iser = 0, nvic_icer = 32, nvic_ispr = 64, nvic_icpr = 96, nvic_iabr = 128, + nvic_ip = 192 }; +/* clang-format on */ + + +extern int threads_schedule(unsigned int n, cpu_context_t *context, void *arg); + + +void _interrupts_nvicSetIRQ(s8 irqn, u8 state) +{ + volatile u32 *ptr = interrupts.nvic + ((u8)irqn >> 5) + ((state != 0) ? nvic_iser : nvic_icer); + *ptr = 1u << (irqn & 0x1f); + + hal_cpuDataSyncBarrier(); + hal_cpuInstrBarrier(); +} + + +void _interrupts_nvicSetPriority(s8 irqn, u32 priority) +{ + volatile u32 *ptr; + + ptr = ((u32 *)(interrupts.nvic + nvic_ip)) + (irqn / 4); + + /* We set only group priority field */ + *ptr = (priority << (8 * (irqn % 4) + 4)); +} + + +void _interrupts_nvicSetPending(s8 irqn) +{ + volatile u32 *ptr = interrupts.nvic + ((u8)irqn >> 5) + nvic_ispr; + + *ptr = 1u << (irqn & 0x1f); + + hal_cpuDataSyncBarrier(); +} + + +void _interrupts_nvicSystemReset(void) +{ + *(interrupts.scb + scb_aircr) = ((0x5fau << 16) | (*(interrupts.scb + scb_aircr) & (0x700u)) | (1u << 2)); + + hal_cpuDataSyncBarrier(); + + for (;;) { + hal_cpuHalt(); + } +} + + +void interrupts_dispatch(unsigned int n, cpu_context_t *ctx) +{ + intr_handler_t *h; + int reschedule = 0; + spinlock_ctx_t sc; + + if (n >= SIZE_INTERRUPTS) { + return; + } + + hal_spinlockSet(&interrupts.spinlock, &sc); + + interrupts.counters[n]++; + + h = interrupts.handlers[n]; + if (h != NULL) { + do { + hal_cpuSetGot(h->got); + if (h->f(n, ctx, h->data) != 0) { + reschedule = 1; + } + h = h->next; + } while (h != interrupts.handlers[n]); + } + + hal_spinlockClear(&interrupts.spinlock, &sc); + + if (reschedule != 0) { + threads_schedule(n, ctx, NULL); + } +} + + +int hal_interruptsSetHandler(intr_handler_t *h) +{ + spinlock_ctx_t sc; + + if (h == NULL || h->f == NULL || h->n >= SIZE_INTERRUPTS) { + return -1; + } + + hal_spinlockSet(&interrupts.spinlock, &sc); + h->got = hal_cpuGetGot(); + + /* adding to interrupt handlers tree */ + HAL_LIST_ADD(&interrupts.handlers[h->n], h); + + if (h->n >= 0x10) { + _interrupts_nvicSetPriority(h->n - 0x10, 1); + _interrupts_nvicSetIRQ(h->n - 0x10, 1); + } + hal_spinlockClear(&interrupts.spinlock, &sc); + + return 0; +} + + +int hal_interruptsDeleteHandler(intr_handler_t *h) +{ + spinlock_ctx_t sc; + + if (h == NULL || h->f == NULL || h->n >= SIZE_INTERRUPTS) { + return -1; + } + + hal_spinlockSet(&interrupts.spinlock, &sc); + HAL_LIST_REMOVE(&interrupts.handlers[h->n], h); + + if (h->n >= 0x10 && interrupts.handlers[h->n] == NULL) { + _interrupts_nvicSetIRQ(h->n - 0x10, 0); + } + + hal_spinlockClear(&interrupts.spinlock, &sc); + + return 0; +} + + +char *hal_interruptsFeatures(char *features, unsigned int len) +{ + hal_strncpy(features, "Using NVIC interrupt controller", len); + features[len - 1] = 0; + + return features; +} + + +__attribute__((section(".init"))) void _hal_interruptsInit(void) +{ + unsigned int n; + + for (n = 0; n < SIZE_INTERRUPTS; ++n) { + interrupts.handlers[n] = NULL; + interrupts.counters[n] = 0; + } + + interrupts.nvic = (void *)0xe000e100; + interrupts.scb = (void *)0xe000e000; + + hal_spinlockCreate(&interrupts.spinlock, "interrupts.spinlock"); + + _mcxn94x_scbSetPriority(SYSTICK_IRQ, 1); + _mcxn94x_scbSetPriority(PENDSV_IRQ, 1); + _mcxn94x_scbSetPriority(SVC_IRQ, 0); + + /* Set no subprorities in Interrupt Group Priority */ + _mcxn94x_scbSetPriorityGrouping(3); + + return; +} diff --git a/hal/armv8m/mcx/n94x/Makefile b/hal/armv8m/mcx/n94x/Makefile new file mode 100644 index 000000000..d98838de5 --- /dev/null +++ b/hal/armv8m/mcx/n94x/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for Phoenix-RTOS kernel (ARMv8 HAL) +# +# Copyright 2016-2017, 2019-2020, 2022, 2024 Phoenix Systems +# + +CFLAGS += -Ihal/armv8m/mcx/n94x + +OBJS += $(addprefix $(PREFIX_O)hal/armv8m/mcx/n94x/, mcxn94x.o console.o timer.o) diff --git a/hal/armv8m/mcx/n94x/config.h b/hal/armv8m/mcx/n94x/config.h new file mode 100644 index 000000000..b1ea9a0bc --- /dev/null +++ b/hal/armv8m/mcx/n94x/config.h @@ -0,0 +1,29 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Configuration file for MCXN94x + * + * Copyright 2021, 2022, 2024 Phoenix Systems + * Author: Hubert Buczynski, Damian Loewnau, Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _HAL_CONFIG_H_ +#define _HAL_CONFIG_H_ + +#define SIZE_INTERRUPTS (171 + 16) + +#ifndef __ASSEMBLY__ + +#include "include/arch/armv8m/mcx/syspage.h" +#include "mcxn94x.h" + +#define HAL_NAME_PLATFORM "MCX N94x " +#endif + +#endif diff --git a/hal/armv8m/mcx/n94x/console.c b/hal/armv8m/mcx/n94x/console.c new file mode 100644 index 000000000..01aceaa5b --- /dev/null +++ b/hal/armv8m/mcx/n94x/console.c @@ -0,0 +1,138 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * HAL console (MCXN94x UART) + * + * Copyright 2024 Phoenix Systems + * Author: Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "mcxn94x.h" + +#include "hal/console.h" +#include "hal/cpu.h" +#include "hal/string.h" +#include "hal/spinlock.h" +#include "hal/armv8m/armv8m.h" +#include + + +/* clang-format off */ +enum { uart_verid = 0, uart_param, uart_global, uart_pincfg, uart_baud, + uart_stat, uart_ctrl, uart_data, uart_match, uart_modir, uart_fifo, + uart_water, uart_dataro, uart_mcr = 16, uart_msr, uart_reir, uart_teir, + uart_hdcr, uart_tocr = 22, uart_tosr, uart_timeoutn, uart_tcbrn = 128, + uart_tdbrn = 256 }; +/* clang-format on */ + + +static struct { + volatile u32 *uart; +} console_common; + + +static void _hal_consolePrint(const char *s) +{ + while (*s) { + hal_consolePutch(*(s++)); + } +} + + +void hal_consolePrint(int attr, const char *s) +{ + if (attr == ATTR_BOLD) { + _hal_consolePrint(CONSOLE_BOLD); + } + else if (attr != ATTR_USER) { + _hal_consolePrint(CONSOLE_CYAN); + } + + _hal_consolePrint(s); + _hal_consolePrint(CONSOLE_NORMAL); +} + + +void hal_consolePutch(char c) +{ + while ((*(console_common.uart + uart_stat) & (1 << 23)) == 0) { + } + + *(console_common.uart + uart_data) = c; +} + + +void _hal_consoleInit(void) +{ + u32 t; + static const struct { + volatile u32 *base; + int tx; + int rx; + int txalt; + int rxalt; + } info[10] = { + { .base = FLEXCOMM0_BASE, .tx = UART0_TX_PIN, .rx = UART0_RX_PIN, .txalt = UART0_TX_ALT, .rxalt = UART0_RX_ALT }, + { .base = FLEXCOMM1_BASE, .tx = UART1_TX_PIN, .rx = UART1_RX_PIN, .txalt = UART1_TX_ALT, .rxalt = UART1_RX_ALT }, + { .base = FLEXCOMM2_BASE, .tx = UART2_TX_PIN, .rx = UART2_RX_PIN, .txalt = UART2_TX_ALT, .rxalt = UART2_RX_ALT }, + { .base = FLEXCOMM3_BASE, .tx = UART3_TX_PIN, .rx = UART3_RX_PIN, .txalt = UART3_TX_ALT, .rxalt = UART3_RX_ALT }, + { .base = FLEXCOMM4_BASE, .tx = UART4_TX_PIN, .rx = UART4_RX_PIN, .txalt = UART4_TX_ALT, .rxalt = UART4_RX_ALT }, + { .base = FLEXCOMM5_BASE, .tx = UART5_TX_PIN, .rx = UART5_RX_PIN, .txalt = UART5_TX_ALT, .rxalt = UART5_RX_ALT }, + { .base = FLEXCOMM6_BASE, .tx = UART6_TX_PIN, .rx = UART6_RX_PIN, .txalt = UART6_TX_ALT, .rxalt = UART6_RX_ALT }, + { .base = FLEXCOMM7_BASE, .tx = UART7_TX_PIN, .rx = UART7_RX_PIN, .txalt = UART7_TX_ALT, .rxalt = UART7_RX_ALT }, + { .base = FLEXCOMM8_BASE, .tx = UART8_TX_PIN, .rx = UART8_RX_PIN, .txalt = UART8_TX_ALT, .rxalt = UART8_RX_ALT }, + { .base = FLEXCOMM9_BASE, .tx = UART9_TX_PIN, .rx = UART9_RX_PIN, .txalt = UART9_TX_ALT, .rxalt = UART9_RX_ALT }, + }; + static const int baud[10] = { UART0_BAUDRATE, UART1_BAUDRATE, UART2_BAUDRATE, UART3_BAUDRATE, UART4_BAUDRATE, + UART5_BAUDRATE, UART6_BAUDRATE, UART7_BAUDRATE, UART8_BAUDRATE, UART9_BAUDRATE }; + + console_common.uart = info[UART_CONSOLE].base; + + /* Configure RX and TX pins */ + _mcxn94x_portPinConfig(info[UART_CONSOLE].rx, info[UART_CONSOLE].rxalt, MCX_PIN_SLOW | MCX_PIN_WEAK | MCX_PIN_PULLUP_WEAK | MCX_PIN_INPUT_BUFFER_ENABLE); + _mcxn94x_portPinConfig(info[UART_CONSOLE].tx, info[UART_CONSOLE].txalt, MCX_PIN_SLOW | MCX_PIN_WEAK); + + /* Reset all internal logic and registers, except the Global Register */ + *(console_common.uart + uart_global) |= 1 << 1; + hal_cpuDataMemoryBarrier(); + *(console_common.uart + uart_global) &= ~(1 << 1); + hal_cpuDataMemoryBarrier(); + + /* Set baud rate */ + t = *(console_common.uart + uart_baud) & ~((0xf << 24) | (1 << 17) | 0x1fff); + + /* For baud rate calculation, default UART_CLK=12MHz assumed */ + switch (baud[UART_CONSOLE]) { + case 9600: t |= 0x03020138; break; + case 19200: t |= 0x0302009c; break; + case 38400: t |= 0x0302004e; break; + case 57600: t |= 0x03020034; break; + case 230400: t |= 0x0302000d; break; + default: t |= 0x0302001a; break; /* 115200 */ + } + *(console_common.uart + uart_baud) = t; + + /* Set 8 bit and no parity mode */ + *(console_common.uart + uart_ctrl) &= ~0x117; + + /* One stop bit */ + *(console_common.uart + uart_baud) &= ~(1 << 13); + + *(console_common.uart + uart_water) = 0; + + /* Enable FIFO */ + *(console_common.uart + uart_fifo) |= (1 << 7) | (1 << 3); + *(console_common.uart + uart_fifo) |= 0x3 << 14; + + /* Clear all status flags */ + *(console_common.uart + uart_stat) |= 0xc01fc000; + + /* Enable TX and RX */ + *(console_common.uart + uart_ctrl) |= (1 << 19) | (1 << 18); +} diff --git a/hal/armv8m/mcx/n94x/mcxn94x.c b/hal/armv8m/mcx/n94x/mcxn94x.c new file mode 100644 index 000000000..51630e802 --- /dev/null +++ b/hal/armv8m/mcx/n94x/mcxn94x.c @@ -0,0 +1,663 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * MCXN94x basic peripherals control functions + * + * Copyright 2024 Phoenix Systems + * Author: Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "mcxn94x.h" + +#include "hal/cpu.h" +#include "hal/armv8m/armv8m.h" +#include "include/errno.h" + + +extern void _interrupts_nvicSystemReset(void); + + +/* clang-format off */ +enum { + syscon_ahbmatprio = 4, syscon_cpu0stckcal = 14, syscon_cpu0nstckcal, syscon_cpu1stckcal, + syscon_nmisrc = 18, + syscon_presetctrl0 = 64, syscon_presetctrl1, syscon_presetctrl2, syscon_presetctrl3, + syscon_presetctrlset0 = 72, syscon_presetctrlset1, syscon_presetctrlset2, syscon_presetctrlset3, + syscon_presetctrlcrl0 = 80, syscon_presetctrlcrl1, syscon_presetctrlcrl2, syscon_presetctrlcrl3, + syscon_ahbclkctrl0 = 128, syscon_ahbclkctrl1, syscon_ahbclkctrl2, syscon_ahbclkctrl3, + syscon_ahbclkctrlset0 = 136, syscon_ahbclkctrlset1, syscon_ahbclkctrlset2, syscon_ahbclkctrlset3, + syscon_ahbclkctrlclr0 = 144, syscon_ahbclkctrlclr1, syscon_ahbclkctrlclr2, syscon_ahbclkctrlclr3, + syscon_systickclksel0 = 152, syscon_systickclksel1, syscon_tracesel, + syscon_ctimer0clksel, syscon_ctimer1clksel, syscon_ctimer2clksel, syscon_ctimer3clksel, + syscon_ctimer4clksel, syscon_clkoutset = 162, syscon_adc0clksel = 169, syscon_usb0clksel, + syscon_fc0clksel = 172, syscon_fc1clksel, syscon_fc2clksel, syscon_fc3clksel, syscon_fc4clksel, + syscon_fc5clksel, syscon_fc6clksel, syscon_fc7clksel, syscon_fc8clksel, syscon_fc9clksel, + syscon_sctclksel = 188, syscon_systickclkdiv0 = 192, syscon_systickclkdiv1, syscon_traceclkdiv, + syscon_tsiclksel = 212, syscon_sincfiltclksel = 216, syscon_slowclkdiv = 222, syscon_tsiclkdiv, + syscon_ahbclkdiv, syscon_clkoutdiv, syscon_frohfdiv, syscon_wdt0clkdiv, syscon_adc0clkdiv = 229, + syscon_usb0clkdiv, syscon_sctclkdiv = 237, syscon_pllclkdiv = 241, syscon_ctimer0clkdiv = 244, + syscon_ctimer1clkdiv, syscon_ctimer2clkdiv, syscon_ctimer3clkdiv, syscon_ctimer4clkdiv, + syscon_pll1clk0div, syscon_pll1clk1div, syscon_clkunlock, syscon_nvmctrl, syscon_romcr, + syscon_smartdmaint = 261, syscon_adc1clksel = 281, syscon_adc1clkdiv, syscon_dac0clksel = 292, + syscon_dac0clkdiv, syscon_dac1clksel, syscon_dac1clkdiv, syscon_dac2clksel, syscon_dac2clkdiv, + syscon_flexspiclksel, syscon_flexspiclkdiv, syscon_pllclkdivsel = 331, syscon_i3c0fclksel, + syscon_i3c0fclkstcsel, syscon_i3c0fclkstcdiv, syscon_i3c0fclksdiv, syscon_i3c0fclkdiv, syscon_i3c0fclkssel, + syscon_micfilfclksel, syscon_micfilfclkdiv, syscon_usdhcclksel = 342, syscon_usdhcclkdiv, + syscon_flexioclksel, syscon_flexioclkdiv, syscon_flexcan0clksel = 360, syscon_flexcan0clkdiv, + syscon_flexcan1clksel, syscon_flexcan1clkdiv, syscon_enetrmiiclksel, syscon_enetrmiiclkdiv, + syscon_enetptprefclksel, syscon_enetptprefclkdiv, syscon_enetphyintfsel, syscon_enetsbdflowctrl, + syscon_ewm0clksel = 373, syscon_wdt1clksel, syscon_wdt1clkdiv, syscon_ostimerclksel, + syscon_cmp0fclksel = 380, syscon_cmp0fclkdiv, syscon_cmp0rrclksel, syscon_rrclkdiv, + syscon_cmp1fclksel, syscon_cmp1fclkdiv, syscon_cmp1rrclksel, syscon_cmp1rrclkdiv, + syscon_cmp2fclksel, syscon_cmp2fclkdiv, syscon_cmp2rrclksel, syscon_cmp2rrclkdiv, + syscon_cpuctrl = 512, syscon_cpboot, syscon_cpustat = 514, syscon_pcacctrl = 521, + syscon_flexcomm0clkdiv = 532, syscon_flexcomm1clkdiv, syscon_flexcomm2clkdiv, + syscon_flexcomm3clkdiv, syscon_flexcomm4clkdiv, syscon_flexcomm5clkdiv, syscon_flexcomm6clkdiv, + syscon_flexcomm7clkdiv, syscon_flexcomm8clkdiv, syscon_flexcomm9clkdiv, + syscon_sai0clksel = 544, syscon_sai1clksel, syscon_sai0clkdiv, syscon_sai1clkdiv, + syscon_emvsim0clksel, syscon_emvsim1clksel, syscon_emvsim0clkdiv, syscon_emvsim1clkdiv, + syscon_clockctrl = 646, syscon_i3c1fclksel = 716, syscon_i3c1fclkstcsel, syscon_i3c1fclkstcdiv, + syscon_i3c1fclksdiv, syscon_i3c1fclkdiv, syscon_i3c1fclkssel, syscon_etbstatus = 724, + syscon_etbcounterctrl, syscon_etbcounterreload, syscon_etbcountervalue, syscon_graycodelsb, + syscon_graycodemsb, syscon_binarycodelsb, syscon_binarycodemsb, syscon_autoclkgateoverride = 897, + syscon_autoclkgataoverridec = 907, syscon_pwm0subctl = 910, syscon_pwm1subctl, + syscon_ctimerglobalstarten, syscon_eccenablectrl, syscon_jtagid = 1020, syscon_devicetype, + syscon_deviceid0, syscon_dieid +}; + + +enum { + port_verid = 0, port_gpclr = 4, port_gpchr, port_config = 8, port_edfr = 16, port_edier, + port_edcr, port_calib0 = 24, port_calib1, port_pcr0 = 32, port_pcr1, port_pcr2, port_pcr3, + port_pcr4, port_pcr5, port_pcr6, port_pcr7, port_pcr8, port_pcr9, port_pcr10, port_pcr11, + port_pcr12, port_pcr13, port_pcr14, port_pcr15, port_pcr16, port_pcr17, port_pcr18, + port_pcr19, port_pcr20, port_pcr21, port_pcr22, port_pcr23, port_pcr24, port_pcr25, + port_pcr26, port_pcr27, port_pcr28, port_pcr29, port_pcr30, port_pcr31 +}; + + +enum { + inputmux_sct0inmux0 = 0, inputmux_sct0inmux1, inputmux_sct0inmux2, inputmux_sct0inmux3, + inputmux_sct0inmux4, inputmux_sct0inmux5, inputmux_sct0inmux6, inputmux_sct0inmux7, + inputmux_ctimer0cap0, inputmux_ctimer0cap1, inputmux_ctimer0cap2, inputmux_ctimer0cap3, + inputmux_timer0trig, inputmux_ctimer1cap0 = 16, inputmux_ctimer1cap1, inputmux_ctimer1cap2, + inputmux_ctimer1cap3, inputmux_timer1trig, inputmux_ctimer2cap0 = 24, inputmux_ctimer2cap1, + inputmux_ctimer2cap2, inputmux_ctimer2cap3, inputmux_timer2trig, inputmux_smartdmaarchbinmux0 = 40, + inputmux_smartdmaarchbinmux1, inputmux_smartdmaarchbinmux2, inputmux_smartdmaarchbinmux3, + inputmux_smartdmaarchbinmux4, inputmux_smartdmaarchbinmux5, inputmux_smartdmaarchbinmux6, + inputmux_smartdmaarchbinmux7, inputmux_pintsel0, inputmux_pintsel1, inputmux_pintsel2, + inputmux_pintsel3, inputmux_pintsel4, inputmux_pintsel5, inputmux_pintsel6, inputmux_pintsel7, + inputmux_freqmesref = 96, inputmux_freqmeastar, inputmux_ctimer3cap0 = 105, inputmux_ctimer3cap1, + inputmux_ctimer3cap2, inputmux_ctimer3cap3, inputmux_timer3trig, inputmux_ctimer4cap0 = 112, + inputmux_ctimer4cap1, inputmux_ctimer4cap2, inputmux_ctimer4cap3, inputmux_timer4trig, + inputmux_cmp0trig = 152, inputmux_adc0trig0 = 160, inputmux_adc0trig1, inputmux_adc0trig2, + inputmux_adc0trig3, inputmux_adc1trig0 = 176, inputmux_adc1trig1, inputmux_adc1trig2, + inputmux_adc1trig3, inputmux_dac0trig = 192, inputmux_dac1trig = 200, inputmux_dac2trig = 208, + inputmux_enc0trig = 216, inputmux_enc0home, inputmux_enc0index, inputmux_enc0phaseb, + inputmux_enc0phasea, inputmux_enc1trig = 224, inputmux_enc1home, inputmux_enc1index, + inputmux_enc1phaseb, inputmux_enc1phasea, inputmux_flexpwm0sm0extsync = 232, + inputmux_flexpwm0sm1extsync, inputmux_flexpwm0sm2extsync, inputmux_flexpwm0sm3extsync, + inputmux_flexpwm0sm0exta, inputmux_flexpwm0sm1exta, inputmux_flexpwm0sm2exta, + inputmux_flexpwm0sm3exta, inputmux_flexpwm0extforce, inputmux_flexpwm0fault0, + inputmux_flexpwm0fault1, inputmux_flexpwm0fault2, inputmux_flexpwm0fault3, + inputmux_flexpwm1sm0extsync = 248, inputmux_flexpwm1sm1extsync, inputmux_flexpwm1sm2extsync, + inputmux_flexpwm1sm3extsync, inputmux_flexpwm1sm0exta, inputmux_flexpwm1sm1exta, + inputmux_flexpwm1sm2exta, inputmux_flexpwm1sm3exta, inputmux_flexpwm1extforce, + inputmux_flexpwm1fault0, inputmux_flexpwm1fault1, inputmux_flexpwm1fault2, + inputmux_flexpwm1fault3, inputmux_pwm0extclk = 264, inputmux_pwm1extclk, + inputmux_evtgtrig0 = 272, inputmux_evtgtrig1, inputmux_evtgtrig2, inputmux_evtgtrig3, + inputmux_evtgtrig4, inputmux_evtgtrig5, inputmux_evtgtrig6, inputmux_evtgtrig7, + inputmux_evtgtrig8, inputmux_evtgtrig9, inputmux_evtgtrig10, inputmux_evtgtrig11, + inputmux_evtgtrig12, inputmux_evtgtrig13, inputmux_evtgtrig14, inputmux_evtgtrig15, + inputmux_usbfstrig, inputmux_tsitrig = 296, inputmux_exttrig0 = 304, inputmux_exttrig1, + inputmux_exttrig2, inputmux_exttrig3, inputmux_exttrig4, inputmux_exttrig5, inputmux_exttrig6, + inputmux_exttrig7, inputmux_cmp1trig = 312, inputmux_cmp2trig = 320, + inputmux_sincfilterch0 = 328, inputmux_sincfilterch1, inputmux_sincfilterch2, + inputmux_sincfilterch3, inputmux_sincfilterch4, inputmux_opamp0trig = 352, + inputmux_opamp1trig, inputmux_opamp2trig, inputmux_flexcomm0trig = 360, + inputmux_flexcomm1trig = 368, inputmux_flexcomm2trig = 376, inputmux_flexcomm3trig = 384, + inputmux_flexcomm4trig = 392, inputmux_flexcomm5trig = 400, inputmux_flexcomm6trig = 408, + inputmux_flexcomm7trig = 416, inputmux_flexcomm8trig = 424, inputmux_flexcomm9trig = 436, + inputmux_flexiotrig0 = 440, inputmux_flexiotrig1, inputmux_flexiotrig2, inputmux_flexiotrig3, + inputmux_flexiotrig4, inputmux_flexiotrig5, inputmux_flexiotrig6, inputmux_flexiotrig7, + inputmux_dma0reqenable0 = 448, inputmux_dma0reqenable0set, inputmux_dma0reqenable0clr, + inputmux_dma0reqenable0tog, inputmux_dma0reqenable1, inputmux_dma0reqenable1set, + inputmux_dma0reqenable1clr, inputmux_dma0reqenable1tog, inputmux_dma0reqenable2, + inputmux_dma0reqenable2set, inputmux_dma0reqenable2clr,inputmux_dma0reqenable2tog, + inputmux_dma0reqenable3, inputmux_dma0reqenable3set, inputmux_dma0reqenable3clr, + inputmux_dma1reqenable0 = 480, inputmux_dma1reqenable0set, inputmux_dma1reqenable0clr, + inputmux_dma1reqenable0tog, inputmux_dma1reqenable1, inputmux_dma1reqenable1set, + inputmux_dma1reqenable1clr, inputmux_dma1reqenable1tog, inputmux_dma1reqenable2, + inputmux_dma1reqenable2set, inputmux_dma1reqenable2clr, inputmux_dma1reqenable2tog, + inputmux_dma1reqenable3, inputmux_dma1reqenable3set, inputmux_dma1reqenable3clr +}; +/* clang-format on */ + + +static struct { + volatile u32 *scb; + volatile u32 *syscon; + volatile u32 *port[6]; + volatile u32 *inputmux; + + spinlock_t pltctlSp; + unsigned int resetFlags; +} n94x_common; + + +int _mcxn94x_portPinConfig(int pin, int mux, int options) +{ + int port = pin / 32; + + pin %= 32; + + if (port >= (sizeof(n94x_common.port) / sizeof(*n94x_common.port))) { + return -EINVAL; + } + + *(n94x_common.port[port] + port_pcr0 + pin) = (((mux & 0xf) << 8) | (options & 0x307f)); + + return 0; +} + + +u64 _mcxn94x_sysconGray2Bin(u64 gray) +{ + u64 ret; + + *(n94x_common.syscon + syscon_graycodelsb) = gray & 0xffffffff; + *(n94x_common.syscon + syscon_graycodemsb) = gray >> 32; + hal_cpuDataMemoryBarrier(); + + ret = *(n94x_common.syscon + syscon_binarycodelsb); + ret |= ((u64)*(n94x_common.syscon + syscon_binarycodemsb)) << 32; + + return ret; +} + + +static int _mcxn94x_sysconGetRegs(int dev, volatile u32 **selr, volatile u32 **divr) +{ + if ((dev < pctl_rom) || (dev > pctl_i3c1stc)) { + return -1; + } + + *selr = NULL; + *divr = NULL; + + switch (dev) { + case pctl_flexspi: + *selr = n94x_common.syscon + syscon_flexspiclksel; + *divr = n94x_common.syscon + syscon_flexspiclkdiv; + break; + + case pctl_adc0: + *selr = n94x_common.syscon + syscon_adc0clksel; + *divr = n94x_common.syscon + syscon_adc0clkdiv; + break; + + case pctl_adc1: + *selr = n94x_common.syscon + syscon_adc1clksel; + *divr = n94x_common.syscon + syscon_adc1clkdiv; + break; + + case pctl_dac0: + *selr = n94x_common.syscon + syscon_dac0clksel; + *divr = n94x_common.syscon + syscon_dac0clkdiv; + break; + + case pctl_dac1: + *selr = n94x_common.syscon + syscon_dac1clksel; + *divr = n94x_common.syscon + syscon_dac1clkdiv; + break; + + case pctl_dac2: + *selr = n94x_common.syscon + syscon_dac2clksel; + *divr = n94x_common.syscon + syscon_dac2clkdiv; + break; + + case pctl_timer0: + *selr = n94x_common.syscon + syscon_ctimer0clksel; + *divr = n94x_common.syscon + syscon_ctimer0clkdiv; + break; + + case pctl_timer1: + *selr = n94x_common.syscon + syscon_ctimer1clksel; + *divr = n94x_common.syscon + syscon_ctimer1clkdiv; + break; + + case pctl_timer2: + *selr = n94x_common.syscon + syscon_ctimer2clksel; + *divr = n94x_common.syscon + syscon_ctimer2clkdiv; + break; + + case pctl_timer3: + *selr = n94x_common.syscon + syscon_ctimer3clksel; + *divr = n94x_common.syscon + syscon_ctimer3clkdiv; + break; + + case pctl_timer4: + *selr = n94x_common.syscon + syscon_ctimer4clksel; + *divr = n94x_common.syscon + syscon_ctimer4clkdiv; + break; + + case pctl_sct: + *selr = n94x_common.syscon + syscon_sctclksel; + *divr = n94x_common.syscon + syscon_sctclkdiv; + break; + + case pctl_ostimer: + *selr = n94x_common.syscon + syscon_ostimerclksel; + break; + + case pctl_ewm: + *selr = n94x_common.syscon + syscon_ewm0clksel; + break; + + case pctl_wwdt0: + *divr = n94x_common.syscon + syscon_wdt0clkdiv; + break; + + case pctl_wwdt1: + *selr = n94x_common.syscon + syscon_wdt1clksel; + *divr = n94x_common.syscon + syscon_wdt1clkdiv; + break; + + case pctl_usb0fs: + *selr = n94x_common.syscon + syscon_usb0clksel; + *divr = n94x_common.syscon + syscon_usb0clkdiv; + break; + + case pctl_evsim0: + *selr = n94x_common.syscon + syscon_emvsim0clksel; + *divr = n94x_common.syscon + syscon_emvsim0clkdiv; + break; + + case pctl_evsim1: + *selr = n94x_common.syscon + syscon_emvsim1clksel; + *divr = n94x_common.syscon + syscon_emvsim1clkdiv; + break; + + case pctl_cmp0: + *selr = n94x_common.syscon + syscon_cmp0fclksel; + *divr = n94x_common.syscon + syscon_cmp0fclkdiv; + break; + + case pctl_cmp1: + *selr = n94x_common.syscon + syscon_cmp1fclksel; + *divr = n94x_common.syscon + syscon_cmp1fclkdiv; + break; + + case pctl_cmp2: + *selr = n94x_common.syscon + syscon_cmp2fclksel; + *divr = n94x_common.syscon + syscon_cmp2fclkdiv; + break; + + case pctl_cmp0rr: + *selr = n94x_common.syscon + syscon_cmp0rrclksel; + break; + + case pctl_cmp1rr: + *selr = n94x_common.syscon + syscon_cmp1rrclksel; + break; + + case pctl_cmp2rr: + *selr = n94x_common.syscon + syscon_cmp2rrclksel; + break; + + case pctl_fc0: + *selr = n94x_common.syscon + syscon_fc0clksel; + *divr = n94x_common.syscon + syscon_flexcomm0clkdiv; + break; + + case pctl_fc1: + *selr = n94x_common.syscon + syscon_fc1clksel; + *divr = n94x_common.syscon + syscon_flexcomm1clkdiv; + break; + + case pctl_fc2: + *selr = n94x_common.syscon + syscon_fc2clksel; + *divr = n94x_common.syscon + syscon_flexcomm2clkdiv; + break; + + case pctl_fc3: + *selr = n94x_common.syscon + syscon_fc3clksel; + *divr = n94x_common.syscon + syscon_flexcomm3clkdiv; + break; + + case pctl_fc4: + *selr = n94x_common.syscon + syscon_fc4clksel; + *divr = n94x_common.syscon + syscon_flexcomm4clkdiv; + break; + + case pctl_fc5: + *selr = n94x_common.syscon + syscon_fc5clksel; + *divr = n94x_common.syscon + syscon_flexcomm5clkdiv; + break; + + case pctl_fc6: + *selr = n94x_common.syscon + syscon_fc6clksel; + *divr = n94x_common.syscon + syscon_flexcomm6clkdiv; + break; + + case pctl_fc7: + *selr = n94x_common.syscon + syscon_fc7clksel; + *divr = n94x_common.syscon + syscon_flexcomm7clkdiv; + break; + + case pctl_fc8: + *selr = n94x_common.syscon + syscon_fc8clksel; + *divr = n94x_common.syscon + syscon_flexcomm8clkdiv; + break; + + case pctl_fc9: + *selr = n94x_common.syscon + syscon_fc9clksel; + *divr = n94x_common.syscon + syscon_flexcomm9clkdiv; + break; + + case pctl_flexcan0: + *selr = n94x_common.syscon + syscon_flexcan0clksel; + *divr = n94x_common.syscon + syscon_flexcan0clkdiv; + break; + + case pctl_flexcan1: + *selr = n94x_common.syscon + syscon_flexcan1clksel; + *divr = n94x_common.syscon + syscon_flexcan1clkdiv; + break; + + case pctl_flexio: + *selr = n94x_common.syscon + syscon_flexioclksel; + *divr = n94x_common.syscon + syscon_flexioclkdiv; + break; + + case pctl_usdhc: + *selr = n94x_common.syscon + syscon_usdhcclksel; + *divr = n94x_common.syscon + syscon_usdhcclkdiv; + break; + + case pctl_sinc: + *selr = n94x_common.syscon + syscon_sincfiltclksel; + break; + + case pctl_i3c0: + *selr = n94x_common.syscon + syscon_i3c0fclksel; + *divr = n94x_common.syscon + syscon_i3c0fclkdiv; + break; + + case pctl_i3c1: + *selr = n94x_common.syscon + syscon_i3c1fclksel; + *divr = n94x_common.syscon + syscon_i3c1fclkdiv; + break; + + case pctl_i3c0s: + *selr = n94x_common.syscon + syscon_i3c0fclkssel; + *divr = n94x_common.syscon + syscon_i3c0fclksdiv; + break; + + case pctl_i3c1s: + *selr = n94x_common.syscon + syscon_i3c1fclkssel; + *divr = n94x_common.syscon + syscon_i3c1fclksdiv; + break; + + case pctl_i3c0stc: + *selr = n94x_common.syscon + syscon_i3c0fclkstcsel; + *divr = n94x_common.syscon + syscon_i3c0fclkstcdiv; + break; + + case pctl_i3c1stc: + *selr = n94x_common.syscon + syscon_i3c1fclkstcsel; + *divr = n94x_common.syscon + syscon_i3c1fclkstcdiv; + break; + + case pctl_sai0: + *selr = n94x_common.syscon + syscon_sai0clksel; + *divr = n94x_common.syscon + syscon_sai0clkdiv; + break; + + case pctl_sai1: + *selr = n94x_common.syscon + syscon_sai1clksel; + *divr = n94x_common.syscon + syscon_sai1clkdiv; + break; + + /* enet TODO */ + + case pctl_micfil: + *selr = n94x_common.syscon + syscon_micfilfclksel; + *divr = n94x_common.syscon + syscon_micfilfclkdiv; + break; + + case pctl_tsi: + *selr = n94x_common.syscon + syscon_tsiclksel; + *divr = n94x_common.syscon + syscon_tsiclkdiv; + break; + + default: + break; + } + + return 0; +} + + +static int _mcxn94x_sysconGetDevClk(int dev, unsigned int *sel, unsigned int *div, int *enable) +{ + volatile u32 *selr, *divr; + + if (_mcxn94x_sysconGetRegs(dev, &selr, &divr) < 0) { + return -1; + } + + if (sel != NULL) { + *sel = *selr & 0x7; + } + + if (div != NULL) { + *div = *divr & 0xff; + } + + *enable = (*(n94x_common.syscon + syscon_ahbclkctrlset0 + (dev / 32)) & 1 << (dev & 0x1f)) ? 1 : 0; + + return 0; +} + +static void _mcxn94x_sysconSetDevClkState(int dev, int enable) +{ + hal_cpuDataMemoryBarrier(); + if (enable != 0) { + /* cmp0 and cmp1 fields are "reserved", let's try to control them anyway */ + *(n94x_common.syscon + syscon_ahbclkctrlset0 + (dev / 32)) = 1 << (dev & 0x1f); + } + else { + *(n94x_common.syscon + syscon_ahbclkctrlclr0 + (dev / 32)) = 1 << (dev & 0x1f); + } + hal_cpuDataMemoryBarrier(); +} + + +int _mcxn94x_sysconSetDevClk(int dev, unsigned int sel, unsigned int div, int enable) +{ + volatile u32 *selr = NULL, *divr = NULL; + + if (_mcxn94x_sysconGetRegs(dev, &selr, &divr) < 0) { + return -1; + } + + /* Disable the clock */ + _mcxn94x_sysconSetDevClkState(dev, 0); + + if (selr != NULL) { + *selr = sel & 0x7; + } + + if (divr != NULL) { + *divr = div & 0xff; + + /* Unhalt the divider */ + *divr &= ~(1 << 30); + } + + _mcxn94x_sysconSetDevClkState(dev, enable); + + return 0; +} + + +int _mcxn94x_sysconDevReset(int dev, int state) +{ + volatile u32 *reg = n94x_common.syscon + syscon_presetctrl0; + + if ((dev < pctl_rom) || (dev > pctl_sema42)) { + return -1; + } + + /* Select relevant AHB register */ + reg += dev / 32; + + /* Need to disable the clock before the reset */ + if (state != 0) { + _mcxn94x_sysconSetDevClkState(dev, 0); + } + + if (state != 0) { + *(reg + (syscon_presetctrlset0 - syscon_presetctrl0)) = 1 << (dev & 0x1f); + } + else { + *(reg + (syscon_presetctrlcrl0 - syscon_presetctrl0)) = 1 << (dev & 0x1f); + } + hal_cpuDataMemoryBarrier(); + + return 0; +} + + +int hal_platformctl(void *ptr) +{ + platformctl_t *data = ptr; + int ret = -EINVAL; + unsigned int sel, div; + int enable; + spinlock_ctx_t sp; + + hal_spinlockSet(&n94x_common.pltctlSp, &sp); + switch (data->type) { + case pctl_reboot: + if (data->action == pctl_set) { + if (data->reboot.magic == PCTL_REBOOT_MAGIC) { + _interrupts_nvicSystemReset(); + } + } + else { + if (data->action == pctl_get) { + data->reboot.reason = n94x_common.resetFlags; + ret = 0; + } + } + break; + + case pctl_devclk: + if (data->action == pctl_set) { + ret = _mcxn94x_sysconSetDevClk(data->devClk.dev, data->devClk.sel, + data->devClk.div, data->devClk.enable); + } + else if (data->action == pctl_get) { + ret = _mcxn94x_sysconGetDevClk(data->devClk.dev, &sel, &div, &enable); + if (ret >= 0) { + data->devClk.sel = sel; + data->devClk.div = div; + data->devClk.enable = enable; + } + } + else { + ret = -EINVAL; + } + break; + + case pctl_devrst: + if (data->action != pctl_set) { + ret = -ENOSYS; + } + else { + ret = _mcxn94x_sysconDevReset(data->devRst.dev, data->devRst.state); + } + break; + + case pctl_pinConf: + if (data->action != pctl_set) { + ret = -ENOSYS; + } + else { + ret = _mcxn94x_portPinConfig(data->pinConf.pin, data->pinConf.mux, + data->pinConf.options); + } + break; + + default: + ret = -EINVAL; + break; + } + hal_spinlockClear(&n94x_common.pltctlSp, &sp); + + return ret; +} + + +void _hal_platformInit(void) +{ + hal_spinlockCreate(&n94x_common.pltctlSp, "pltctl"); +} + + +/* SCB */ + + +void _mcxn94x_scbSetPriorityGrouping(u32 group) +{ + u32 t; + + /* Get register value and clear bits to set */ + t = *(n94x_common.scb + scb_aircr) & ~0xffff0700; + + /* Set AIRCR.PRIGROUP to 3: 16 priority groups and 16 subgroups + The value is same as for armv7m4-stm32l4x6 target + Setting various priorities is not supported on Phoenix-RTOS, so it's just default value */ + *(n94x_common.scb + scb_aircr) = t | 0x5fa0000 | ((group & 7) << 8); +} + + +void _mcxn94x_scbSetPriority(s8 excpn, u32 priority) +{ + volatile u8 *ptr; + + ptr = &((u8 *)(n94x_common.scb + scb_shp1))[excpn - 4]; + + /* We set only group priority field */ + *ptr = (priority << 4) & 0xff; +} + + +unsigned int _mcxn94x_cpuid(void) +{ + return *(n94x_common.scb + scb_cpuid); +} + + +void _mcxn94x_init(void) +{ + n94x_common.scb = (void *)0xe000e000; + n94x_common.syscon = (void *)0x40000000; + n94x_common.port[0] = (void *)0x40116000; + n94x_common.port[1] = (void *)0x40117000; + n94x_common.port[2] = (void *)0x40118000; + n94x_common.port[3] = (void *)0x40119000; + n94x_common.port[4] = (void *)0x4011a000; + n94x_common.port[5] = (void *)0x40042000; + n94x_common.inputmux = (void *)0x40006000; + + /* resetFlags TODO */ +} diff --git a/hal/armv8m/mcx/n94x/mcxn94x.h b/hal/armv8m/mcx/n94x/mcxn94x.h new file mode 100644 index 000000000..8832f5a0e --- /dev/null +++ b/hal/armv8m/mcx/n94x/mcxn94x.h @@ -0,0 +1,59 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * MCXN94X basic peripherals control functions + * + * Copyright 2024 Phoenix Systems + * Author: Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _HAL_MCXN94X_H_ +#define _HAL_MCXN94X_H_ + +#include "hal/types.h" +#include "hal/pmap.h" + +#include "include/arch/armv8m/mcx/n94x/mcxn94x.h" + + +/* clang-format off */ +enum { + scb_actlr = 2, scb_cpuid = 832, scb_icsr, scb_vtor, scb_aircr, scb_scr, scb_ccr, scb_shp1, scb_shp2, + scb_shp3, scb_shcsr, scb_cfsr, scb_mmsr, scb_bfsr, scb_ufsr, scb_hfsr, scb_mmar, scb_bfar, scb_afsr +}; +/* clang-format on */ + + +extern int _mcxn94x_portPinConfig(int pin, int mux, int options); + + +extern u64 _mcxn94x_sysconGray2Bin(u64 gray); + + +extern int _mcxn94x_sysconSetDevClk(int dev, unsigned int sel, unsigned int div, int enable); + + +extern int _mcxn94x_sysconDevReset(int dev, int state); + + +extern int hal_platformctl(void *ptr); + + +extern void _hal_platformInit(void); + + +extern void _mcxn94x_scbSetPriorityGrouping(u32 group); + + +extern void _mcxn94x_scbSetPriority(s8 excpn, u32 priority); + + +extern unsigned int _mcxn94x_cpuid(void); + +#endif diff --git a/hal/armv8m/mcx/n94x/timer.c b/hal/armv8m/mcx/n94x/timer.c new file mode 100644 index 000000000..86ca38484 --- /dev/null +++ b/hal/armv8m/mcx/n94x/timer.c @@ -0,0 +1,176 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * System timer driver + * + * Copyright 2024 Phoenix Systems + * Author: Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "config.h" +#include "hal/armv8m/armv8m.h" +#include "hal/timer.h" +#include "hal/interrupts.h" +#include "hal/spinlock.h" +#include "hal/string.h" +#include "include/arch/armv8m/mcx/n94x/mcxn94x.h" + + +extern void _interrupts_nvicSetPending(s8 irqn); + + +/* clang-format off */ +enum { ostimer_evtimerl = 0, ostimer_evtimerh, ostimer_capturel, ostimer_captureh, + ostimer_matchl, ostimer_matchh, ostimer_oseventctrl = 7 }; +/* clang-format on */ + + +static struct { + volatile u32 *base; + u32 high; + u64 timerLast; + u32 interval; + spinlock_t lock; +} timer_common; + + +static u64 timer_gray2bin(u64 gray) +{ + return _mcxn94x_sysconGray2Bin(gray); +} + + +static u64 timer_bin2gray(u64 bin) +{ + return bin ^ (bin >> 1); +} + + +static time_t hal_timerCyc2Us(time_t ticks) +{ + return (ticks * 1000 * 1000) / 32768; +} + + +static time_t hal_timerUs2Cyc(time_t us) +{ + return (32768 * us + (500 * 1000)) / (1000 * 1000); +} + + +static u64 hal_timerGetCyc(void) +{ + u32 low = *(timer_common.base + ostimer_evtimerl); + u32 high = *(timer_common.base + ostimer_evtimerh) & 0x3ff; + u64 timerval; + + timerval = timer_gray2bin((u64)low | ((u64)high << 32)); + if (timerval < timer_common.timerLast) { + /* Once every ~4 years */ + timer_common.high += 1 << (42 - 32); + } + timer_common.timerLast = timerval; + + return timerval | timer_common.high; +} + + +/* Interface functions */ + + +void hal_timerSetWakeup(u32 waitUs) +{ + u64 val, valgray, inc; + spinlock_ctx_t sc; + + if (waitUs >= timer_common.interval) { + waitUs = timer_common.interval; + } + + hal_spinlockSet(&timer_common.lock, &sc); + + /* Clear IRQ flag */ + *(timer_common.base + ostimer_oseventctrl) |= 1; + hal_cpuDataMemoryBarrier(); + + /* Wait for MATCH to be write ready (should be instant) */ + while ((*(timer_common.base + ostimer_oseventctrl) & (1 << 2)) != 0) { + } + + inc = hal_timerUs2Cyc(waitUs); + val = hal_timerGetCyc() + inc; + valgray = timer_bin2gray(val); + + /* Write new MATCH value */ + *(timer_common.base + ostimer_matchl) = valgray & 0xffffffffuL; + *(timer_common.base + ostimer_matchh) = (valgray >> 32) & 0x3ff; + hal_cpuDataMemoryBarrier(); + + /* Wait for MATCH value transfer from shadow */ + while ((*(timer_common.base + ostimer_oseventctrl) & (1 << 2)) != 0) { + } + + if ((hal_timerGetCyc() >= val) && (((val >> 32) & 0x400) == 0) && + ((*(timer_common.base + ostimer_oseventctrl) & 1) == 0)) { + /* We just missed the timer value and be the interrupt won't + * be generated. Trigger the interrupt manually instead. */ + _interrupts_nvicSetPending(ostimer0_irq - 0x10); + } + + hal_spinlockClear(&timer_common.lock, &sc); +} + + +time_t hal_timerGetUs(void) +{ + time_t ret; + spinlock_ctx_t sc; + + hal_spinlockSet(&timer_common.lock, &sc); + ret = hal_timerCyc2Us(hal_timerGetCyc()); + hal_spinlockClear(&timer_common.lock, &sc); + + return ret; +} + + +int hal_timerRegister(int (*f)(unsigned int, cpu_context_t *, void *), void *data, intr_handler_t *h) +{ + h->f = f; + h->n = ostimer0_irq; + h->data = data; + + return hal_interruptsSetHandler(h); +} + + +char *hal_timerFeatures(char *features, unsigned int len) +{ + hal_strncpy(features, "Using OSTIMER", len); + features[len - 1] = '\0'; + return features; +} + + +void _hal_timerInit(u32 interval) +{ + timer_common.base = (void *)0x40049000; + timer_common.timerLast = 0; + timer_common.high = 0; + timer_common.interval = interval; + + /* Use xtal32k clock source, enable the clock, deassert reset */ + _mcxn94x_sysconSetDevClk(pctl_ostimer, 1, 0, 1); + _mcxn94x_sysconDevReset(pctl_ostimer, 0); + + /* Enable MATCH interrupt */ + *(timer_common.base + ostimer_oseventctrl) |= (1 << 1) | 1; + + hal_spinlockCreate(&timer_common.lock, "timer"); +} diff --git a/hal/armv8m/nrf/91/config.h b/hal/armv8m/nrf/91/config.h index cf379de61..473f0e49e 100644 --- a/hal/armv8m/nrf/91/config.h +++ b/hal/armv8m/nrf/91/config.h @@ -22,6 +22,9 @@ #include "include/arch/armv8m/nrf/syspage.h" #include "nrf91.h" +/* Based on INTLINESNUM value (ICTR cpu register) */ +#define SIZE_INTERRUPTS 256 + #define HAL_NAME_PLATFORM "NRF91 " #endif diff --git a/hal/armv8m/nrf/_init.S b/hal/armv8m/nrf/_init.S index c545c6e0d..19221e873 100644 --- a/hal/armv8m/nrf/_init.S +++ b/hal/armv8m/nrf/_init.S @@ -156,6 +156,7 @@ _syscallend: mov r1, #3 msr control, r1 isb + dsb mov lr, r2 mov pc, r3 @@ -333,3 +334,26 @@ hal_jmp_user: .size hal_jmp, .-hal_jmp .ltorg + +.globl hal_exceptionJump /* void hal_exceptionJump(unsigned int n, exc_context_t *ctx, void (*handler)(unsigned int, exc_context_t *)) */ +.type hal_exceptionJump, %function +hal_exceptionJump: + push {r4-r11, lr} + ldr r7, =0x01000000 + mov r6, r2 + ldr r5, =1f + orr r5, #1 + push {r0-r7} + + mov lr, #0 + msr control, lr + mov lr, 0xfffffff9 + cpsie if + dsb + bx lr + +1: pop {r4-r11, lr} + bx lr + +.size hal_exceptionJump, .-hal_exceptionJump +.ltorg \ No newline at end of file diff --git a/hal/armv8m/nrf/interrupts.c b/hal/armv8m/nrf/interrupts.c index b04fd18e8..591913894 100644 --- a/hal/armv8m/nrf/interrupts.c +++ b/hal/armv8m/nrf/interrupts.c @@ -24,15 +24,6 @@ #include "config.h" -#ifdef CPU_NRF91 -/* Based on INTLINESNUM value (ICTR cpu register) */ -#define SIZE_INTERRUPTS 256 -#endif - -/* Value based on other target architectures */ -#define SIZE_HANDLERS 4 - - static struct { volatile u32 *nvic; volatile u32 *scb; diff --git a/hal/armv8m/pmap.c b/hal/armv8m/pmap.c index 6575ba4a1..926b4e48e 100644 --- a/hal/armv8m/pmap.c +++ b/hal/armv8m/pmap.c @@ -36,6 +36,12 @@ addr_t pmap_destroy(pmap_t *pmap, int *i) } +int pmap_addMap(pmap_t *pmap, unsigned int map) +{ + return 0; +} + + void pmap_switch(pmap_t *pmap) { } @@ -59,6 +65,12 @@ addr_t pmap_resolve(pmap_t *pmap, void *vaddr) } +int pmap_isAllowed(pmap_t *pmap, const void *vaddr, size_t size) +{ + return 1; +} + + int pmap_getPage(page_t *page, addr_t *addr) { return 0; diff --git a/hal/sparcv8leon3/gaisler/irqamp.c b/hal/sparcv8leon3/gaisler/irqamp.c index 5bf7f84da..194298887 100644 --- a/hal/sparcv8leon3/gaisler/irqamp.c +++ b/hal/sparcv8leon3/gaisler/irqamp.c @@ -32,7 +32,6 @@ extern unsigned int _end; #endif #define SIZE_INTERRUPTS 32 -#define SIZE_HANDLERS 4 /* Interrupt controller */ diff --git a/hal/sparcv8leon3/gaisler/irqmp.c b/hal/sparcv8leon3/gaisler/irqmp.c index 6fa39a708..c99a006a1 100644 --- a/hal/sparcv8leon3/gaisler/irqmp.c +++ b/hal/sparcv8leon3/gaisler/irqmp.c @@ -32,7 +32,6 @@ extern unsigned int _end; #endif #define SIZE_INTERRUPTS 32 -#define SIZE_HANDLERS 4 /* Interrupt controller */ diff --git a/include/arch/armv8m/mcx/n94x/mcxn94x.h b/include/arch/armv8m/mcx/n94x/mcxn94x.h new file mode 100644 index 000000000..c28189be4 --- /dev/null +++ b/include/arch/armv8m/mcx/n94x/mcxn94x.h @@ -0,0 +1,171 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Macros and enums for MCXN94x related code + * + * Copyright 2024 Phoenix Systems + * Author: Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _PHOENIX_ARCH_MCXN94X_H_ +#define _PHOENIX_ARCH_MCXN94X_H_ + + +#define PCTL_REBOOT_MAGIC 0xaa55aa55UL + +/* clang-format off */ + +/* IRQ numbers */ +enum { + all_irq = 16, edma0_ch0_irq, edma0_ch1_irq, edma0_ch2_irq, edma0_ch3_irq, edma0_ch4_irq, + edma0_ch5_irq, edma0_ch6_irq, edma0_ch7_irq, edma0_ch8_irq, edma0_ch9_irq, edma0_ch10_irq, + edma0_ch11_irq, edma0_ch12_irq, edma0_ch13_irq, edma0_ch14_irq, edma0_ch15_irq, gpio0_0_irq, + gpio0_1_irq, gpio1_0_irq, gpio1_1_irq, gpio2_0_irq, gpio2_1_irq, gpio3_0_irq, gpio3_1_irq, + gpio4_0_irq, gpio4_1_irq, gpio5_0_irq, gpio5_1_irq, utick0_irq, mrt0_irq, ctimer0_irq, ctimer1_irq, + sct0_irq, ctimer2_irq, lp_flexcomm0_irq, lp_flexcomm1_irq, lp_flexcomm2_irq, lp_flexcomm3_irq, + lp_flexcomm4_irq, lp_flexcomm5_irq, lp_flexcomm6_irq, lp_flexcomm7_irq, lp_flexcomm8_irq, + lp_flexcomm9_irq, adc0_irq, adc1_irq, pint0_irq, micfil0_irq, /* reserved */ usbfs0_irq = 16 + 50, + usbdcd0_irq, rtc0_irq, smartdma_irq, mailbox0_irq, ctimer3_irq, ctimer4_irq, ostimer0_irq, flexspi0_irq, + sai0_irq, sai1_irq, usdhc0_irq, can0_irq, can1_irq, /* 2 reserved */ usbhs1_phy_irq = 16 + 66, usbhs1_irq, + /* secure irq */ /* reserved */ plu0_irq = 16 + 70, freqme0_irq, /* 4 secure irq */ powerquad0_irq = 16 + 76, + edma1_ch0_irq, edma1_ch1_irq, edma1_ch2_irq, edma1_ch3_irq, edma1_ch4_irq, edma1_ch5_irq, edma1_ch6_irq, + edma1_ch7_irq, edma1_ch8_irq, edma1_ch9_irq, edma1_ch10_irq, edma1_ch11_irq, edma1_ch12_irq, edma1_ch13_irq, + edma1_ch14_irq, edma1_ch15_irq, /* 2 secure irq */ i3c0_irq = 16 + 95, i3c1_irq, npu_irq, /* secure irq */ + vbat0_irq = 16 + 99, ewm0_irq, tsi0_irq, tsi1_irq, emvsim0_irq, emvsim1_irq, flexio0_irq, dac0_irq, dac1_irq, + dac2_irq, cmp0_irq, cmp1_irq, cmp2_irq, pwm0re_irq, pwm0f_irq, pwm0ccr0_irq, pwm0ccr1_irq, pwm0ccr2_irq, + pwm0ccr3_irq, pwm1re_irq, pwm1f_irq, pwm1ccr0_irq, pwm1ccr1_irq, pwm1ccr2_irq, pwm1ccr3_irq, enc0c_irq, + enc0h_irq, enc0wdg_irq, enc0idx_irq, enc1c_irq, enc1h_irq, enc1wdg_irq, enc1idx_irq, /* secure irq */ + bsp32_irq = 16 + 133, /* 2 secure irq */ erm0s_irq = 16 + 136, erm0m_irq, fmu0_irq, enet0_irq, enet0pm_irq, + enet0lp1_irq, sinc0_irq, lpmtr0_irq, lptmr1_irq, scg0_irq, spc0_irq, wuu0_irq, port_irq, etb0_irq, + /* 2 reserved */ wwdt0_irq = 16 + 152, wwdt1_irq, cmc0_irq, ct_irq +}; + +/* Pinout */ +enum { + /* Port 0 */ + pctl_pin_p0_0 = 0, pctl_pin_p0_1, pctl_pin_p0_2, pctl_pin_p0_3, pctl_pin_p0_4, pctl_pin_p0_5, + pctl_pin_p0_6, pctl_pin_p0_7, pctl_pin_p0_8, pctl_pin_p0_9, pctl_pin_p0_10, pctl_pin_p0_11, + pctl_pin_p0_12, pctl_pin_p0_13, pctl_pin_p0_14, pctl_pin_p0_15, pctl_pin_p0_16, pctl_pin_p0_17, + pctl_pin_p0_18, pctl_pin_p0_19, pctl_pin_p0_20, pctl_pin_p0_21, pctl_pin_p0_22, pctl_pin_p0_23, + pctl_pin_p0_24, pctl_pin_p0_25, pctl_pin_p0_26, pctl_pin_p0_27, pctl_pin_p0_28, pctl_pin_p0_29, + pctl_pin_p0_30, pctl_pin_p0_31, + + /* Port 1 */ + pctl_pin_p1_0 = 32, pctl_pin_p1_1, pctl_pin_p1_2, pctl_pin_p1_3, pctl_pin_p1_4, pctl_pin_p1_5, + pctl_pin_p1_6, pctl_pin_p1_7 ,pctl_pin_p1_8, pctl_pin_p1_9, pctl_pin_p1_10, pctl_pin_p1_11, + pctl_pin_p1_12, pctl_pin_p1_13, pctl_pin_p1_14, pctl_pin_p1_15, pctl_pin_p1_16, pctl_pin_p1_17, + pctl_pin_p1_18, pctl_pin_p1_19, pctl_pin_p1_20, pctl_pin_p1_21, pctl_pin_p1_22, pctl_pin_p1_23, + /* pins 24-29 missing */ pctl_pin_p1_30 = 32 + 30, pctl_pin_p1_31, + + /* Port 2 */ + pctl_pin_p2_0 = 64, pctl_pin_p2_1, pctl_pin_p2_2, pctl_pin_p2_3, pctl_pin_p2_4, pctl_pin_p2_5, + pctl_pin_p2_6, pctl_pin_p2_7, pctl_pin_p2_8, pctl_pin_p2_9, pctl_pin_p2_10, pctl_pin_p2_11, + /* pins 12-31 missing */ + + /* Port 3 */ + pctl_pin_p3_0 = 96, pctl_pin_p3_1, pctl_pin_p3_2, pctl_pin_p3_3, pctl_pin_p3_4, pctl_pin_p3_5, + pctl_pin_p3_6, pctl_pin_p3_7, pctl_pin_p3_8, pctl_pin_p3_9, pctl_pin_p3_10, pctl_pin_p3_11, + pctl_pin_p3_12, pctl_pin_p3_13, pctl_pin_p3_14, pctl_pin_p3_15, pctl_pin_p3_16, pctl_pin_p3_17, + pctl_pin_p3_18, pctl_pin_p3_19, pctl_pin_p3_20, pctl_pin_p3_21, pctl_pin_p3_22, pctl_pin_p3_23, + /* pins 24-31 missing */ + + /* Port 4 */ + pctl_pin_p4_0 = 128, pctl_pin_p4_1, pctl_pin_p4_2, pctl_pin_p4_3, pctl_pin_p4_4, pctl_pin_p4_5, + pctl_pin_p4_6, pctl_pin_p4_7, /* pins 8-11 missing */ pctl_pin_p4_12 = 128 + 12, pctl_pin_p4_13, + pctl_pin_p4_14, pctl_pin_p4_15, pctl_pin_p4_16, pctl_pin_p4_17, pctl_pin_p4_18, pctl_pin_p4_19, + pctl_pin_p4_20, pctl_pin_p4_21, pctl_pin_p4_22, pctl_pin_p4_23, /* pins 24-31 missing */ + + /* Port 5 */ + pctl_pin_p5_0 = 160, pctl_pin_p5_1, pctl_pin_p5_2, pctl_pin_p5_3, pctl_pin_p5_4, pctl_pin_p5_5, + pctl_pin_p5_6, pctl_pin_p5_7, pctl_pin_p5_8, pctl_pin_p5_9, /* pins 10-31 missing */ +}; + + +/* Pin options */ +#define MCX_PIN_INVERT (1 << 13) +#define MCX_PIN_INPUT_BUFFER_ENABLE (1 << 12) +#define MCX_PIN_SLOW (1 << 3) +#define MCX_PIN_FAST 0 +#define MCX_PIN_STRONG (1 << 6) +#define MCX_PIN_WEAK 0 +#define MCX_PIN_OPEN_DRAIN (1 << 5) +#define MCX_PIN_FILTER_ENABLE (1 << 4) +#define MCX_PIN_PULLDOWN_WEAK ((1 << 1) | (1 << 2)) +#define MCX_PIN_PULLDOWN_STRONG (1 << 1) +#define MCX_PIN_PULLUP_WEAK ((1 << 0) | (1 << 1) | (1 << 2)) +#define MCX_PIN_PULLUP_STRONG ((1 << 0) | (1 << 1)) + + +/* Peripherals */ +enum { + /* AHB0 */ + /* reserved */ pctl_rom = 1, pctl_ramb, pctl_ramc, pctl_ramd, pctl_rame, pctl_ramf, pctl_ramg, + pctl_ramh, pctl_fmu, pctl_fmc, pctl_flexspi, pctl_mux, pctl_port0, pctl_port1, pctl_port2, + pctl_port3, pctl_port4, /* reserved */ pctl_gpio0 = 19, pctl_gpio1, pctl_gpio2, pctl_gpio3, + pctl_gpio4, /* reserved */ pctl_pint = 25, pctl_dma0, pctl_crc, pctl_wwdt0, pctl_wwdt1, + /* reserved */ pctl_mailbox = 31, + + /* AHB1 */ + pctl_mrt = 32, pctl_ostimer, pctl_sct, pctl_adc0, pctl_adc1, pctl_dac0, pctl_rtc, /* reserved */ + pctl_evsim0 = 32 + 8, pctl_evsim1, pctl_utick, pctl_fc0, pctl_fc1, pctl_fc2, pctl_fc3, pctl_fc4, + pctl_fc5, pctl_fc6, pctl_fc7, pctl_fc8, pctl_fc9, pctl_micfil, pctl_timer2, /* reserved */ + pctl_usb0fsdcd = 32 + 24, pctl_usb0fs, pctl_timer0, pctl_timer1, /* 2 reserved */ + pctl_smartdma = 32 + 31, + + /* AHB2 */ + /* reserved */ pctl_dma1 = 64 + 1, pctl_enet, pctl_usdhc, pctl_flexio, pctl_sai0, pctl_sai1, + /* reserved */ pctl_freqme = 64 + 8, /* 5 reserved */ pctl_flexcan0 = 64 + 14, pctl_flexcan1, + pctl_usbhs, pctl_usbhsphy, /* reserved */ pctl_pq = 64 + 19, pctl_plulut, pctl_timer3, pctl_timer4, + /* 3 reserved */ pctl_scq = 64 + 26, /* 5 reserved */ + + /* AHB3 */ + pctl_i3c0 = 96, pctl_i3c1, pctl_sinc, pctl_coolflux, pctl_enc0, pctl_enc1, pctl_pwm0, pctl_pwm1, + pctl_evtg, /* 2 reserved */ pctl_dac1 = 96 + 11, pctl_dac2, pctl_opamp0, pctl_opamp1, pctl_opamp2, + pctl_cmp0, pctl_cmp1, pctl_cmp2, pctl_vref, pctl_coolfluxapb, pctl_npu, pctl_tsi, pctl_ewm, + pctl_eim, pctl_erm, pctl_intm, pctl_sema42, /* 4 reserved */ + + /* Misc clocks */ + pctl_cmp0rr = 128, pctl_cmp1rr, pctl_cmp2rr, + pctl_i3c0s, pctl_i3c1s, pctl_i3c0stc, pctl_i3c1stc +}; +/* clang-format off */ + + +typedef struct { + enum { pctl_set = 0, pctl_get } action; + enum { pctl_devclk = 0, pctl_devrst, pctl_pinConf, pctl_reboot } type; + + union { + struct { + unsigned int magic; + unsigned int reason; + } reboot; + + struct { + int dev; + unsigned int sel; + unsigned int div; + int enable; + } devClk; + + struct { + int dev; + int state; + } devRst; + + struct { + int pin; + int mux; + int options; + } pinConf; + }; +} __attribute__((packed)) platformctl_t; + + +#endif diff --git a/include/arch/armv8m/mcx/syspage.h b/include/arch/armv8m/mcx/syspage.h new file mode 100644 index 000000000..a21574be6 --- /dev/null +++ b/include/arch/armv8m/mcx/syspage.h @@ -0,0 +1,33 @@ + +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * HAL syspage for MCXN94x + * + * Copyright 2021, 2022, 204 Phoenix Systems + * Authors: Hubert Buczynski, Damian Loewnau, Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _PHOENIX_SYSPAGE_MCXN94X_H_ +#define _PHOENIX_SYSPAGE_MCXN94X_H_ + + +typedef struct { + struct { + unsigned int type; + unsigned int allocCnt; + struct { + unsigned int rbar; + unsigned int rlar; + } table[16] __attribute__((aligned(8))); + unsigned int map[16]; /* ((unsigned int)-1) = map is not assigned */ + } __attribute__((packed)) mpu; +} __attribute__((packed)) hal_syspage_t; + +#endif