diff --git a/LICENSE.md b/LICENSE.md index 331298c0f5..4891943d11 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -21,7 +21,7 @@ Folders containing files under different permissive license than Apache 2.0 are - [drivers](./drivers) - MIT - [TESTS/mbed_hal/trng/pithy](./TESTS/mbed_hal/trng/pithy) - BSD-3-Clause - [tools/data/rpc](./tools/data/rpc) - MIT -- [targets](./targets) - PBL, BSD-style, MIT-style, Zlib-style, Public-domain +- [targets](./targets) - PBL, BSD-style, MIT-style, Zlib-style, Public-domain, BSD-3-Clause The Python modules used by Mbed tools are used under the following licenses: diff --git a/TESTS/psa/its_ps/main.cpp b/TESTS/psa/its_ps/main.cpp index 38ab54fddb..7aab27ad64 100644 --- a/TESTS/psa/its_ps/main.cpp +++ b/TESTS/psa/its_ps/main.cpp @@ -178,8 +178,10 @@ utest::v1::status_t case_its_setup_handler(const Case *const source, const size_ Case cases[] = { Case("PSA prot internal storage - Basic", case_its_setup_handler, pits_ps_test, case_its_teardown_handler), Case("PSA prot internal storage - Write-once", case_its_setup_handler, pits_ps_write_once_test, case_its_teardown_handler), +#if COMPONENT_FLASHIAP Case("PSA protected storage - Basic", case_its_setup_handler, pits_ps_test), Case("PSA protected storage - Write-once", case_its_setup_handler, pits_ps_write_once_test) +#endif }; utest::v1::status_t greentea_test_setup(const size_t number_of_cases) diff --git a/features/storage/kvstore/conf/global/mbed_lib.json b/features/storage/kvstore/conf/global/mbed_lib.json index 2d115fa24f..9212f91f9b 100644 --- a/features/storage/kvstore/conf/global/mbed_lib.json +++ b/features/storage/kvstore/conf/global/mbed_lib.json @@ -34,6 +34,9 @@ }, "LPC55S69_S": { "storage_type": "TDB_INTERNAL" + }, + "ARM_MUSCA_A1_S": { + "storage_type": "TDB_INTERNAL" } } } diff --git a/features/storage/kvstore/conf/tdb_internal/mbed_lib.json b/features/storage/kvstore/conf/tdb_internal/mbed_lib.json index 97915a4a22..13ca7c1848 100644 --- a/features/storage/kvstore/conf/tdb_internal/mbed_lib.json +++ b/features/storage/kvstore/conf/tdb_internal/mbed_lib.json @@ -26,6 +26,10 @@ "LPC55S69_S": { "internal_size": "0x8000", "internal_base_address": "0x00028000" + }, + "ARM_MUSCA_A1_S": { + "internal_size": "0x8000", + "internal_base_address": "0x00420000" } } } diff --git a/platform/mbed_lib.json b/platform/mbed_lib.json index 9854de5918..9dfa4c8d13 100644 --- a/platform/mbed_lib.json +++ b/platform/mbed_lib.json @@ -130,6 +130,12 @@ } }, "target_overrides": { + "ARM_MUSCA_A1_NS": { + "stdio-baud-rate": 115200 + }, + "ARM_MUSCA_A1_S": { + "stdio-baud-rate": 115200 + }, "EFM32": { "stdio-baud-rate": 115200 }, diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/LICENSE b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/LICENSE new file mode 100644 index 0000000000..d4242fc347 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/LICENSE @@ -0,0 +1,2 @@ +Unless specifically indicated otherwise in a file, MUSCA_A1 files in this directory are licensed under the BSD-3-Clause license, +as can be found in: LICENSE-bsd-3-clause.txt diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/LICENSE-BSD-3-Clause b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/LICENSE-BSD-3-Clause new file mode 100644 index 0000000000..476769c1fb --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/LICENSE-BSD-3-Clause @@ -0,0 +1,26 @@ +Copyright 2019 Arm Limited and affiliates. +SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/PeripheralNames.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/PeripheralNames.h new file mode 100644 index 0000000000..98e7bec484 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/PeripheralNames.h @@ -0,0 +1,48 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_PERIPHERALNAMES_H +#define MBED_PERIPHERALNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PORTNUM_0 = 0 +} PortName; + +typedef enum { + UART_0 = 0, + UART_1 +} UARTName; + +#define STDIO_UART_TX UART1_TX +#define STDIO_UART_RX UART1_RX +#define STDIO_UART UART_1 + +#define USBTX STDIO_UART_TX +#define USBRX STDIO_UART_RX + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/PinNames.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/PinNames.h new file mode 100644 index 0000000000..b027af42ea --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/PinNames.h @@ -0,0 +1,112 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +typedef enum { + PA0 = 0, + PA1 = 1, + PA2 = 2, + PA3 = 3, + PA4 = 4, + PA5 = 5, + PA6 = 6, + PA7 = 7, + PA8 = 8, + PA9 = 9, + PA10 = 10, + PA11 = 11, + PA12 = 12, + PA13 = 13, + PA14 = 14, + PA15 = 15, + PA16 = 16, + PA17 = 17, + PA18 = 18, + PA19 = 19, + PA20 = 20, + PA21 = 21, + PA22 = 22, + PA23 = 23, + PA24 = 24, + PA25 = 25, + + /* Arduino Connector Namings */ + D0 = PA0, + D1 = PA1, + D2 = PA2, + D3 = PA3, + D4 = PA4, + D5 = PA5, + D6 = PA6, + D7 = PA7, + D8 = PA8, + D9 = PA9, + D10 = PA10, + D11 = PA11, + D12 = PA12, + D13 = PA13, + D14 = PA14, + D15 = PA15, + + /* UART pins */ + UART0_RX = PA0, /* Alternate Function - 1 */ + UART0_TX = PA1, /* Alternate Function - 1 */ + UART1_RX = PA16, + UART1_TX = PA17, + + LED1 = PA2, + LED2 = PA3, + LED3 = PA4, + + /* Not connected */ + NC = (int)0xFFFFFFFF +} PinName; + +typedef enum { + PRIMARY_FUNC = 0, + ALTERNATE_FUNC_1 = 1, + ALTERNATE_FUNC_2 = 2, + ALTERNATE_FUNC_3 = 3 +} PinFunction; + +typedef enum { + PullNone = 0, + PullUp, + PullDown, + PullDefault = PullNone +} PinMode; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_ARMC6/musca_ns.sct b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_ARMC6/musca_ns.sct new file mode 100644 index 0000000000..72a013d54b --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_ARMC6/musca_ns.sct @@ -0,0 +1,64 @@ +#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc + +/* + * Copyright (c) 2019 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../../../partition/region_defs.h" +#include "../cmsis_nvic.h" + +#if !defined(MBED_ROM_START) + #define MBED_ROM_START NS_CODE_START // 0x000a0400 +#endif + +#if !defined(MBED_ROM_SIZE) + #define MBED_ROM_SIZE NS_CODE_SIZE // 0x5f800 +#endif + +#if !defined(MBED_RAM_START) + #define MBED_RAM_START NS_DATA_START +#endif + +#if !defined(MBED_RAM_SIZE) + #define MBED_RAM_SIZE NS_DATA_SIZE +#endif + +#define VECTOR_SIZE NVIC_RAM_VECTOR_SIZE + +#if !defined(MBED_BOOT_STACK_SIZE) + #define MBED_BOOT_STACK_SIZE 0x400 +#endif + +#define RAM_FIXED_SIZE (MBED_BOOT_STACK_SIZE+VECTOR_SIZE) + +LR_CODE MBED_ROM_START MBED_ROM_SIZE { + ER_CODE MBED_ROM_START MBED_ROM_SIZE { + *.o (VECTOR +First) + .ANY (+RO) + } + + RW_IRAM1 (MBED_RAM_START+VECTOR_SIZE) (MBED_RAM_SIZE-VECTOR_SIZE) { + * (+RW) ; RW data that gets copied from Flash to SRAM + * (+ZI) ; ZI data that gets initialised to zero in SRAM + } + + ARM_LIB_HEAP AlignExpr(+0, 16) EMPTY (MBED_RAM_SIZE-RAM_FIXED_SIZE+MBED_RAM_START-AlignExpr(ImageLimit(RW_IRAM1), 16)) { + } + + ARM_LIB_STACK (MBED_RAM_START+MBED_RAM_SIZE) EMPTY -MBED_BOOT_STACK_SIZE { ; stack + } +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_ARMC6/startup_cmsdk_musca_ns.S b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_ARMC6/startup_cmsdk_musca_ns.S new file mode 100644 index 0000000000..e477a5f81b --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_ARMC6/startup_cmsdk_musca_ns.S @@ -0,0 +1,240 @@ +;/* +; * Copyright (c) 2019 ARM Limited +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; */ +; +; This file is derivative of CMSIS V5.01 startup_ARMv8MML.s +; Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75 + +;/* +;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ +;*/ + +; Vector Table Mapped to Address 0 at Reset + + AREA VECTOR, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + + IMPORT |Image$$ARM_LIB_STACK$$ZI$$Limit| + +__Vectors ;Core Interrupts + DCD |Image$$ARM_LIB_STACK$$ZI$$Limit|; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + ;SSE-200 Interrupts + DCD NS_WATCHDOG_RESET_IRQHandler ; 0: Non-Secure Watchdog Reset Request Interrupt + DCD NS_WATCHDOG_IRQHandler ; 1: Non-Secure Watchdog Interrupt + DCD S32K_TIMER_IRQHandler ; 2: S32K Timer Interrupt + DCD TIMER0_IRQHandler ; 3: CMSDK Timer 0 Interrupt + DCD TIMER1_IRQHandler ; 4: CMSDK Timer 1 Interrupt + DCD DUALTIMER_IRQHandler ; 5: CMSDK Dual Timer Interrupt + DCD MHU0_IRQHandler ; 6: Message Handling Unit 0 Interrupt + DCD MHU1_IRQHandler ; 7: Message Handling Unit 1 Interrupt + DCD CRYPTOCELL_IRQHandler ; 8: CryptoCell-312 Interrupt + DCD 0 ; 9: Reserved + DCD 0 ; 10: Reserved + DCD 0 ; 11: Reserved + DCD 0 ; 12: Reserved + DCD I_CACHE_INV_ERR_IRQHandler ; 13: Intsruction Cache Invalidation Interrupt + DCD 0 ; 14: Reserved + DCD SYS_PPU_IRQHandler ; 15: System PPU Interrupt + DCD CPU0_PPU_IRQHandler ; 16: CPU0 PPU Interrupt + DCD CPU1_PPU_IRQHandler ; 17: CPU1 PPU Interrupt + DCD CPU0_DGB_PPU_IRQHandler ; 18: CPU0 Debug PPU Interrupt + DCD CPU1_DGB_PPU_IRQHandler ; 19: CPU1 Debug PPU Interrupt + DCD CRYPTOCELL_PPU_IRQHandler ; 20: CryptoCell PPU Interrupt + DCD 0 ; 21: Reserved + DCD RAM0_PPU_IRQHandler ; 22: RAM 0 PPU Interrupt + DCD RAM1_PPU_IRQHandler ; 23: RAM 1 PPU Interrupt + DCD RAM2_PPU_IRQHandler ; 24: RAM 2 PPU Interrupt + DCD RAM3_PPU_IRQHandler ; 25: RAM 3 PPU Interrupt + DCD DEBUG_PPU_IRQHandler ; 26: Debug PPU Interrupt + DCD 0 ; 27: Reserved + DCD CPU0_CTI_IRQHandler ; 28: CPU0 CTI Interrupt + DCD CPU1_CTI_IRQHandler ; 29: CPU1 CTI Interrupt + DCD 0 ; 30: Reserved + DCD 0 ; 31: Reserved + ;Expansion Interrupts + DCD 0 ; 32: Reserved + DCD GpTimer_IRQHandler ; 33: General Purpose Timer + DCD I2C0_IRQHandler ; 34: I2C0 + DCD I2C1_IRQHandler ; 35: I2C1 + DCD I2S_IRQHandler ; 36: I2S + DCD SPI_IRQHandler ; 37: SPI + DCD QSPI_IRQHandler ; 38: QSPI + DCD UARTRX0_Handler ; 39: UART0 receive FIFO interrupt + DCD UARTTX0_Handler ; 40: UART0 transmit FIFO interrupt + DCD UART0_RxTimeout_IRQHandler ; 41: UART0 receive timeout interrupt + DCD UART0_ModemStatus_IRQHandler ; 42: UART0 modem status interrupt + DCD UART0_Error_IRQHandler ; 43: UART0 error interrupt + DCD UART0_IRQHandler ; 44: UART0 interrupt + DCD UARTRX1_Handler ; 45: UART0 receive FIFO interrupt + DCD UARTTX1_Handler ; 46: UART0 transmit FIFO interrupt + DCD UART1_RxTimeout_IRQHandler ; 47: UART0 receive timeout interrupt + DCD UART1_ModemStatus_IRQHandler ; 48: UART0 modem status interrupt + DCD UART1_Error_IRQHandler ; 49: UART0 error interrupt + DCD UART1_IRQHandler ; 50: UART0 interrupt + DCD GPIO_0_IRQHandler ; 51: GPIO 0 interrupt + DCD GPIO_1_IRQHandler ; 52: GPIO 1 interrupt + DCD GPIO_2_IRQHandler ; 53: GPIO 2 interrupt + DCD GPIO_3_IRQHandler ; 54: GPIO 3 interrupt + DCD GPIO_4_IRQHandler ; 55: GPIO 4 interrupt + DCD GPIO_5_IRQHandler ; 56: GPIO 5 interrupt + DCD GPIO_6_IRQHandler ; 57: GPIO 6 interrupt + DCD GPIO_7_IRQHandler ; 58: GPIO 7 interrupt + DCD GPIO_8_IRQHandler ; 59: GPIO 8 interrupt + DCD GPIO_9_IRQHandler ; 60: GPIO 9 interrupt + DCD GPIO_10_IRQHandler ; 61: GPIO 10 interrupt + DCD GPIO_11_IRQHandler ; 62: GPIO 11 interrupt + DCD GPIO_12_IRQHandler ; 63: GPIO 12 interrupt + DCD GPIO_13_IRQHandler ; 64: GPIO 13 interrupt + DCD GPIO_14_IRQHandler ; 65: GPIO 14 interrupt + DCD GPIO_15_IRQHandler ; 66: GPIO 15 interrupt + DCD Combined_IRQHandler ; 67: Combined interrupt + DCD PVT_IRQHandler ; 68: PVT sensor interrupt + DCD 0 ; 69: Reserved + DCD PWM_0_IRQHandler ; 70: PWM0 interrupt + DCD RTC_IRQHandler ; 71: RTC interrupt + DCD GpTimer1_IRQHandler ; 72: General Purpose Timer1 + DCD GpTimer0_IRQHandler ; 73: General Purpose Timer0 + DCD PWM_1_IRQHandler ; 74: PWM1 interrupt + DCD PWM_2_IRQHandler ; 75: PWM2 interrupt + DCD IOMUX_IRQHandler ; 76: IOMUX interrupt + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + +; Reset Handler + AREA RESET, CODE, READONLY +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP +End_Of_Main + B . + + +; Dummy Exception Handlers (infinite loops which can be modified) + MACRO + Default_Handler $handler_name +$handler_name PROC + EXPORT $handler_name [WEAK] + B . + ENDP + MEND + + Default_Handler NMI_Handler + Default_Handler HardFault_Handler + Default_Handler MemManage_Handler + Default_Handler BusFault_Handler + Default_Handler UsageFault_Handler + Default_Handler SVC_Handler + Default_Handler DebugMon_Handler + Default_Handler PendSV_Handler + Default_Handler SysTick_Handler + + Default_Handler NS_WATCHDOG_RESET_IRQHandler + Default_Handler NS_WATCHDOG_IRQHandler + Default_Handler S32K_TIMER_IRQHandler + Default_Handler TIMER0_IRQHandler + Default_Handler TIMER1_IRQHandler + Default_Handler DUALTIMER_IRQHandler + Default_Handler MHU0_IRQHandler + Default_Handler MHU1_IRQHandler + Default_Handler CRYPTOCELL_IRQHandler + Default_Handler I_CACHE_INV_ERR_IRQHandler + Default_Handler SYS_PPU_IRQHandler + Default_Handler CPU0_PPU_IRQHandler + Default_Handler CPU1_PPU_IRQHandler + Default_Handler CPU0_DGB_PPU_IRQHandler + Default_Handler CPU1_DGB_PPU_IRQHandler + Default_Handler CRYPTOCELL_PPU_IRQHandler + Default_Handler RAM0_PPU_IRQHandler + Default_Handler RAM1_PPU_IRQHandler + Default_Handler RAM2_PPU_IRQHandler + Default_Handler RAM3_PPU_IRQHandler + Default_Handler DEBUG_PPU_IRQHandler + Default_Handler CPU0_CTI_IRQHandler + Default_Handler CPU1_CTI_IRQHandler + + Default_Handler GpTimer_IRQHandler + Default_Handler I2C0_IRQHandler + Default_Handler I2C1_IRQHandler + Default_Handler I2S_IRQHandler + Default_Handler SPI_IRQHandler + Default_Handler QSPI_IRQHandler + Default_Handler UARTRX0_Handler + Default_Handler UARTTX0_Handler + Default_Handler UART0_RxTimeout_IRQHandler + Default_Handler UART0_ModemStatus_IRQHandler + Default_Handler UART0_Error_IRQHandler + Default_Handler UART0_IRQHandler + Default_Handler UARTRX1_Handler + Default_Handler UARTTX1_Handler + Default_Handler UART1_RxTimeout_IRQHandler + Default_Handler UART1_ModemStatus_IRQHandler + Default_Handler UART1_Error_IRQHandler + Default_Handler UART1_IRQHandler + Default_Handler GPIO_0_IRQHandler + Default_Handler GPIO_1_IRQHandler + Default_Handler GPIO_2_IRQHandler + Default_Handler GPIO_3_IRQHandler + Default_Handler GPIO_4_IRQHandler + Default_Handler GPIO_5_IRQHandler + Default_Handler GPIO_6_IRQHandler + Default_Handler GPIO_7_IRQHandler + Default_Handler GPIO_8_IRQHandler + Default_Handler GPIO_9_IRQHandler + Default_Handler GPIO_10_IRQHandler + Default_Handler GPIO_11_IRQHandler + Default_Handler GPIO_12_IRQHandler + Default_Handler GPIO_13_IRQHandler + Default_Handler GPIO_14_IRQHandler + Default_Handler GPIO_15_IRQHandler + Default_Handler Combined_IRQHandler + Default_Handler PVT_IRQHandler + Default_Handler PWM_0_IRQHandler + Default_Handler RTC_IRQHandler + Default_Handler GpTimer1_IRQHandler + Default_Handler GpTimer0_IRQHandler + Default_Handler PWM_1_IRQHandler + Default_Handler PWM_2_IRQHandler + Default_Handler IOMUX_IRQHandler + + ALIGN + + END diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_GCC_ARM/musca_ns.ld b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_GCC_ARM/musca_ns.ld new file mode 100644 index 0000000000..b29140c972 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_GCC_ARM/musca_ns.ld @@ -0,0 +1,212 @@ +;/* +; * Copyright (c) 2019 ARM Limited +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; * +; * +; * This file is derivative of CMSIS V5.00 gcc_arm.ld +; */ + +/* Linker script to configure memory regions. */ +/* This file will be run trough the pre-processor. */ + +#include "../../../partition/region_defs.h" +#include "../cmsis_nvic.h" + +/* Stack size is 1K for Mbed-OS */ +#if !defined(MBED_BOOT_STACK_SIZE) + #define MBED_BOOT_STACK_SIZE 0x400 +#endif + +MEMORY +{ + CODE_RAM (rx) : ORIGIN = NS_CODE_START, LENGTH = ((TOTAL_CODE_SRAM_SIZE / 2) - BL2_HEADER_SIZE) + /* Vector table is copied to RAM, so RAM address needs to be adjusted */ + RAM (rwx) : ORIGIN = NVIC_RAM_VECTOR_LIMIT, LENGTH = (NS_DATA_SIZE - NVIC_RAM_VECTOR_SIZE) +} + +__stack_size__ = MBED_BOOT_STACK_SIZE; + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a) + +ENTRY(Reset_Handler) + +SECTIONS +{ + /* Startup section is loaded to Flash and runs from Flash */ + .startup : + { + KEEP(*(.vectors)) + __Vectors_End = .; + __Vectors_Size = __Vectors_End - __Vectors; + __end__ = .; + + KEEP(*(.init)) + KEEP(*(.fini)) + + } > CODE_RAM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > CODE_RAM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > CODE_RAM + __exidx_end = .; + + /* The text section is loaded into Flash but runs from SRAM + * The load address is aligned to 8 bytes + */ + .text : ALIGN(8) + { + *(.text*) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } >CODE_RAM + . = ALIGN(8); /* This alignment is needed to make the section size 8 bytes aligned */ + + /* Create same symbols that armclang does so that in the c files + * we do not have to deal with the compiler type + */ + Image$$ER_CODE_SRAM$$Base = ADDR(.text); + Image$$ER_CODE_SRAM$$Limit = .; + Image$$ER_CODE_SRAM$$Length = Image$$ER_CODE_SRAM$$Limit - Image$$ER_CODE_SRAM$$Base; + Load$$ER_CODE_SRAM$$Base = LOADADDR(.text); + Load$$ER_CODE_SRAM$$Length = Image$$ER_CODE_SRAM$$Length; + Load$$ER_CODE_SRAM$$Limit = Load$$ER_CODE_SRAM$$Base + Load$$ER_CODE_SRAM$$Length; + + /* To copy multiple ROM to RAM sections, + * define etext2/data2_start/data2_end and + * define __STARTUP_COPY_MULTIPLE in startup_cmsdk_musca_ns.S */ + .copy.table : + { + . = ALIGN(8); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (DEFINED(__etext2) ? __etext2 : 0) + LONG (DEFINED(__data2_start__) ? __data2_start__ : 0) + LONG (DEFINED(__data2_start__) ? __data2_end__ - __data2_start__ : 0) + __copy_table_end__ = .; + } > CODE_RAM + + /* To clear multiple BSS sections, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_cmsdk_musca_ns.S */ + .zero.table : + { + . = ALIGN(8); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (DEFINED(__bss2_start__) ? __bss2_start__ : 0) + LONG (DEFINED(__bss2_start__) ? __bss2_end__ - __bss2_start__ : 0) + __zero_table_end__ = .; + } > CODE_RAM + + __etext = .; + + .data : ALIGN(8) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(8); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(8); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(8); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(8); + /* All data end */ + __data_end__ = .; + + } > RAM AT>CODE_RAM + + .bss : + { + . = ALIGN(8); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(8); + __bss_end__ = .; + } > RAM + + bss_size = __bss_end__ - __bss_start__; + + .stack : + { + . = ALIGN(8); + __StackLimit = .; + KEEP(*(.stack*)) + . += __stack_size__; + __StackTop = .; + } > RAM + PROVIDE(__stack = __StackTop); + + .heap (COPY): + { + . = ALIGN(8); + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + . += (ORIGIN(RAM) + LENGTH(RAM) - .); + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + } > RAM + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackTop <= (NS_DATA_START + NS_DATA_SIZE), "RAM region overflowed") +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_GCC_ARM/startup_cmsdk_musca_ns.S b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_GCC_ARM/startup_cmsdk_musca_ns.S new file mode 100644 index 0000000000..d1eb48fd15 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_GCC_ARM/startup_cmsdk_musca_ns.S @@ -0,0 +1,355 @@ +;/* +; * Copyright (c) 2019 ARM Limited +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; * +; * +; * This file is derivative of CMSIS V5.00 startup_ARMCM33.S +; */ + + .syntax unified + .arch armv8-m.main + + .section .vectors + .align 2 + .globl __Vectors +__Vectors: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long MemManage_Handler /* MPU Fault Handler */ + .long BusFault_Handler /* Bus Fault Handler */ + .long UsageFault_Handler /* Usage Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long DebugMon_Handler /* Debug Monitor Handler */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long SysTick_Handler /* SysTick Handler */ + + /* Core interrupts */ + .long NS_WATCHDOG_RESET_IRQHandler /* 0: Non-Secure Watchdog Reset Request Interrupt */ + .long NS_WATCHDOG_IRQHandler /* 1: Non-Secure Watchdog Interrupt */ + .long S32K_TIMER_IRQHandler /* 2: S32K Timer Interrupt */ + .long TIMER0_IRQHandler /* 3: CMSDK Timer 0 Interrupt */ + .long TIMER1_IRQHandler /* 4: CMSDK Timer 1 Interrupt */ + .long DUALTIMER_IRQHandler /* 5: CMSDK Dual Timer Interrupt */ + .long MHU0_IRQHandler /* 6: Message Handling Unit 0 Interrupt */ + .long MHU1_IRQHandler /* 7: Message Handling Unit 1 Interrupt */ + .long CRYPTOCELL_IRQHandler /* 8: CryptoCell-312 Interrupt */ + .long 0 /* 9: Reserved */ + .long 0 /* 10: Reserved */ + .long 0 /* 11: Reserved */ + .long 0 /* 12: Reserved */ + .long I_CACHE_INV_ERR_IRQHandler /* 13: Intsruction Cache Invalidation Interrupt */ + .long 0 /* 14: Reserved */ + .long SYS_PPU_IRQHandler /* 15: System PPU Interrupt */ + .long CPU0_PPU_IRQHandler /* 16: CPU0 PPU Interrupt */ + .long CPU1_PPU_IRQHandler /* 17: CPU1 PPU Interrupt */ + .long CPU0_DGB_PPU_IRQHandler /* 18: CPU0 Debug PPU Interrupt */ + .long CPU1_DGB_PPU_IRQHandler /* 19: CPU1 Debug PPU Interrupt */ + .long CRYPTOCELL_PPU_IRQHandler /* 20: CryptoCell PPU Interrupt */ + .long 0 /* 21: Reserved */ + .long RAM0_PPU_IRQHandler /* 22: RAM 0 PPU Interrupt */ + .long RAM1_PPU_IRQHandler /* 23: RAM 1 PPU Interrupt */ + .long RAM2_PPU_IRQHandler /* 24: RAM 2 PPU Interrupt */ + .long RAM3_PPU_IRQHandler /* 25: RAM 3 PPU Interrupt */ + .long DEBUG_PPU_IRQHandler /* 26: Debug PPU Interrupt */ + .long 0 /* 27: Reserved */ + .long CPU0_CTI_IRQHandler /* 28: CPU0 CTI Interrupt */ + .long CPU1_CTI_IRQHandler /* 29: CPU1 CTI Interrupt */ + .long 0 /* 30: Reserved */ + .long 0 /* 31: Reserved */ + + /* External interrupts */ + .long 0 /* 32: Reserved */ + .long GpTimer_IRQHandler /* 33: General Purpose Timer */ + .long I2C0_IRQHandler /* 34: I2C0 */ + .long I2C1_IRQHandler /* 35: I2C1 */ + .long I2S_IRQHandler /* 36: I2S */ + .long SPI_IRQHandler /* 37: SPI */ + .long QSPI_IRQHandler /* 38: QSPI */ + .long UARTRX0_Handler /* 39: UART0 receive FIFO interrupt */ + .long UARTTX0_Handler /* 40: UART0 transmit FIFO interrupt */ + .long UART0_RxTimeout_IRQHandler /* 41: UART0 receive timeout interrupt */ + .long UART0_ModemStatus_IRQHandler /* 42: UART0 modem status interrupt */ + .long UART0_Error_IRQHandler /* 43: UART0 error interrupt */ + .long UART0_IRQHandler /* 44: UART0 interrupt */ + .long UARTRX1_Handler /* 45: UART0 receive FIFO interrupt */ + .long UARTTX1_Handler /* 46: UART0 transmit FIFO interrupt */ + .long UART1_RxTimeout_IRQHandler /* 47: UART0 receive timeout interrupt */ + .long UART1_ModemStatus_IRQHandler /* 48: UART0 modem status interrupt */ + .long UART1_Error_IRQHandler /* 49: UART0 error interrupt */ + .long UART1_IRQHandler /* 50: UART0 interrupt */ + .long GPIO_0_IRQHandler /* 51: GPIO 0 interrupt */ + .long GPIO_1_IRQHandler /* 52: GPIO 1 interrupt */ + .long GPIO_2_IRQHandler /* 53: GPIO 2 interrupt */ + .long GPIO_3_IRQHandler /* 54: GPIO 3 interrupt */ + .long GPIO_4_IRQHandler /* 55: GPIO 4 interrupt */ + .long GPIO_5_IRQHandler /* 56: GPIO 5 interrupt */ + .long GPIO_6_IRQHandler /* 57: GPIO 6 interrupt */ + .long GPIO_7_IRQHandler /* 58: GPIO 7 interrupt */ + .long GPIO_8_IRQHandler /* 59: GPIO 8 interrupt */ + .long GPIO_9_IRQHandler /* 60: GPIO 9 interrupt */ + .long GPIO_10_IRQHandler /* 61: GPIO 10 interrupt */ + .long GPIO_11_IRQHandler /* 62: GPIO 11 interrupt */ + .long GPIO_12_IRQHandler /* 63: GPIO 12 interrupt */ + .long GPIO_13_IRQHandler /* 64: GPIO 13 interrupt */ + .long GPIO_14_IRQHandler /* 65: GPIO 14 interrupt */ + .long GPIO_15_IRQHandler /* 66: GPIO 15 interrupt */ + .long Combined_IRQHandler /* 67: Combined interrupt */ + .long PVT_IRQHandler /* 68: PVT sensor interrupt */ + .long 0 /* 69: Reserved */ + .long PWM_0_IRQHandler /* 70: PWM0 interrupt */ + .long RTC_IRQHandler /* 71: RTC interrupt */ + .long GpTimer1_IRQHandler /* 72: General Purpose Timer0 */ + .long GpTimer0_IRQHandler /* 73: General Purpose Timer1 */ + .long PWM_1_IRQHandler /* 74: PWM1 interrupt */ + .long PWM_2_IRQHandler /* 75: PWM2 interrupt */ + .long IOMUX_IRQHandler /* 76: IOMUX interrupt */ + + .size __Vectors, . - __Vectors + + .text + .thumb + .thumb_func + .align 2 + .globl Reset_Handler + .type Reset_Handler, %function +Reset_Handler: +/* Firstly it copies data from read only memory to RAM. There are two schemes + * to copy. One can copy more than one sections. Another can only copy + * one section. The former scheme needs more instructions and read-only + * data to implement than the latter. + * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */ + +#ifdef __STARTUP_COPY_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of triplets, each of which specify: + * offset 0: LMA of start of a section to copy from + * offset 4: VMA of start of a section to copy to + * offset 8: size of the section to copy. Must be multiply of 4 + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r4, =__copy_table_start__ + ldr r5, =__copy_table_end__ + +.L_loop0: + cmp r4, r5 + bge .L_loop0_done + ldr r1, [r4] + ldr r2, [r4, #4] + ldr r3, [r4, #8] + +.L_loop0_0: + subs r3, #4 + ittt ge + ldrge r0, [r1, r3] + strge r0, [r2, r3] + bge .L_loop0_0 + + adds r4, #12 + b .L_loop0 + +.L_loop0_done: +#else +/* Single section scheme. + * + * The ranges of copy from/to are specified by following symbols + * __etext: LMA of start of the section to copy from. Usually end of text + * __data_start__: VMA of start of the section to copy to + * __data_end__: VMA of end of the section to copy to + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + +.L_loop1: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .L_loop1 +#endif /*__STARTUP_COPY_MULTIPLE */ + +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * There are two schemes too. One can clear multiple BSS sections. Another + * can only clear one section. The former is more size expensive than the + * latter. + * + * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former. + * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later. + */ +#ifdef __STARTUP_CLEAR_BSS_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of tuples specifying: + * offset 0: Start of a BSS section + * offset 4: Size of this BSS section. Must be multiply of 4 + */ + ldr r3, =__zero_table_start__ + ldr r4, =__zero_table_end__ + +.L_loop2: + cmp r3, r4 + bge .L_loop2_done + ldr r1, [r3] + ldr r2, [r3, #4] + movs r0, 0 + +.L_loop2_0: + subs r2, #4 + itt ge + strge r0, [r1, r2] + bge .L_loop2_0 + + adds r3, #8 + b .L_loop2 +.L_loop2_done: +#elif defined (__STARTUP_CLEAR_BSS) +/* Single BSS section scheme. + * + * The BSS section is specified by following symbols + * __bss_start__: start of the BSS section. + * __bss_end__: end of the BSS section. + * + * Both addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 +.L_loop3: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .L_loop3 +#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */ + +#ifndef __NO_SYSTEM_INIT + bl SystemInit +#endif + +#ifndef __START +#define __START _start +#endif + bl __START + + .pool + .size Reset_Handler, . - Reset_Handler + + +/* Macro to define default handlers. */ + .macro def_irq_handler handler_name + .align 1 + .thumb_func + .weak \handler_name + \handler_name: + b \handler_name + .endm + + def_irq_handler NMI_Handler + def_irq_handler HardFault_Handler + def_irq_handler MemManage_Handler + def_irq_handler BusFault_Handler + def_irq_handler UsageFault_Handler + def_irq_handler SVC_Handler + def_irq_handler DebugMon_Handler + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + + /* Core interrupts */ + def_irq_handler NS_WATCHDOG_RESET_IRQHandler /* 0: Non-Secure Watchdog Reset Request Interrupt */ + def_irq_handler NS_WATCHDOG_IRQHandler /* 1: Non-Secure Watchdog Interrupt */ + def_irq_handler S32K_TIMER_IRQHandler /* 2: S32K Timer Interrupt */ + def_irq_handler TIMER0_IRQHandler /* 3: CMSDK Timer 0 Interrupt */ + def_irq_handler TIMER1_IRQHandler /* 4: CMSDK Timer 1 Interrupt */ + def_irq_handler DUALTIMER_IRQHandler /* 5: CMSDK Dual Timer Interrupt */ + def_irq_handler MHU0_IRQHandler /* 6: Message Handling Unit 0 Interrupt */ + def_irq_handler MHU1_IRQHandler /* 7: Message Handling Unit 1 Interrupt */ + def_irq_handler CRYPTOCELL_IRQHandler /* 8: CryptoCell-312 Interrupt */ + def_irq_handler I_CACHE_INV_ERR_IRQHandler /* 13: Intsruction Cache Invalidation Interrupt */ + def_irq_handler SYS_PPU_IRQHandler /* 15: System PPU Interrupt */ + def_irq_handler CPU0_PPU_IRQHandler /* 16: CPU0 PPU Interrupt */ + def_irq_handler CPU1_PPU_IRQHandler /* 17: CPU1 PPU Interrupt */ + def_irq_handler CPU0_DGB_PPU_IRQHandler /* 18: CPU0 Debug PPU Interrupt */ + def_irq_handler CPU1_DGB_PPU_IRQHandler /* 19: CPU1 Debug PPU Interrupt */ + def_irq_handler CRYPTOCELL_PPU_IRQHandler /* 20: CryptoCell PPU Interrupt */ + def_irq_handler RAM0_PPU_IRQHandler /* 22: RAM 0 PPU Interrupt */ + def_irq_handler RAM1_PPU_IRQHandler /* 23: RAM 1 PPU Interrupt */ + def_irq_handler RAM2_PPU_IRQHandler /* 24: RAM 2 PPU Interrupt */ + def_irq_handler RAM3_PPU_IRQHandler /* 25: RAM 3 PPU Interrupt */ + def_irq_handler DEBUG_PPU_IRQHandler /* 26: Debug PPU Interrupt */ + def_irq_handler CPU0_CTI_IRQHandler /* 28: CPU0 CTI Interrupt */ + def_irq_handler CPU1_CTI_IRQHandler /* 29: CPU1 CTI Interrupt */ + + /* External interrupts */ + def_irq_handler GpTimer_IRQHandler /* 33: General Purpose Timer */ + def_irq_handler I2C0_IRQHandler /* 34: I2C0 */ + def_irq_handler I2C1_IRQHandler /* 35: I2C1 */ + def_irq_handler I2S_IRQHandler /* 36: I2S */ + def_irq_handler SPI_IRQHandler /* 37: SPI */ + def_irq_handler QSPI_IRQHandler /* 38: QSPI */ + def_irq_handler UARTRX0_Handler /* 39: UART0 receive FIFO interrupt */ + def_irq_handler UARTTX0_Handler /* 40: UART0 transmit FIFO interrupt */ + def_irq_handler UART0_RxTimeout_IRQHandler /* 41: UART0 receive timeout interrupt */ + def_irq_handler UART0_ModemStatus_IRQHandler /* 42: UART0 modem status interrupt */ + def_irq_handler UART0_Error_IRQHandler /* 43: UART0 error interrupt */ + def_irq_handler UART0_IRQHandler /* 44: UART0 interrupt */ + def_irq_handler UARTRX1_Handler /* 45: UART0 receive FIFO interrupt */ + def_irq_handler UARTTX1_Handler /* 46: UART0 transmit FIFO interrupt */ + def_irq_handler UART1_RxTimeout_IRQHandler /* 47: UART0 receive timeout interrupt */ + def_irq_handler UART1_ModemStatus_IRQHandler /* 48: UART0 modem status interrupt */ + def_irq_handler UART1_Error_IRQHandler /* 49: UART0 error interrupt */ + def_irq_handler UART1_IRQHandler /* 50: UART0 interrupt */ + def_irq_handler GPIO_0_IRQHandler /* 51: GPIO 0 interrupt */ + def_irq_handler GPIO_1_IRQHandler /* 52: GPIO 1 interrupt */ + def_irq_handler GPIO_2_IRQHandler /* 53: GPIO 2 interrupt */ + def_irq_handler GPIO_3_IRQHandler /* 54: GPIO 3 interrupt */ + def_irq_handler GPIO_4_IRQHandler /* 55: GPIO 4 interrupt */ + def_irq_handler GPIO_5_IRQHandler /* 56: GPIO 5 interrupt */ + def_irq_handler GPIO_6_IRQHandler /* 57: GPIO 6 interrupt */ + def_irq_handler GPIO_7_IRQHandler /* 58: GPIO 7 interrupt */ + def_irq_handler GPIO_8_IRQHandler /* 59: GPIO 8 interrupt */ + def_irq_handler GPIO_9_IRQHandler /* 60: GPIO 9 interrupt */ + def_irq_handler GPIO_10_IRQHandler /* 61: GPIO 10 interrupt */ + def_irq_handler GPIO_11_IRQHandler /* 62: GPIO 11 interrupt */ + def_irq_handler GPIO_12_IRQHandler /* 63: GPIO 12 interrupt */ + def_irq_handler GPIO_13_IRQHandler /* 64: GPIO 13 interrupt */ + def_irq_handler GPIO_14_IRQHandler /* 65: GPIO 14 interrupt */ + def_irq_handler GPIO_15_IRQHandler /* 66: GPIO 15 interrupt */ + def_irq_handler Combined_IRQHandler /* 67: Combined interrupt */ + def_irq_handler PVT_IRQHandler /* 68: PVT sensor interrupt */ + def_irq_handler PWM_0_IRQHandler /* 70: PWM0 interrupt */ + def_irq_handler RTC_IRQHandler /* 71: RTC interrupt */ + def_irq_handler GpTimer1_IRQHandler /* 72: General Purpose Timer0 */ + def_irq_handler GpTimer0_IRQHandler /* 73: General Purpose Timer1 */ + def_irq_handler PWM_1_IRQHandler /* 74: PWM1 interrupt */ + def_irq_handler PWM_2_IRQHandler /* 75: PWM2 interrupt */ + def_irq_handler IOMUX_IRQHandler /* 76: IOMUX interrupt */ + + .end diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_IAR/musca_ns.icf b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_IAR/musca_ns.icf new file mode 100644 index 0000000000..a545208c88 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_IAR/musca_ns.icf @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2019 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License) you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +define symbol NS_CODE_START = 0x000a0400; +define symbol NS_CODE_SIZE = 0x0005f800; +define symbol NS_DATA_START = 0x20011000; +define symbol NS_DATA_SIZE = 0x0000f000; + +define symbol __ram_vector_table__ = 1; + +if (!isdefinedsymbol(MBED_ROM_START)) { + define symbol MBED_ROM_START = NS_CODE_START; +} + +if (!isdefinedsymbol(MBED_APP_START)) { + define symbol MBED_APP_START = MBED_ROM_START; +} + +if (!isdefinedsymbol(MBED_ROM_SIZE)) { + define symbol MBED_ROM_SIZE = NS_CODE_SIZE; +} + +if (!isdefinedsymbol(MBED_APP_SIZE)) { + define symbol MBED_APP_SIZE = MBED_ROM_SIZE; +} + +if (!isdefinedsymbol(MBED_RAM_START)) { + define symbol MBED_RAM_START = NS_DATA_START; +} + +if (!isdefinedsymbol(MBED_RAM_SIZE)) { + define symbol MBED_RAM_SIZE = NS_DATA_SIZE; +} + +if (!isdefinedsymbol(MBED_BOOT_STACK_SIZE)) { + define symbol MBED_BOOT_STACK_SIZE = 0x400; +} + +define symbol __stack_size__ = MBED_BOOT_STACK_SIZE; +define symbol __heap_size__ = 0x4000; + +define symbol __ram_vector_table_size__ = isdefinedsymbol(__ram_vector_table__) ? 0x00000200 : 0; +define symbol __ram_vector_table_offset__ = isdefinedsymbol(__ram_vector_table__) ? 0x000001FF : 0; + +/* Stack and Heap Sizes */ +if (isdefinedsymbol(__stack_size__)) { + define symbol __size_cstack__ = __stack_size__; +} else { + define symbol __size_cstack__ = 0x0400; +} + +if (isdefinedsymbol(__heap_size__)) { + define symbol __size_heap__ = __heap_size__; +} else { + define symbol __size_heap__ = 0x0400; +} + +define symbol m_interrupts_start = MBED_APP_START; +define symbol m_interrupts_end = (MBED_APP_START + 0x16F); + +define symbol m_text_start = (MBED_APP_START + 0x170); +define symbol m_text_end = (MBED_APP_START + MBED_APP_SIZE - 1); + +define symbol m_interrupts_ram_start = MBED_RAM_START; +define symbol m_interrupts_ram_end = (MBED_RAM_START + __ram_vector_table_size__ - 1); + +define symbol m_data_start = (m_interrupts_ram_start + __ram_vector_table_size__); +define symbol m_data_end = (MBED_RAM_START + MBED_RAM_SIZE - 1); + +define exported symbol __VECTOR_TABLE = m_interrupts_start; +define exported symbol __VECTOR_RAM = isdefinedsymbol(__ram_vector_table__) ? m_interrupts_ram_start : m_interrupts_start; +define exported symbol __RAM_VECTOR_TABLE_SIZE = __ram_vector_table_size__; + +define memory mem with size = 4G; + +define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end] + | mem:[from m_text_start to m_text_end]; +define region DATA_region = mem:[from m_data_start to m_data_end-__size_cstack__]; +define region CSTACK_region = mem:[from m_data_end-__size_cstack__+1 to m_data_end]; + +define region m_interrupts_ram_region = mem:[from m_interrupts_ram_start to m_interrupts_ram_end]; + +define block CSTACK with alignment = 8, size = __size_cstack__ { }; +define block HEAP with alignment = 8, size = __size_heap__ { }; +define block RW { readwrite }; +define block ZI { zi }; + +initialize by copy { readwrite, section .textrw }; +do not initialize { section .noinit }; + +place at address mem: m_interrupts_start { readonly section .intvec }; +place in TEXT_region { readonly }; +place in DATA_region { block RW }; +place in DATA_region { block ZI }; +place in DATA_region { last block HEAP }; +place in CSTACK_region { block CSTACK }; +place in m_interrupts_ram_region { section m_interrupts_ram }; diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_IAR/startup_cmsdk_musca_ns.S b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_IAR/startup_cmsdk_musca_ns.S new file mode 100644 index 0000000000..19bb5b847e --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/TOOLCHAIN_IAR/startup_cmsdk_musca_ns.S @@ -0,0 +1,736 @@ +; mbed Microcontroller Library +; Copyright (c) 2019 ARM Limited +; SPDX-License-Identifier: Apache-2.0 +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. +; + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + PUBLIC __vector_table_0x1c + PUBLIC __Vectors + PUBLIC __Vectors_End + PUBLIC __Vectors_Size + + DATA + +__vector_table + ; Core Interrupts + DCD sfe(CSTACK) ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler +__vector_table_0x1c + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; SSE-200 Interrupts + DCD NS_WATCHDOG_RESET_IRQHandler ; 0: Non-Secure Watchdog Reset Request Interrupt + DCD NS_WATCHDOG_IRQHandler ; 1: Non-Secure Watchdog Interrupt + DCD S32K_TIMER_IRQHandler ; 2: S32K Timer Interrupt + DCD TIMER0_IRQHandler ; 3: CMSDK Timer 0 Interrupt + DCD TIMER1_IRQHandler ; 4: CMSDK Timer 1 Interrupt + DCD DUALTIMER_IRQHandler ; 5: CMSDK Dual Timer Interrupt + DCD MHU0_IRQHandler ; 6: Message Handling Unit 0 Interrupt + DCD MHU1_IRQHandler ; 7: Message Handling Unit 1 Interrupt + DCD CRYPTOCELL_IRQHandler ; 8: CryptoCell-312 Interrupt + DCD 0 ; 9: Reserved + DCD 0 ; 10: Reserved + DCD 0 ; 11: Reserved + DCD 0 ; 12: Reserved + DCD I_CACHE_INV_ERR_IRQHandler ; 13: Intsruction Cache Invalidation Interrupt + DCD 0 ; 14: Reserved + DCD SYS_PPU_IRQHandler ; 15: System PPU Interrupt + DCD CPU0_PPU_IRQHandler ; 16: CPU0 PPU Interrupt + DCD CPU1_PPU_IRQHandler ; 17: CPU1 PPU Interrupt + DCD CPU0_DGB_PPU_IRQHandler ; 18: CPU0 Debug PPU Interrupt + DCD CPU1_DGB_PPU_IRQHandler ; 19: CPU1 Debug PPU Interrupt + DCD CRYPTOCELL_PPU_IRQHandler ; 20: CryptoCell PPU Interrupt + DCD 0 ; 21: Reserved + DCD RAM0_PPU_IRQHandler ; 22: RAM 0 PPU Interrupt + DCD RAM1_PPU_IRQHandler ; 23: RAM 1 PPU Interrupt + DCD RAM2_PPU_IRQHandler ; 24: RAM 2 PPU Interrupt + DCD RAM3_PPU_IRQHandler ; 25: RAM 3 PPU Interrupt + DCD DEBUG_PPU_IRQHandler ; 26: Debug PPU Interrupt + DCD 0 ; 27: Reserved + DCD CPU0_CTI_IRQHandler ; 28: CPU0 CTI Interrupt + DCD CPU1_CTI_IRQHandler ; 29: CPU1 CTI Interrupt + DCD 0 ; 30: Reserved + DCD 0 ; 31: Reserved + ;Expansion Interrupts + DCD 0 ; 32: Reserved + DCD GpTimer_IRQHandler ; 33: General Purpose Timer + DCD I2C0_IRQHandler ; 34: I2C0 + DCD I2C1_IRQHandler ; 35: I2C1 + DCD I2S_IRQHandler ; 36: I2S + DCD SPI_IRQHandler ; 37: SPI + DCD QSPI_IRQHandler ; 38: QSPI + DCD UARTRX0_Handler ; 39: UART0 receive FIFO interrupt + DCD UARTTX0_Handler ; 40: UART0 transmit FIFO interrupt + DCD UART0_RxTimeout_IRQHandler ; 41: UART0 receive timeout interrupt + DCD UART0_ModemStatus_IRQHandler ; 42: UART0 modem status interrupt + DCD UART0_Error_IRQHandler ; 43: UART0 error interrupt + DCD UART0_IRQHandler ; 44: UART0 interrupt + DCD UARTRX1_Handler ; 45: UART0 receive FIFO interrupt + DCD UARTTX1_Handler ; 46: UART0 transmit FIFO interrupt + DCD UART1_RxTimeout_IRQHandler ; 47: UART0 receive timeout interrupt + DCD UART1_ModemStatus_IRQHandler ; 48: UART0 modem status interrupt + DCD UART1_Error_IRQHandler ; 49: UART0 error interrupt + DCD UART1_IRQHandler ; 50: UART0 interrupt + DCD GPIO_0_IRQHandler ; 51: GPIO 0 interrupt + DCD GPIO_1_IRQHandler ; 52: GPIO 1 interrupt + DCD GPIO_2_IRQHandler ; 53: GPIO 2 interrupt + DCD GPIO_3_IRQHandler ; 54: GPIO 3 interrupt + DCD GPIO_4_IRQHandler ; 55: GPIO 4 interrupt + DCD GPIO_5_IRQHandler ; 56: GPIO 5 interrupt + DCD GPIO_6_IRQHandler ; 57: GPIO 6 interrupt + DCD GPIO_7_IRQHandler ; 58: GPIO 7 interrupt + DCD GPIO_8_IRQHandler ; 59: GPIO 8 interrupt + DCD GPIO_9_IRQHandler ; 60: GPIO 9 interrupt + DCD GPIO_10_IRQHandler ; 61: GPIO 10 interrupt + DCD GPIO_11_IRQHandler ; 62: GPIO 11 interrupt + DCD GPIO_12_IRQHandler ; 63: GPIO 12 interrupt + DCD GPIO_13_IRQHandler ; 64: GPIO 13 interrupt + DCD GPIO_14_IRQHandler ; 65: GPIO 14 interrupt + DCD GPIO_15_IRQHandler ; 66: GPIO 15 interrupt + DCD Combined_IRQHandler ; 67: Combined interrupt + DCD PVT_IRQHandler ; 68: PVT sensor interrupt + DCD 0 ; 69: Reserved + DCD PWM_0_IRQHandler ; 70: PWM0 interrupt + DCD RTC_IRQHandler ; 71: RTC interrupt + DCD GpTimer1_IRQHandler ; 72: General Purpose Timer1 + DCD GpTimer0_IRQHandler ; 73: General Purpose Timer0 + DCD PWM_1_IRQHandler ; 74: PWM1 interrupt + DCD PWM_2_IRQHandler ; 75: PWM2 interrupt + DCD IOMUX_IRQHandler ; 76: IOMUX interrupt +__Vectors_End + + +__Vectors EQU __vector_table +__Vectors_Size EQU __Vectors_End - __Vectors + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:REORDER:NOROOT(2) +Reset_Handler + CPSID I ; Mask interrupts + LDR R0, =sfb(CSTACK) + MSR MSPLIM, R0 + LDR R0, =SystemInit + BLX R0 + CPSIE I ; Unmask interrupts + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +NMI_Handler + B . + + PUBWEAK HardFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +HardFault_Handler + B . + + PUBWEAK MemManage_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +MemManage_Handler + B . + + PUBWEAK BusFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +BusFault_Handler + B . + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +UsageFault_Handler + B . + + PUBWEAK SVC_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SVC_Handler + B . + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +DebugMon_Handler + B . + + PUBWEAK PendSV_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +PendSV_Handler + B . + + PUBWEAK SysTick_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SysTick_Handler + B . + + PUBWEAK NS_WATCHDOG_RESET_IRQHandler + PUBWEAK NS_WATCHDOG_RESET_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +NS_WATCHDOG_RESET_IRQHandler + LDR R0, =NS_WATCHDOG_RESET_DriverIRQHandler + BX R0 + + PUBWEAK NS_WATCHDOG_IRQHandler + PUBWEAK NS_WATCHDOG_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +NS_WATCHDOG_IRQHandler + LDR R0, =NS_WATCHDOG_DriverIRQHandler + BX R0 + + PUBWEAK S32K_TIMER_IRQHandler + PUBWEAK S32K_TIMER_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +S32K_TIMER_IRQHandler + LDR R0, =S32K_TIMER_DriverIRQHandler + BX R0 + + PUBWEAK TIMER0_IRQHandler + PUBWEAK TIMER0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +TIMER0_IRQHandler + LDR R0, =TIMER0_DriverIRQHandler + BX R0 + + PUBWEAK TIMER1_IRQHandler + PUBWEAK TIMER1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +TIMER1_IRQHandler + LDR R0, =TIMER1_DriverIRQHandler + BX R0 + + PUBWEAK DUALTIMER_IRQHandler + PUBWEAK DUALTIMER_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +DUALTIMER_IRQHandler + LDR R0, =DUALTIMER_DriverIRQHandler + BX R0 + + PUBWEAK MHU0_IRQHandler + PUBWEAK MHU0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +MHU0_IRQHandler + LDR R0, =MHU0_DriverIRQHandler + BX R0 + + PUBWEAK MHU1_IRQHandler + PUBWEAK MHU1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +MHU1_IRQHandler + LDR R0, =MHU1_DriverIRQHandler + BX R0 + + PUBWEAK CRYPTOCELL_IRQHandler + PUBWEAK CRYPTOCELL_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CRYPTOCELL_IRQHandler + LDR R0, =CRYPTOCELL_DriverIRQHandler + BX R0 + + PUBWEAK I_CACHE_INV_ERR_IRQHandler + PUBWEAK I_CACHE_INV_ERR_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +I_CACHE_INV_ERR_IRQHandler + LDR R0, =I_CACHE_INV_ERR_DriverIRQHandler + BX R0 + + PUBWEAK SYS_PPU_IRQHandler + PUBWEAK SYS_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SYS_PPU_IRQHandler + LDR R0, =SYS_PPU_DriverIRQHandler + BX R0 + + PUBWEAK CPU0_PPU_IRQHandler + PUBWEAK CPU0_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CPU0_PPU_IRQHandler + LDR R0, =CPU0_PPU_DriverIRQHandler + BX R0 + + PUBWEAK CPU1_PPU_IRQHandler + PUBWEAK CPU1_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CPU1_PPU_IRQHandler + LDR R0, =CPU1_PPU_DriverIRQHandler + BX R0 + + PUBWEAK CPU0_DGB_PPU_IRQHandler + PUBWEAK CPU0_DGB_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CPU0_DGB_PPU_IRQHandler + LDR R0, =CPU0_DGB_PPU_DriverIRQHandler + BX R0 + + PUBWEAK CPU1_DGB_PPU_IRQHandler + PUBWEAK CPU1_DGB_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CPU1_DGB_PPU_IRQHandler + LDR R0, =CPU1_DGB_PPU_DriverIRQHandler + BX R0 + + PUBWEAK CRYPTOCELL_PPU_IRQHandler + PUBWEAK CRYPTOCELL_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CRYPTOCELL_PPU_IRQHandler + LDR R0, =CRYPTOCELL_PPU_DriverIRQHandler + BX R0 + + PUBWEAK RAM0_PPU_IRQHandler + PUBWEAK RAM0_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +RAM0_PPU_IRQHandler + LDR R0, =RAM0_PPU_DriverIRQHandler + BX R0 + + PUBWEAK RAM1_PPU_IRQHandler + PUBWEAK RAM1_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +RAM1_PPU_IRQHandler + LDR R0, =RAM1_PPU_DriverIRQHandler + BX R0 + + PUBWEAK RAM2_PPU_IRQHandler + PUBWEAK RAM2_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +RAM2_PPU_IRQHandler + LDR R0, =RAM2_PPU_DriverIRQHandler + BX R0 + + PUBWEAK RAM3_PPU_IRQHandler + PUBWEAK RAM3_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +RAM3_PPU_IRQHandler + LDR R0, =RAM3_PPU_DriverIRQHandler + BX R0 + + PUBWEAK DEBUG_PPU_IRQHandler + PUBWEAK DEBUG_PPU_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +DEBUG_PPU_IRQHandler + LDR R0, =DEBUG_PPU_DriverIRQHandler + BX R0 + + PUBWEAK CPU0_CTI_IRQHandler + PUBWEAK CPU0_CTI_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CPU0_CTI_IRQHandler + LDR R0, =CPU0_CTI_DriverIRQHandler + BX R0 + + PUBWEAK CPU1_CTI_IRQHandler + PUBWEAK CPU1_CTI_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +CPU1_CTI_IRQHandler + LDR R0, =CPU1_CTI_DriverIRQHandler + BX R0 + + PUBWEAK GpTimer_IRQHandler + PUBWEAK GpTimer_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GpTimer_IRQHandler + LDR R0, =GpTimer_DriverIRQHandler + BX R0 + + PUBWEAK I2C0_IRQHandler + PUBWEAK I2C0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +I2C0_IRQHandler + LDR R0, =I2C0_DriverIRQHandler + BX R0 + + PUBWEAK I2C1_IRQHandler + PUBWEAK I2C1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +I2C1_IRQHandler + LDR R0, =I2C1_DriverIRQHandler + BX R0 + + PUBWEAK I2S_IRQHandler + PUBWEAK I2S_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +I2S_IRQHandler + LDR R0, =I2S_DriverIRQHandler + BX R0 + + PUBWEAK SPI_IRQHandler + PUBWEAK SPI_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +SPI_IRQHandler + LDR R0, =SPI_DriverIRQHandler + BX R0 + + PUBWEAK QSPI_IRQHandler + PUBWEAK QSPI_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +QSPI_IRQHandler + LDR R0, =QSPI_DriverIRQHandler + BX R0 + + PUBWEAK UARTRX0_Handler + PUBWEAK UARTRX0_DriverHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UARTRX0_Handler + LDR R0, =UARTRX0_DriverHandler + BX R0 + + PUBWEAK UARTTX0_Handler + PUBWEAK UARTTX0_DriverHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UARTTX0_Handler + LDR R0, =UARTTX0_DriverHandler + BX R0 + + PUBWEAK UART0_RxTimeout_IRQHandler + PUBWEAK UART0_RxTimeout_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UART0_RxTimeout_IRQHandler + LDR R0, =UART0_RxTimeout_DriverIRQHandler + BX R0 + + PUBWEAK UART0_ModemStatus_IRQHandler + PUBWEAK UART0_ModemStatus_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UART0_ModemStatus_IRQHandler + LDR R0, =UART0_ModemStatus_DriverIRQHandler + BX R0 + + PUBWEAK UART0_Error_IRQHandler + PUBWEAK UART0_Error_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UART0_Error_IRQHandler + LDR R0, =UART0_Error_DriverIRQHandler + BX R0 + + PUBWEAK UART0_IRQHandler + PUBWEAK UART0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UART0_IRQHandler + LDR R0, =UART0_DriverIRQHandler + BX R0 + + PUBWEAK UARTRX1_Handler + PUBWEAK UARTRX1_DriverHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UARTRX1_Handler + LDR R0, =UARTRX1_DriverHandler + BX R0 + + PUBWEAK UARTTX1_Handler + PUBWEAK UARTTX1_DriverHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UARTTX1_Handler + LDR R0, =UARTTX1_DriverHandler + BX R0 + + PUBWEAK UART1_RxTimeout_IRQHandler + PUBWEAK UART1_RxTimeout_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UART1_RxTimeout_IRQHandler + LDR R0, =UART1_RxTimeout_DriverIRQHandler + BX R0 + + PUBWEAK UART1_ModemStatus_IRQHandler + PUBWEAK UART1_ModemStatus_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UART1_ModemStatus_IRQHandler + LDR R0, =UART1_ModemStatus_DriverIRQHandler + BX R0 + + PUBWEAK UART1_Error_IRQHandler + PUBWEAK UART1_Error_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UART1_Error_IRQHandler + LDR R0, =UART1_Error_DriverIRQHandler + BX R0 + + PUBWEAK UART1_IRQHandler + PUBWEAK UART1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +UART1_IRQHandler + LDR R0, =UART1_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_0_IRQHandler + PUBWEAK GPIO_0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_0_IRQHandler + LDR R0, =GPIO_0_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_1_IRQHandler + PUBWEAK GPIO_1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_1_IRQHandler + LDR R0, =GPIO_1_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_2_IRQHandler + PUBWEAK GPIO_2_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_2_IRQHandler + LDR R0, =GPIO_2_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_3_IRQHandler + PUBWEAK GPIO_3_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_3_IRQHandler + LDR R0, =GPIO_3_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_4_IRQHandler + PUBWEAK GPIO_4_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_4_IRQHandler + LDR R0, =GPIO_4_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_5_IRQHandler + PUBWEAK GPIO_5_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_5_IRQHandler + LDR R0, =GPIO_5_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_6_IRQHandler + PUBWEAK GPIO_6_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_6_IRQHandler + LDR R0, =GPIO_6_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_7_IRQHandler + PUBWEAK GPIO_7_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_7_IRQHandler + LDR R0, =GPIO_7_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_8_IRQHandler + PUBWEAK GPIO_8_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_8_IRQHandler + LDR R0, =GPIO_8_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_9_IRQHandler + PUBWEAK GPIO_9_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_9_IRQHandler + LDR R0, =GPIO_9_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_10_IRQHandler + PUBWEAK GPIO_10_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_10_IRQHandler + LDR R0, =GPIO_10_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_11_IRQHandler + PUBWEAK GPIO_11_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_11_IRQHandler + LDR R0, =GPIO_11_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_12_IRQHandler + PUBWEAK GPIO_12_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_12_IRQHandler + LDR R0, =GPIO_12_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_13_IRQHandler + PUBWEAK GPIO_13_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_13_IRQHandler + LDR R0, =GPIO_13_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_14_IRQHandler + PUBWEAK GPIO_14_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_14_IRQHandler + LDR R0, =GPIO_14_DriverIRQHandler + BX R0 + + PUBWEAK GPIO_15_IRQHandler + PUBWEAK GPIO_15_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GPIO_15_IRQHandler + LDR R0, =GPIO_15_DriverIRQHandler + BX R0 + + PUBWEAK Combined_IRQHandler + PUBWEAK Combined_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +Combined_IRQHandler + LDR R0, =Combined_DriverIRQHandler + BX R0 + + PUBWEAK PVT_IRQHandler + PUBWEAK PVT_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PVT_IRQHandler + LDR R0, =PVT_DriverIRQHandler + BX R0 + + PUBWEAK PWM_0_IRQHandler + PUBWEAK PWM_0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PWM_0_IRQHandler + LDR R0, =PWM_0_DriverIRQHandler + BX R0 + + PUBWEAK RTC_IRQHandler + PUBWEAK RTC_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +RTC_IRQHandler + LDR R0, =RTC_DriverIRQHandler + BX R0 + + PUBWEAK GpTimer1_IRQHandler + PUBWEAK GpTimer1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GpTimer1_IRQHandler + LDR R0, =GpTimer1_DriverIRQHandler + BX R0 + + PUBWEAK GpTimer0_IRQHandler + PUBWEAK GpTimer0_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +GpTimer0_IRQHandler + LDR R0, =GpTimer0_DriverIRQHandler + BX R0 + + PUBWEAK PWM_1_IRQHandler + PUBWEAK PWM_1_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PWM_1_IRQHandler + LDR R0, =PWM_1_DriverIRQHandler + BX R0 + + PUBWEAK PWM_2_IRQHandler + PUBWEAK PWM_2_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +PWM_2_IRQHandler + LDR R0, =PWM_2_DriverIRQHandler + BX R0 + + PUBWEAK IOMUX_IRQHandler + PUBWEAK IOMUX_DriverIRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) +IOMUX_IRQHandler + LDR R0, =IOMUX_DriverIRQHandler + BX R0 + +NS_WATCHDOG_RESET_DriverIRQHandler +NS_WATCHDOG_DriverIRQHandler +S32K_TIMER_DriverIRQHandler +TIMER0_DriverIRQHandler +TIMER1_DriverIRQHandler +DUALTIMER_DriverIRQHandler +MHU0_DriverIRQHandler +MHU1_DriverIRQHandler +CRYPTOCELL_DriverIRQHandler +I_CACHE_INV_ERR_DriverIRQHandler +SYS_PPU_DriverIRQHandler +CPU0_PPU_DriverIRQHandler +CPU1_PPU_DriverIRQHandler +CPU0_DGB_PPU_DriverIRQHandler +CPU1_DGB_PPU_DriverIRQHandler +CRYPTOCELL_PPU_DriverIRQHandler +RAM0_PPU_DriverIRQHandler +RAM1_PPU_DriverIRQHandler +RAM2_PPU_DriverIRQHandler +RAM3_PPU_DriverIRQHandler +DEBUG_PPU_DriverIRQHandler +CPU0_CTI_DriverIRQHandler +CPU1_CTI_DriverIRQHandler +GpTimer_DriverIRQHandler +I2C0_DriverIRQHandler +I2C1_DriverIRQHandler +I2S_DriverIRQHandler +SPI_DriverIRQHandler +QSPI_DriverIRQHandler +UARTRX0_DriverHandler +UARTTX0_DriverHandler +UART0_RxTimeout_DriverIRQHandler +UART0_ModemStatus_DriverIRQHandler +UART0_Error_DriverIRQHandler +UART0_DriverIRQHandler +UARTRX1_DriverHandler +UARTTX1_DriverHandler +UART1_RxTimeout_DriverIRQHandler +UART1_ModemStatus_DriverIRQHandler +UART1_Error_DriverIRQHandler +UART1_DriverIRQHandler +GPIO_0_DriverIRQHandler +GPIO_1_DriverIRQHandler +GPIO_2_DriverIRQHandler +GPIO_3_DriverIRQHandler +GPIO_4_DriverIRQHandler +GPIO_5_DriverIRQHandler +GPIO_6_DriverIRQHandler +GPIO_7_DriverIRQHandler +GPIO_8_DriverIRQHandler +GPIO_9_DriverIRQHandler +GPIO_10_DriverIRQHandler +GPIO_11_DriverIRQHandler +GPIO_12_DriverIRQHandler +GPIO_13_DriverIRQHandler +GPIO_14_DriverIRQHandler +GPIO_15_DriverIRQHandler +Combined_DriverIRQHandler +PVT_DriverIRQHandler +PWM_0_DriverIRQHandler +RTC_DriverIRQHandler +GpTimer1_DriverIRQHandler +GpTimer0_DriverIRQHandler +PWM_1_DriverIRQHandler +PWM_2_DriverIRQHandler +IOMUX_DriverIRQHandler +DefaultISR + B . + + END diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/cmsis_nvic.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/cmsis_nvic.h new file mode 100644 index 0000000000..5660c48e96 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/cmsis_nvic.h @@ -0,0 +1,35 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is included from the linker script, + * limited set of C constructs can be used here + */ + +#ifndef MBED_CMSIS_NVIC_H +#define MBED_CMSIS_NVIC_H + +#include "../../partition/region_defs.h" + +#define NVIC_NUM_VECTORS (16 + 76) +/** Location of vectors to move in RAM */ +#define NVIC_RAM_VECTOR_ADDRESS NS_DATA_START +#define NVIC_RAM_VECTOR_SIZE (NVIC_NUM_VECTORS * 4) +#define NVIC_RAM_VECTOR_LIMIT (NVIC_RAM_VECTOR_ADDRESS + NVIC_RAM_VECTOR_SIZE) + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/cmsis_nvic_virtual.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/cmsis_nvic_virtual.c new file mode 100644 index 0000000000..6a8ef8dc54 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/cmsis_nvic_virtual.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cmsis_nvic_virtual.h" +#include "psa/lifecycle.h" + +void NVIC_SystemReset(void) +{ + mbed_psa_system_reset(); +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/cmsis_nvic_virtual.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/cmsis_nvic_virtual.h new file mode 100644 index 0000000000..a1a8b61752 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/cmsis_nvic_virtual.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cmsis.h" + +#ifndef NVIC_VIRTUAL_H +#define NVIC_VIRTUAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* NVIC functions */ +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority + +/** + * \brief Overriding the default CMSIS system reset implementation by calling + * secure TFM service. + * + */ +void NVIC_SystemReset(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/timer_gp_drv.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/timer_gp_drv.c new file mode 100644 index 0000000000..b7b2c6ee36 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/timer_gp_drv.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2018-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file timer_gp_drv.c + * + * \brief Generic driver for general purpose timer. + */ + +#include "timer_gp_drv.h" + +/** Setter bit manipulation macro */ +#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX))) +/** Clearing bit manipulation macro */ +#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX))) +/** Getter bit manipulation macro */ +#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX)))) + +/** + * \brief Timer register map structure + * + */ +struct timer_gp_reg_map_t { + volatile uint32_t reset; /*!< Offset: 0x000 (R/W) Control Reset */ + volatile uint32_t irq_mask; /*!< Offset: 0x004 (R/W) Masked Interrupt */ + volatile uint32_t irq_clear; /*!< Offset: 0x008 (R/W) Interrupt Clear */ + volatile uint32_t reserved; /*!< Offset: 0x00C Reserved */ + volatile uint32_t alarm0; /*!< Offset: 0x010 (R/W) Alarm0 data value */ + volatile uint32_t alarm1; /*!< Offset: 0x014 (R/W) Alarm1 data value */ + volatile uint32_t irq_status; /*!< Offset: 0x018 (R) Raw Interrupt status */ + volatile uint32_t counter; /*!< Offset: 0x01C (R) Counter data value */ +}; + +/** + * \brief Reset control register bit identifiers + * + */ +enum reset_reg_bits_t{ + RESET_REG_INDEX = 0 + /* 1-31: Reserved. Read as zero. Do No Modify (DNM). */ +}; + +void timer_gp_init(const struct timer_gp_dev_t* dev) +{ + if (dev->data->is_initialized == false) { + timer_gp_interrupt_disable(dev, TIMER_GP_ALARM_0); + timer_gp_interrupt_clear(dev, TIMER_GP_ALARM_0); + timer_gp_interrupt_disable(dev, TIMER_GP_ALARM_1); + timer_gp_interrupt_clear(dev, TIMER_GP_ALARM_1); + timer_gp_set_alarm_value(dev, TIMER_GP_ALARM_0, dev->data->alarm0_init); + timer_gp_set_alarm_value(dev, TIMER_GP_ALARM_1, dev->data->alarm1_init); + timer_gp_counter_reset(dev); + dev->data->is_initialized = true; + } +} + +void timer_gp_counter_reset(const struct timer_gp_dev_t* dev) +{ + struct timer_gp_reg_map_t* const register_map = + (struct timer_gp_reg_map_t*)dev->cfg->base; + + SET_BIT(register_map->reset, RESET_REG_INDEX); + /* Reset bit is not self-clearing and some pulse width is required + * for successful reset, so we have to check whether the + * timer counter is set to reset value. Until this bit is asserted + * the timer won't be started. + * The timer is running only if the reset bit is cleared.*/ + while (timer_gp_get_counter(dev) != TIMER_GP_DEFAULT_RESET) + ; + CLR_BIT(register_map->reset, RESET_REG_INDEX); +} + +uint32_t timer_gp_get_counter(const struct timer_gp_dev_t* dev) +{ + struct timer_gp_reg_map_t* const register_map = + (struct timer_gp_reg_map_t*)dev->cfg->base; + return register_map->counter; +} + +void timer_gp_interrupt_enable(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm) +{ + struct timer_gp_reg_map_t* const register_map = + (struct timer_gp_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->irq_mask, alarm); +} + +void timer_gp_interrupt_disable(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm) +{ + struct timer_gp_reg_map_t* const register_map = + (struct timer_gp_reg_map_t*)dev->cfg->base; + CLR_BIT(register_map->irq_mask, alarm); +} + +bool timer_gp_interrupt_is_enabled(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm) +{ + struct timer_gp_reg_map_t* const register_map = + (struct timer_gp_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->irq_mask, alarm); +} + +bool timer_gp_interrupt_is_active(const struct timer_gp_dev_t* dev, + const enum timer_gp_read_alarm_identifier_t alarm) +{ + struct timer_gp_reg_map_t* const register_map = + (struct timer_gp_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->irq_status, alarm); +} + +void timer_gp_interrupt_clear(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm) +{ + struct timer_gp_reg_map_t* const register_map = + (struct timer_gp_reg_map_t*)dev->cfg->base; + enum timer_gp_read_alarm_identifier_t read_alarm = + ((alarm == TIMER_GP_ALARM_0) ? + (TIMER_GP_READ_ALARM_0) : + (TIMER_GP_READ_ALARM_1)); + + SET_BIT(register_map->irq_clear, alarm); + + /* Clear bit is not self-clearing and some pulse width is required + * for successful interrupt clear, so we have to check whether the + * interrupt is cleared. */ + while(timer_gp_interrupt_is_active(dev, read_alarm)) + ; + CLR_BIT(register_map->irq_clear, alarm); +} + +void timer_gp_set_alarm_value(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm, + const uint32_t value) +{ + struct timer_gp_reg_map_t* const register_map = + (struct timer_gp_reg_map_t*)dev->cfg->base; + if (alarm == TIMER_GP_ALARM_0) { + register_map->alarm0 = value; + } else { + register_map->alarm1 = value; + } +} + +uint32_t timer_gp_get_alarm_value(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm) +{ + struct timer_gp_reg_map_t* const register_map = + (struct timer_gp_reg_map_t*)dev->cfg->base; + if (alarm == TIMER_GP_ALARM_0) { + return register_map->alarm0; + } else { + return register_map->alarm1; + } +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/timer_gp_drv.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/timer_gp_drv.h new file mode 100644 index 0000000000..16348e6b23 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/timer_gp_drv.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2018-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file timer_gp_drv.h + * + * \brief Generic driver for general purpose timer. + * + * \details + * The free running counter is a 32 bit size counter that counts + * up to 0xFFFFFFFF. + * At this maximum value it wraps around to 0x00000000 and continues + * incrementing. + * Software can reset the counter to default 1 by calling + * \ref timer_gp_counter_reset. + * The counter implements two compare interrupts. When the counter + * reaches compare value "alarm0" or "alarm1" value it can trigger a + * corresponding interrupt. + */ + +#ifndef __TIMER_GP_DRV_H__ +#define __TIMER_GP_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TIMER_GP_MAX_VALUE UINT32_MAX /*!< max of 32-bit */ +#define TIMER_GP_DEFAULT_RESET 1U +/*!< Counter's reset value will be set at HW level if reset bit is asserted */ + +/** GP timer device structure */ +struct timer_gp_dev_cfg_t { + const uintptr_t base; /*!< Timer base address */ +}; + +/** GP timer device data structure */ +struct timer_gp_dev_data_t { + bool is_initialized; + uint32_t alarm0_init; /*!< Alarm0 value will be set by init */ + uint32_t alarm1_init; /*!< Alarm1 value will be set by init */ +}; + +/** GP timer device structure */ +struct timer_gp_dev_t { + const struct timer_gp_dev_cfg_t* const cfg; /*!< Timer configuration */ + struct timer_gp_dev_data_t* const data; /*!< Timer data */ +}; + +/** + * \brief GP Timer alarm number identifiers + * + */ +enum timer_gp_alarm_identifier_t{ + TIMER_GP_ALARM_0 = 0, + TIMER_GP_ALARM_1 = 1 +}; + +/** + * \brief GP Timer read alarm number identifiers + * + */ +enum timer_gp_read_alarm_identifier_t{ + TIMER_GP_READ_ALARM_0 = 0, + TIMER_GP_READ_ALARM_1 = 1, + TIMER_GP_READ_ALARM_COMBINED = 2 + /*!< Combined is asserted if Alarm1 OR Alarm2 is asserted */ +}; + +/** + * \brief Initializes timer to a known default state, which is: + * - interrupts disabled + * - alarm0 and alarm1 set to init value in \ref timer_gp_dev_data_t + * - timer reset to default reset value \ref TIMER_GP_DEFAULT_RESET + * Init should be called prior to any other process and + * it's the caller's responsibility to follow proper call order. + * More than one call results fall through. + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + */ +void timer_gp_init(const struct timer_gp_dev_t* dev); + +/** + * \brief Resets the timer counter to 1. + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + */ +void timer_gp_counter_reset(const struct timer_gp_dev_t* dev); + +/** + * \brief Read the 32bit free runnning counter's current value + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + * + * \return 32bit counter current value + */ +uint32_t timer_gp_get_counter(const struct timer_gp_dev_t* dev); + +/** + * \brief Enable alarm interrupt of the given source + * Note: This function is not interrupt safe. + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + * \param[in] alarm Alarm source of the interrupt + * \ref timer_gp_alarm_identifier_t + * + */ +void timer_gp_interrupt_enable(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm); + +/** + * \brief Disable alarm interrupt of the given source + * Note: This function is not interrupt safe. + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + * \param[in] alarm Alarm source of the interrupt + * \ref timer_gp_alarm_identifier_t + * + */ +void timer_gp_interrupt_disable(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm); + +/** + * \brief Get alarm interrupt enabled status of the given source + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + * \param[in] alarm Alarm source of the interrupt + * \ref timer_gp_alarm_identifier_t + * + * \return true if enabled, false if not + */ +bool timer_gp_interrupt_is_enabled(const struct timer_gp_dev_t* dev, + const enum + timer_gp_alarm_identifier_t alarm); + +/** + * \brief Get alarm interrupt pending status of the given source + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + * \param[in] alarm Alarm source of the interrupt + * \ref timer_gp_read_alarm_identifier_t + * + * \return true if active, false if not + */ +bool timer_gp_interrupt_is_active(const struct timer_gp_dev_t* dev, + const enum timer_gp_read_alarm_identifier_t alarm); + +/** + * \brief Clear alarm interrupt of the given source + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + * \param[in] alarm Alarm source of the interrupt + * \ref timer_gp_alarm_identifier_t + * + */ +void timer_gp_interrupt_clear(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm); + +/** + * \brief Set alarm value of the given source + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + * \param[in] alarm Alarm source \ref timer_gp_alarm_identifier_t + * \param[in] value When the counter reaches this tick value + * corresponding interrupt status will be asserted. + */ +void timer_gp_set_alarm_value(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm, + const uint32_t value); + +/** + * \brief Get alarm value of the given source + * + * \param[in] dev Timer device struct \ref timer_gp_dev_t + * \param[in] alarm Alarm source \ref timer_gp_alarm_identifier_t + * + * \return value Counter value when the alarm is asserted. + */ +uint32_t timer_gp_get_alarm_value(const struct timer_gp_dev_t* dev, + const enum timer_gp_alarm_identifier_t alarm); + +#ifdef __cplusplus +} +#endif +#endif /* __TIMER_GP_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/uart_pl011_drv.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/uart_pl011_drv.c new file mode 100644 index 0000000000..557f2565ef --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/uart_pl011_drv.c @@ -0,0 +1,1021 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "uart_pl011_drv.h" + +#include +#include "cmsis_compiler.h" + +#define FREQ_IRLPBAUD16_MIN (1420000u) /* 1.42 MHz */ +#define FREQ_IRLPBAUD16_MAX (2120000u) /* 2.12 MHz */ +#define SAMPLING_FACTOR (16u) +#define UART_PL011_FBRD_WIDTH (6u) + +/** + * \brief UART PL011 register map structure + */ +struct _uart_pl011_reg_map_t { + volatile uint32_t uartdr; /*!< Offset: 0x000 (R/W) Data register */ + union { + volatile uint32_t uartrsr; + /*!< Offset: 0x004 (R/ ) Receive status register */ + volatile uint32_t uartecr; + /*!< Offset: 0x004 ( /W) Error clear register */ + }; + volatile uint32_t reserved_0[4]; /*!< Offset: 0x008-0x014 Reserved */ + volatile uint32_t uartfr; /*!< Offset: 0x018 (R/ ) Flag register */ + volatile uint32_t reserved_1; /*!< Offset: 0x01C Reserved */ + volatile uint32_t uartilpr; + /*!< Offset: 0x020 (R/W) IrDA low-power counter register */ + volatile uint32_t uartibrd; + /*!< Offset: 0x024 (R/W) Integer baud rate register */ + volatile uint32_t uartfbrd; + /*!< Offset: 0x028 (R/W) Fractional baud rate register */ + volatile uint32_t uartlcr_h; + /*!< Offset: 0x02C (R/W) Line control register */ + volatile uint32_t uartcr; + /*!< Offset: 0x030 (R/W) Control register */ + volatile uint32_t uartifls; + /*!< Offset: 0x034 (R/W) Interrupt FIFO level select register */ + volatile uint32_t uartimsc; + /*!< Offset: 0x038 (R/W) Interrupt mask set/clear register */ + volatile uint32_t uartris; + /*!< Offset: 0x03C (R/ ) Raw interrupt status register */ + volatile uint32_t uartmis; + /*!< Offset: 0x040 (R/ ) Masked interrupt status register */ + volatile uint32_t uarticr; + /*!< Offset: 0x044 ( /W) Interrupt clear register */ + volatile uint32_t uartdmacr; + /*!< Offset: 0x048 (R/W) DMA control register */ + volatile uint32_t reserved_2[13]; /*!< Offset: 0x04C-0x07C Reserved */ + volatile uint32_t reserved_3[4]; + /*!< Offset: 0x080-0x08C Reserved for test purposes */ + volatile uint32_t reserved_4[976]; /*!< Offset: 0x090-0xFCC Reserved */ + volatile uint32_t reserved_5[4]; + /*!< Offset: 0xFD0-0xFDC Reserved for future ID expansion */ + volatile uint32_t uartperiphid0; + /*!< Offset: 0xFE0 (R/ ) UARTPeriphID0 register */ + volatile uint32_t uartperiphid1; + /*!< Offset: 0xFE4 (R/ ) UARTPeriphID1 register */ + volatile uint32_t uartperiphid2; + /*!< Offset: 0xFE8 (R/ ) UARTPeriphID2 register */ + volatile uint32_t uartperiphid3; + /*!< Offset: 0xFEC (R/ ) UARTPeriphID3 register */ + volatile uint32_t uartpcellid0; + /*!< Offset: 0xFF0 (R/ ) UARTPCellID0 register */ + volatile uint32_t uartpcellid1; + /*!< Offset: 0xFF4 (R/ ) UARTPCellID1 register */ + volatile uint32_t uartpcellid2; + /*!< Offset: 0xFF8 (R/ ) UARTPCellID2 register */ + volatile uint32_t uartpcellid3; + /*!< Offset: 0xFFC (R/ ) UARTPCellID3 register */ +}; + +#define UART_PL011_UARTFR_CTS_MASK ( \ + 0x1u<uartcr |= UART_PL011_UARTCR_EN_MASK; +} + +static void _uart_pl011_disable(struct _uart_pl011_reg_map_t* p_uart) +{ + p_uart->uartcr &= ~UART_PL011_UARTCR_EN_MASK; +} + +static bool _uart_pl011_is_enabled(struct _uart_pl011_reg_map_t* p_uart) +{ + return (bool)(p_uart->uartcr & UART_PL011_UARTCR_EN_MASK); +} + +static void _uart_pl011_enable_fifo(struct _uart_pl011_reg_map_t* p_uart) +{ + p_uart->uartlcr_h |= UART_PL011_UARTLCR_H_FEN_MASK; +} + +static void _uart_pl011_disable_fifo(struct _uart_pl011_reg_map_t* p_uart) +{ + p_uart->uartlcr_h &= ~UART_PL011_UARTLCR_H_FEN_MASK; +} + +static bool _uart_pl011_is_fifo_enabled(struct _uart_pl011_reg_map_t* p_uart) +{ + return (bool)(p_uart->uartlcr_h & UART_PL011_UARTLCR_H_FEN_MASK); +} + +static bool _uart_pl011_is_busy(struct _uart_pl011_reg_map_t* p_uart) +{ + return (bool)(p_uart->uartfr & UART_PL011_UARTFR_BUSYBIT); +} + +static enum uart_pl011_error_t _uart_pl011_set_baudrate( + struct _uart_pl011_reg_map_t* p_uart, + uint32_t clk, uint32_t baudrate) +{ + /* Avoiding float calculations, bauddiv is left shifted by 6 */ + uint64_t bauddiv = (((uint64_t)clk)<= 16 x baud_rate (max) + * uart_clk (max) <= 16 x 65535 x baud_rate (min) + */ + if((bauddiv < (1u< (65535u<uartibrd = (uint32_t)(bauddiv >> UART_PL011_FBRD_WIDTH); + p_uart->uartfbrd = (uint32_t)(bauddiv & + ((1u << UART_PL011_FBRD_WIDTH) - 1u)); + + __DMB(); + + /* In order to internally update the contents of uartibrd or uartfbrd, a + * uartlcr_h write must always be performed at the end + * ARM DDI 0183F, Pg 3-13 + */ + p_uart->uartlcr_h = p_uart->uartlcr_h; + + return UART_PL011_ERR_NONE; +} + +static void _uart_pl011_set_format(struct _uart_pl011_reg_map_t* p_uart, + enum uart_pl011_wlen_t word_len, + enum uart_pl011_parity_t parity, + enum uart_pl011_stopbit_t stop_bits) +{ + uint32_t ctrl_reg = p_uart->uartlcr_h & ~(UART_PL011_FORMAT_MASK); + + /* Making sure other bit are not changed */ + word_len &= UART_PL011_UARTLCR_H_WLEN_MASK; + parity &= UART_PL011_UARTLCR_H_PARITY_MASK; + stop_bits &= UART_PL011_UARTLCR_H_STOPBIT_MASK; + + p_uart->uartlcr_h = ctrl_reg | word_len | parity | stop_bits; + +} + +static void _uart_pl011_set_cr_bit(struct _uart_pl011_reg_map_t* p_uart, + uint32_t mask) +{ + bool uart_enabled = _uart_pl011_is_enabled(p_uart); + bool fifo_enabled = _uart_pl011_is_fifo_enabled(p_uart); + + /* UART must be disabled before any Control Register or + * Line Control Register are reprogrammed */ + _uart_pl011_disable(p_uart); + + /* Flush the transmit FIFO by disabling bit 4 (FEN) in + * the line control register (UARTCLR_H) */ + _uart_pl011_disable_fifo(p_uart); + + p_uart->uartcr |= (mask); + + /* Enabling the FIFOs if previously enabled */ + if(fifo_enabled) { + _uart_pl011_enable_fifo(p_uart); + } + + /* Enabling the UART if previously enabled */ + if(uart_enabled) { + _uart_pl011_enable(p_uart); + } +} + +static void _uart_pl011_clear_cr_bit(struct _uart_pl011_reg_map_t* p_uart, + uint32_t mask) +{ + bool uart_enabled = _uart_pl011_is_enabled(p_uart); + bool fifo_enabled = _uart_pl011_is_fifo_enabled(p_uart); + + /* UART must be disabled before any Control Register or + * Line Control Register are reprogrammed */ + _uart_pl011_disable(p_uart); + + /* Flush the transmit FIFO by disabling bit 4 (FEN) in + * the line control register (UARTCLR_H) */ + _uart_pl011_disable_fifo(p_uart); + + p_uart->uartcr &= ~(mask); + + /* Enabling the FIFOs if previously enabled */ + if(fifo_enabled) { + _uart_pl011_enable_fifo(p_uart); + } + + /* Enabling the UART if previously enabled */ + if(uart_enabled) { + _uart_pl011_enable(p_uart); + } +} + +static void _uart_pl011_set_lcr_h_bit(struct _uart_pl011_reg_map_t* p_uart, + uint32_t mask) +{ + bool uart_enabled = _uart_pl011_is_enabled(p_uart); + + /* UART must be disabled before any Control Register or + * Line Control Register are reprogrammed */ + _uart_pl011_disable(p_uart); + + p_uart->uartlcr_h |= (mask); + + /* Enabling the UART if previously enabled */ + if(uart_enabled) { + _uart_pl011_enable(p_uart); + } +} + +static void _uart_pl011_clear_lcr_h_bit(struct _uart_pl011_reg_map_t* p_uart, + uint32_t mask) +{ + bool uart_enabled = _uart_pl011_is_enabled(p_uart); + + /* UART must be disabled before any Control Register or + * Line Control Register are reprogrammed */ + _uart_pl011_disable(p_uart); + + p_uart->uartlcr_h &= ~(mask); + + /* Enabling the UART if previously enabled */ + if(uart_enabled) { + _uart_pl011_enable(p_uart); + } +} + +static void _uart_pl011_reset_regs(struct _uart_pl011_reg_map_t* p_uart) +{ + /* Restore the default value of UART registers, the registers which + * are not listed below are Read-Only */ + + /* Will disable the UART */ + p_uart->uartcr = UART_PL011_CR_REG_RESET_VALUE; + p_uart->uartdr = UART_PL011_DATA_REG_RESET_VALUE; + /* Clear all the errors */ + p_uart->uartecr = UART_PL011_ECR_REG_CLEAR_VALUE; + p_uart->uartilpr = UART_PL011_ILPR_REG_RESET_VALUE; + p_uart->uartibrd = UART_PL011_IBRD_REG_RESET_VALUE; + p_uart->uartfbrd = UART_PL011_FBRD_REG_RESET_VALUE; + p_uart->uartlcr_h = UART_PL011_LCR_H_REG_RESET_VALUE; + p_uart->uartifls = UART_PL011_IFLS_REG_RESET_VALUE; + p_uart->uartimsc = UART_PL011_IMSC_REG_RESET_VALUE; + /* Clear all the interrupts */ + p_uart->uarticr = UART_PL011_ICR_REG_CLEAR_VALUE; + p_uart->uartdmacr = UART_PL011_DMACR_REG_RESET_VALUE; +} + +enum uart_pl011_error_t uart_pl011_init(struct uart_pl011_dev_t* dev, + uint32_t uart_clk) +{ + enum uart_pl011_error_t err; + + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + uint32_t def_baud = dev->cfg->def_baudrate; + + if(uart_clk == 0) { + return UART_PL011_ERR_INVALID_ARG; + } + + if(def_baud == 0) { + return UART_PL011_ERR_INVALID_BAUD; + } + + /* Updating the system clock */ + dev->data->uart_clk = uart_clk; + + /* Setting the default baudrate */ + err = _uart_pl011_set_baudrate(p_uart, uart_clk, def_baud); + + if(err != UART_PL011_ERR_NONE) { + return err; + } + + /* Setting the default character format */ + _uart_pl011_set_format(p_uart, dev->cfg->def_wlen, + dev->cfg->def_parity, + dev->cfg->def_stopbit); + + /* Enabling the FIFOs */ + _uart_pl011_enable_fifo(p_uart); + + dev->data->state = UART_PL011_INITIALIZED; + + return UART_PL011_ERR_NONE; +} + +void uart_pl011_uninit(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + while(_uart_pl011_is_busy(p_uart)); + + /* Disable and restore the default configuration of the peripheral */ + _uart_pl011_reset_regs(p_uart); + + dev->data->state = UART_PL011_UNINITIALIZED; + + return; +} + +enum uart_pl011_state_t uart_pl011_get_state(struct uart_pl011_dev_t* dev) +{ + return dev->data->state; +} + +enum uart_pl011_error_t uart_pl011_set_baudrate( + struct uart_pl011_dev_t* dev, uint32_t baudrate) +{ + enum uart_pl011_error_t err = UART_PL011_ERR_NONE; + + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + bool uart_enabled = _uart_pl011_is_enabled(p_uart); + + if(uart_pl011_get_state(dev) != UART_PL011_INITIALIZED) { + return UART_PL011_ERR_NOT_INIT; + } + + if(baudrate == 0) { + return UART_PL011_ERR_INVALID_BAUD; + } + + /* UART must be disabled before any Control Register or + * Line Control Register are reprogrammed */ + _uart_pl011_disable(p_uart); + + /* If baudrate is not valid ie UART_PL011_ERR_NONE is not returned then + * the UART will continue to function at the old baudrate */ + err = _uart_pl011_set_baudrate(p_uart, dev->data->uart_clk, baudrate); + + if(err == UART_PL011_ERR_NONE) { + dev->data->baudrate = baudrate; + } + + if(uart_enabled) { + _uart_pl011_enable(p_uart); + } + + return err; +} + +uint32_t uart_pl011_get_baudrate(struct uart_pl011_dev_t* dev) +{ + return dev->data->baudrate; +} + +void uart_pl011_enable_intr(struct uart_pl011_dev_t* dev, + enum uart_pl011_intr_t mask) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + p_uart->uartimsc |= (uint32_t)(mask); + + return; +} + +void uart_pl011_disable_intr(struct uart_pl011_dev_t* dev, + enum uart_pl011_intr_t mask) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + p_uart->uartimsc &= (uint32_t)(~mask); + + return; +} + +void uart_pl011_clear_intr(struct uart_pl011_dev_t* dev, + enum uart_pl011_intr_t mask) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + p_uart->uarticr = (uint32_t)mask; + + return; +} + + +enum uart_pl011_intr_t uart_pl011_get_masked_intr_status( + struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + return (enum uart_pl011_intr_t)(p_uart->uartmis); + +} + +enum uart_pl011_intr_t uart_pl011_get_raw_intr_status( + struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + return (enum uart_pl011_intr_t)(p_uart->uartris); +} + +void uart_pl011_set_rx_fifo_lvl(struct uart_pl011_dev_t* dev, + enum uart_pl011_rx_fifo_lvl_t rx_lvl) +{ + uint32_t fifo_lvl; + + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + /* Check if rx_lvl have valid values */ + rx_lvl &= UART_PL011_UARTIFLS_RX_FIFO_LVL_MASK; + + fifo_lvl = p_uart->uartifls + & ~(UART_PL011_UARTIFLS_RX_FIFO_LVL_MASK); + p_uart->uartifls = fifo_lvl | rx_lvl; + + return; +} + +void uart_pl011_set_tx_fifo_lvl(struct uart_pl011_dev_t* dev, + enum uart_pl011_tx_fifo_lvl_t tx_lvl) +{ + uint32_t fifo_lvl; + + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + /* Check if tx_lvl have valid values */ + tx_lvl &= UART_PL011_UARTIFLS_TX_FIFO_LVL_MASK; + + fifo_lvl = p_uart->uartifls + & ~(UART_PL011_UARTIFLS_TX_FIFO_LVL_MASK); + p_uart->uartifls = fifo_lvl | tx_lvl; + + return; +} + +void uart_pl011_set_tx_dma(struct uart_pl011_dev_t* dev, + enum uart_pl011_tx_dma_t enable) +{ + uint32_t dma_cr; + + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + enable &= UART_PL011_UARTDMACR_TX_MASK; + + dma_cr = p_uart->uartdmacr + & ~(UART_PL011_UARTDMACR_TX_MASK); + + p_uart->uartdmacr = dma_cr | enable; + + return; +} + +void uart_pl011_set_rx_dma(struct uart_pl011_dev_t* dev, + enum uart_pl011_rx_dma_t enable) +{ + uint32_t dma_cr; + + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + enable &= UART_PL011_UARTDMACR_RX_MASK; + + dma_cr = p_uart->uartdmacr + & ~(UART_PL011_UARTDMACR_RX_MASK); + + p_uart->uartdmacr = dma_cr | enable; + + return; +} + +bool uart_pl011_is_readable(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + if( (uart_pl011_get_state(dev) == UART_PL011_INITIALIZED) && + /* UART is initialized */ + (p_uart->uartcr & UART_PL011_UARTCR_EN_MASK) && + /* UART is enabled */ + (p_uart->uartcr & UART_PL011_UARTCR_RX_EN_MASK) && + /* Receive is enabled */ + ((p_uart->uartfr & UART_PL011_UARTFR_RX_FIFO_EMPTY) == 0)) { + /* Receive Fifo is not empty */ + return true; + } + + return false; + +} + +enum uart_pl011_error_t uart_pl011_read( + struct uart_pl011_dev_t* dev, uint8_t* byte) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + *byte = p_uart->uartdr; + + return (enum uart_pl011_error_t)(p_uart->uartrsr + & UART_PL011_RX_ERR_MASK); +} + +bool uart_pl011_is_writable(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + if( (uart_pl011_get_state(dev) == UART_PL011_INITIALIZED) && + /* UART is initialized */ + (p_uart->uartcr & UART_PL011_UARTCR_EN_MASK) && + /* UART is enabled */ + (p_uart->uartcr & UART_PL011_UARTCR_TX_EN_MASK) && + /* Transmit is enabled */ + ((p_uart->uartfr & UART_PL011_UARTFR_TX_FIFO_FULL) == 0)) { + /* Transmit Fifo is not full */ + return true; + } + return false; + +} + +void uart_pl011_write(struct uart_pl011_dev_t* dev, uint8_t byte) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + p_uart->uartdr = byte; + + return; +} + +enum uart_pl011_error_t uart_pl011_set_format(struct uart_pl011_dev_t* dev, + enum uart_pl011_wlen_t word_len, + enum uart_pl011_parity_t parity, + enum uart_pl011_stopbit_t stop_bits) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + bool uart_enabled = _uart_pl011_is_enabled(p_uart); + + if(uart_pl011_get_state(dev) != UART_PL011_INITIALIZED) { + return UART_PL011_ERR_NOT_INIT; + } + + /* UART must be disabled before any Control Register or + * Line Control Register are reprogrammed */ + _uart_pl011_disable(p_uart); + + _uart_pl011_set_format(p_uart, word_len, parity, stop_bits); + + /* Enabling the UART if previously enabled */ + if(uart_enabled) { + _uart_pl011_enable(p_uart); + } + + return UART_PL011_ERR_NONE; +} + +void uart_pl011_enable_fifo(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_lcr_h_bit(p_uart, UART_PL011_UARTLCR_H_FEN_MASK); + + return; +} + +void uart_pl011_disable_fifo(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_lcr_h_bit(p_uart, UART_PL011_UARTLCR_H_FEN_MASK); + + return; +} + +void uart_pl011_enable_break(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_lcr_h_bit(p_uart, UART_PL011_UARTLCR_H_BRK_MASK); + + return; +} + +void uart_pl011_disable_break(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_lcr_h_bit(p_uart, UART_PL011_UARTLCR_H_BRK_MASK); + + return; +} + +void uart_pl011_enable_cts_flowcontrol(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_CTSE_MASK); + + return; +} + +void uart_pl011_disable_cts_flowcontrol(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_CTSE_MASK); + + return; +} + +void uart_pl011_enable_rts_flowcontrol(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_RTSE_MASK); + + return; +} + +void uart_pl011_disable_rts_flowcontrol(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_RTSE_MASK); + + return; +} + +void uart_pl011_enable_ri(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_OUT2_MASK); + + return; +} + +void uart_pl011_disable_ri(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_OUT2_MASK); + + return; +} + +void uart_pl011_enable_dcd(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_OUT1_MASK); + + return; +} + +void uart_pl011_disable_dcd(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_OUT1_MASK); + + return; +} + +void uart_pl011_set_rts(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_RTS_MASK); + + return; +} + +void uart_pl011_clear_rts(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_RTS_MASK); + + return; +} + +void uart_pl011_set_dtr(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_DTR_MASK); + + return; +} + +void uart_pl011_clear_dtr(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_DTR_MASK); + + return; +} + +void uart_pl011_enable_receive(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_RX_EN_MASK); + + return; +} + +void uart_pl011_disable_receive(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_RX_EN_MASK); + + return; +} + +void uart_pl011_enable_transmit(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_TX_EN_MASK); + + return; +} + +void uart_pl011_disable_transmit(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_TX_EN_MASK); + + return; +} + +void uart_pl011_set_loopback(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_LBE_MASK); + + return; +} + +void uart_pl011_clear_loopback(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_LBE_MASK); + + return; +} + +void uart_pl011_enable_sirlp(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, + UART_PL011_UARTCR_SIREN_MASK | UART_PL011_UARTCR_SIRLP_MASK); + + return; +} + +void uart_pl011_disable_sirlp(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, + UART_PL011_UARTCR_SIREN_MASK | UART_PL011_UARTCR_SIRLP_MASK); + + return; +} + +void uart_pl011_enable_sir(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_SIREN_MASK); + + return; +} + +void uart_pl011_disable_sir(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_SIREN_MASK); + + return; +} + +void uart_pl011_enable(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_enable(p_uart); + + return; +} + +void uart_pl011_disable(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + _uart_pl011_disable(p_uart); + + return; +} + +bool uart_pl011_get_cts_status(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + return (bool)(p_uart->uartfr & UART_PL011_UARTFR_CTS_MASK); + +} + +bool uart_pl011_get_dsr_status(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + return (bool)(p_uart->uartfr & UART_PL011_UARTFR_DSR_MASK); + +} + +bool uart_pl011_get_dcd_status(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + return (bool)(p_uart->uartfr & UART_PL011_UARTFR_DCD_MASK); + +} + +bool uart_pl011_get_ri_status(struct uart_pl011_dev_t* dev) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + return (bool)(p_uart->uartfr & UART_PL011_UARTFR_RI_MASK); + +} + +enum uart_pl011_error_t uart_pl011_set_sirlp_divisor( + struct uart_pl011_dev_t* dev, uint32_t value) +{ + struct _uart_pl011_reg_map_t* p_uart = + (struct _uart_pl011_reg_map_t*)dev->cfg->base; + + uint32_t irlp_baud16_clk; + + if(uart_pl011_get_state(dev) != UART_PL011_INITIALIZED) { + return UART_PL011_ERR_NOT_INIT; + } + + if(value == 0) { + return UART_PL011_ERR_INVALID_ARG; + } + + irlp_baud16_clk = dev->data->uart_clk/value; + + /* Chose the divisor so that 1.42MHz < FIrLPBaud16 < 2.12MHz, that + * results in a low-power pulse duration of 1.41–2.11μs (three times + * the period of IrLPBaud16). ARM DDI0183F Pg 3-9 */ + if(irlp_baud16_clk < FREQ_IRLPBAUD16_MIN || + irlp_baud16_clk > FREQ_IRLPBAUD16_MAX) { + return UART_PL011_ERR_INVALID_ARG; + } + + p_uart->uartilpr = value; + + return UART_PL011_ERR_NONE; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/uart_pl011_drv.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/uart_pl011_drv.h new file mode 100644 index 0000000000..be4e315768 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/drivers/uart_pl011_drv.h @@ -0,0 +1,854 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file uart_pl011_drv.h + * \brief Driver for ARM UART PL011. + */ + +#ifndef __UART_PL011_DRV_H__ +#define __UART_PL011_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARM UART PL011 state types + */ +enum uart_pl011_state_t { + UART_PL011_UNINITIALIZED = 0x0u, + UART_PL011_INITIALIZED = 0x1u, +}; + +#define UART_PL011_UARTRSR_FE_ERR_OFF 0x0u + /*!< Receive Status Register Frame Error bit field offset */ +#define UART_PL011_UARTRSR_PE_ERR_OFF 0x1u + /*!< Receive Status Register Parity Error bit field offset */ +#define UART_PL011_UARTRSR_BE_ERR_OFF 0x2u + /*!< Receive Status Register Break Error bit field offset */ +#define UART_PL011_UARTRSR_OE_ERR_OFF 0x3u + /*!< Receive Status Register Overrun Error bit field offset */ + +#define UART_PL011_RX_ERR_MASK ( \ + 0x1u< +#include "gpio_irq_api.h" +#include "objects.h" +#include "mbed_error.h" + +int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, + uint32_t id) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ + return 0; +} + +void gpio_irq_free(gpio_irq_t *obj) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ +} + +void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ +} + +void gpio_irq_enable(gpio_irq_t *obj) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ +} + +void gpio_irq_disable(gpio_irq_t *obj) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/lp_ticker.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/lp_ticker.c new file mode 100644 index 0000000000..3a8f769e20 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/lp_ticker.c @@ -0,0 +1,89 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Low-power elapsed time measure and interval ticker, + * using General Purpose Timer \ref timer_gp_dev_t. + */ + +#include "cmsis.h" +#include "device_cfg.h" +#include "timer_gp_drv.h" +#include "lp_ticker_api.h" + +/* Check if the module configuration is right. These definitions + are usually located in device_cfg.h */ +#ifndef GP_TIMER_DEV +#error "Configuration macro GP_TIMER_DEV is undefined!" +#endif + +void lp_ticker_init(void) +{ + timer_gp_init(&GP_TIMER_DEV); + NVIC_EnableIRQ(GP_TIMER_ALARM0_IRQ); + timer_gp_interrupt_disable(&GP_TIMER_DEV, GP_TIMER_ALARM_NR); +} + +void lp_ticker_free(void) +{ + /* This function should stop the ticker from counting, but GP Timer cannot + * be stopped. + */ + timer_gp_interrupt_disable(&GP_TIMER_DEV, GP_TIMER_ALARM_NR); +} + +uint32_t lp_ticker_read(void) +{ + return timer_gp_get_counter(&GP_TIMER_DEV); +} + +void lp_ticker_set_interrupt(timestamp_t timestamp) +{ + timer_gp_set_alarm_value(&GP_TIMER_DEV, GP_TIMER_ALARM_NR, (uint32_t)timestamp); + timer_gp_interrupt_enable(&GP_TIMER_DEV, GP_TIMER_ALARM_NR); +} + +void lp_ticker_disable_interrupt(void) +{ + timer_gp_interrupt_disable(&GP_TIMER_DEV, GP_TIMER_ALARM_NR); +} + +void lp_ticker_clear_interrupt(void) +{ + timer_gp_interrupt_clear(&GP_TIMER_DEV, GP_TIMER_ALARM_NR); +} + +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(GP_TIMER_ALARM0_IRQ); +} + +const ticker_info_t* lp_ticker_get_info(void) +{ + static const ticker_info_t info = { + GP_TIMER_FREQ_HZ, + GP_TIMER_BIT_WIDTH + }; + return &info; +} + +#ifndef GP_TIMER_IRQ0_HANDLER +#error "GP_TIMER_IRQ0_HANDLER should be defined, check device_cfg.h!" +#endif +void GP_TIMER_IRQ0_HANDLER(void) +{ + lp_ticker_irq_handler(); +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/LICENSE-permissive-binary-license-1.0.txt b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/LICENSE-permissive-binary-license-1.0.txt new file mode 100644 index 0000000000..8acf76a4b1 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/LICENSE-permissive-binary-license-1.0.txt @@ -0,0 +1,49 @@ +Permissive Binary License + +Version 1.0, December 2018 + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of this software is + permitted. + +3) Redistribution as part of a software development kit must include the + accompanying file named DEPENDENCIES and any dependencies listed in + that file. + +4) Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +Limited patent license. The copyright holders (and contributors) grant a +worldwide, non-exclusive, no-charge, royalty-free patent license to +make, have made, use, offer to sell, sell, import, and otherwise +transfer this software, where such license applies only to those patent +claims licensable by the copyright holders (and contributors) that are +necessarily infringed by this software. This patent license shall not +apply to any combinations that include this software. No hardware is +licensed hereunder. + +If you institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the software +itself infringes your patent(s), then your rights granted under this +license shall terminate as of the date such litigation is filed. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/README.md b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/README.md new file mode 100644 index 0000000000..4e58e703e8 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/README.md @@ -0,0 +1,43 @@ +# MUSCA_A1_NS prebuilt secure binaries + +This directory tree contains Secure images released under Permissive Binary License. + +Built by mbed-cli using GNU Arm Embedded - version 6.3.1 + +These images were compiled by the following command: + +## mcuboot.bin +### Repository +https://git.trustedfirmware.org/trusted-firmware-m.git +### Commit SHA +8da7f102a6a6a1a99462f7f32edbd1565096c2f3 +```sh +cmake ../ -G"Unix Makefiles" -DTARGET_PLATFORM=MUSCA_A -DCOMPILER=ARMCLANG -DCMAKE_BUILD_TYPE=Debug +make +``` + +## tfm.bin + +```sh +mbed compile -t GCC_ARM -m ARM_MUSCA_A1_S --app-config tools/psa/tfm/mbed_app.json --profile release +``` + +## spm_smoke.bin + +```sh +mbed test --compile -t GCC_ARM -m ARM_MUSCA_A1_S --app-config tools/psa/tfm/mbed_app.json -n tests-psa-spm_smoke -DUSE_PSA_TEST_PARTITIONS -DUSE_SMOKE_TESTS_PART1 --profile release +``` + +## spm_client.bin + +```sh +mbed test --compile -t GCC_ARM -m ARM_MUSCA_A1_S --app-config tools/psa/tfm/mbed_app.json -n tests-psa-spm_client -DUSE_PSA_TEST_PARTITIONS -DUSE_CLIENT_TESTS_PART1 --profile release +``` + +## spm_server.bin + +```sh +mbed test --compile -t GCC_ARM -m ARM_MUSCA_A1_S --app-config tools/psa/tfm/mbed_app.json -n tests-psa-spm_server -DUSE_PSA_TEST_PARTITIONS -DUSE_SERVER_TESTS_PART1 -DUSE_SERVER_TESTS_PART2 --profile release +``` + +To update the prebuilt binaries run the previous commands. diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/cmse_lib.o b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/cmse_lib.o new file mode 100644 index 0000000000..118b2d3fbf Binary files /dev/null and b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/cmse_lib.o differ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/crypto_access_control.bin b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/crypto_access_control.bin new file mode 100644 index 0000000000..38b4d43c4c Binary files /dev/null and b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/crypto_access_control.bin differ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/mcuboot.bin b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/mcuboot.bin new file mode 100644 index 0000000000..718c0217e2 Binary files /dev/null and b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/mcuboot.bin differ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/spm_client.bin b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/spm_client.bin new file mode 100644 index 0000000000..81b62200c3 Binary files /dev/null and b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/spm_client.bin differ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/spm_server.bin b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/spm_server.bin new file mode 100644 index 0000000000..6aaa8681e7 Binary files /dev/null and b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/spm_server.bin differ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/spm_smoke.bin b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/spm_smoke.bin new file mode 100644 index 0000000000..12db5814c2 Binary files /dev/null and b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/spm_smoke.bin differ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/tfm.bin b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/tfm.bin new file mode 100644 index 0000000000..62e6a53c48 Binary files /dev/null and b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/tfm.bin differ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/serial_api.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/serial_api.c new file mode 100644 index 0000000000..a3e1dfcb56 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/serial_api.c @@ -0,0 +1,322 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +/* Use memcpy */ +#include +#include "serial_api.h" +#include "pinmap.h" +#include "objects.h" +/* Use error(...) function */ +#include "mbed_error.h" + +#define STDIO_UART_NOT_INITED 0 +#define STDIO_UART_INITED 1 +#define UART_DEVICES_NUMBER 2 + +struct uart_irq_t { + uart_irq_handler handler; + uint32_t id; +}; + +extern const PinMap PinMap_UART_TX[]; +extern const PinMap PinMap_UART_RX[]; + +/* Handlers registered */ +static struct uart_irq_t uart_irq[UART_DEVICES_NUMBER]; + +/* Global variables needed for mbed */ +int stdio_uart_inited = STDIO_UART_NOT_INITED; +serial_t stdio_uart; + +#ifdef UART0_PL011_DEV +#ifndef uart0_tx_irq_handler +#error "uart0_tx_irq_handler should be defined, check device_cfg.h!" +#endif +void uart0_tx_irq_handler(void) +{ + uart_pl011_clear_intr(&UART0_PL011_DEV, UART_PL011_TX_INTR_MASK); + if(uart_irq[UART_0].handler != 0) { + uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq); + } +} + +#ifndef uart0_rx_irq_handler +#error "uart0_rx_irq_handler should be defined, check device_cfg.h!" +#endif +void uart0_rx_irq_handler(void) +{ + uart_pl011_clear_intr(&UART0_PL011_DEV, UART_PL011_RX_INTR_MASK); + if(uart_irq[UART_0].handler != 0) { + uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq); + } +} + +#ifndef uart0_rx_timeout_irq_handler +#error "uart0_rx_timeout_irq_handler should be defined, check device_cfg.h!" +#endif +void uart0_rx_timeout_irq_handler(void) +{ + if(uart_irq[UART_0].handler != 0) { + uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq); + } +} +#endif + +#ifdef UART1_PL011_DEV +#ifndef uart1_tx_irq_handler +#error "uart1_tx_irq_handler should be defined, check device_cfg.h!" +#endif +void uart1_tx_irq_handler(void) +{ + uart_pl011_clear_intr(&UART1_PL011_DEV, UART_PL011_TX_INTR_MASK); + if(uart_irq[UART_1].handler != 0) { + uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq); + } +} + +#ifndef uart1_rx_irq_handler +#error "uart1_rx_irq_handler should be defined, check device_cfg.h!" +#endif +void uart1_rx_irq_handler(void) +{ + uart_pl011_clear_intr(&UART1_PL011_DEV, UART_PL011_RX_INTR_MASK); + if(uart_irq[UART_1].handler != 0) { + uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq); + } +} + +#ifndef uart1_rx_timeout_irq_handler +#error "uart1_rx_timeout_irq_handler should be defined, check device_cfg.h!" +#endif +void uart1_rx_timeout_irq_handler(void) +{ + if(uart_irq[UART_1].handler != 0) { + uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq); + } +} +#endif + +void serial_init(serial_t *obj, PinName tx, PinName rx) +{ + /* Determine the UART to use */ + UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); + UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); + UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx); + if (uart == (UARTName)NC) { + error("Serial pinout mapping failed"); + } + switch (uart) { +#ifdef UART0_PL011_DEV + case UART_0: + obj->uart_dev = &UART0_PL011_DEV; + obj->tx_irq = UART0_Tx_IRQn; + obj->rx_irq = UART0_Rx_IRQn; + obj->rx_timeout_irq = UART0_RxTimeout_IRQn; + break; +#endif +#ifdef UART1_PL011_DEV + case UART_1: + obj->uart_dev = &UART1_PL011_DEV; + obj->tx_irq = UART1_Tx_IRQn; + obj->rx_irq = UART1_Rx_IRQn; + obj->rx_timeout_irq = UART1_RxTimeout_IRQn; + break; +#endif + default: + error("serial_init: No uart selected"); + } + obj->uart_index = uart; + + /* Pinout the chosen uart */ + pinmap_pinout(tx, PinMap_UART_TX); + pinmap_pinout(rx, PinMap_UART_RX); + + uart_pl011_init(obj->uart_dev, SystemCoreClock); + + uart_pl011_set_baudrate(obj->uart_dev, + MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE); + + + uart_pl011_enable(obj->uart_dev); + + if (uart == STDIO_UART) { + stdio_uart_inited = STDIO_UART_INITED; + memcpy(&stdio_uart, obj, sizeof(serial_t)); + } +} + +void serial_free(serial_t *obj) +{ + uart_pl011_uninit(obj->uart_dev); +} + +void serial_baud(serial_t *obj, int baudrate) +{ + if(uart_pl011_set_baudrate(obj->uart_dev,baudrate) != UART_PL011_ERR_NONE) { + error("serial_baud: invalid baudrate"); + } +} + +void serial_format(serial_t *obj, int data_bits, SerialParity parity, + int stop_bits) +{ + enum uart_pl011_wlen_t uart_word_len = UART_PL011_WLEN_8; + enum uart_pl011_parity_t uart_parity = UART_PL011_PARITY_DISABLED; + enum uart_pl011_stopbit_t uart_stop_bits = UART_PL011_STOPBIT_1; + switch (data_bits) { + case 5: + uart_word_len = UART_PL011_WLEN_5; + break; + case 6: + uart_word_len = UART_PL011_WLEN_6; + break; + case 7: + uart_word_len = UART_PL011_WLEN_7; + break; + case 8: + uart_word_len = UART_PL011_WLEN_8; + break; + default: + error("serial_format: unexpected data bits"); + } + switch (parity) { + case ParityNone: + uart_parity = UART_PL011_PARITY_DISABLED; + break; + case ParityOdd: + uart_parity = UART_PL011_PARITY_ODD; + break; + case ParityEven: + uart_parity = UART_PL011_PARITY_EVEN; + break; + case ParityForced1: + uart_parity = UART_PL011_PARITY_STICKY_ONE; + break; + case ParityForced0: + uart_parity = UART_PL011_PARITY_STICKY_ZERO; + break; + default: + error("serial_format: unexpected parity"); + } + switch (stop_bits) { + case 1: + uart_stop_bits = UART_PL011_STOPBIT_1; + break; + case 2: + uart_stop_bits = UART_PL011_STOPBIT_2; + break; + default: + error("serial_format: unexpected stop bit"); + } + (void)uart_pl011_set_format(obj->uart_dev, + uart_word_len, uart_parity, uart_stop_bits); +} + +void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) +{ + uart_irq[obj->uart_index].handler = handler; + uart_irq[obj->uart_index].id = id; +} + +void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) +{ + switch(irq) { + case RxIrq: + if (enable) { + NVIC_EnableIRQ(obj->rx_irq); + uart_pl011_enable_intr(obj->uart_dev, UART_PL011_RX_INTR_MASK); + NVIC_EnableIRQ(obj->rx_timeout_irq); + uart_pl011_enable_intr(obj->uart_dev, UART_PL011_RT_INTR_MASK); + } else { + uart_pl011_disable_intr(obj->uart_dev, UART_PL011_RX_INTR_MASK); + NVIC_DisableIRQ(obj->rx_irq); + uart_pl011_disable_intr(obj->uart_dev, UART_PL011_RT_INTR_MASK); + NVIC_DisableIRQ(obj->rx_timeout_irq); + } + break; + case TxIrq: + if (enable) { + NVIC_EnableIRQ(obj->tx_irq); + uart_pl011_enable_intr(obj->uart_dev, UART_PL011_TX_INTR_MASK); + } else { + uart_pl011_disable_intr(obj->uart_dev, UART_PL011_TX_INTR_MASK); + NVIC_DisableIRQ(obj->tx_irq); + } + break; + default : return; + } +} + +int serial_readable(serial_t *obj) +{ + return (int)uart_pl011_is_readable(obj->uart_dev); +} + +int serial_writable(serial_t *obj) +{ + return (int)uart_pl011_is_writable(obj->uart_dev); +} + +int serial_getc(serial_t *obj) +{ + uint8_t byte = 0; + while(!uart_pl011_is_readable(obj->uart_dev)); + (void)uart_pl011_read(obj->uart_dev, &byte); + return byte; +} + +void serial_putc(serial_t *obj, int c) +{ + while(!uart_pl011_is_writable(obj->uart_dev)); + uart_pl011_write(obj->uart_dev, (uint8_t)c); +} + +void serial_clear(serial_t *obj) +{ + uart_pl011_write(obj->uart_dev, (uint8_t)0); +} + +void serial_pinout_tx(PinName tx) +{ + pinmap_pinout(tx, PinMap_UART_TX); +} + +void serial_break_set(serial_t *obj) +{ + uart_pl011_enable_break(obj->uart_dev); +} + +void serial_break_clear(serial_t *obj) +{ + uart_pl011_disable_break(obj->uart_dev); +} + +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, + PinName txflow) +{ + error("serial_set_flow_control: Flow control is not supported in MUSCA"); +} + +const PinMap *serial_tx_pinmap() +{ + return PinMap_UART_TX; +} + +const PinMap *serial_rx_pinmap() +{ + return PinMap_UART_RX; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/sleep_api.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/sleep_api.c new file mode 100644 index 0000000000..de49722315 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/sleep_api.c @@ -0,0 +1,48 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device_cfg.h" +#include "sleep_api.h" +#include "timer_cmsdk_drv.h" + +#if DEVICE_SLEEP + +void hal_sleep(void) +{ + __WFI(); +} + +/* Since there is no power management implemented in Musca-A, Deep Sleep could + * be supported only by additional software components, registering and managing + * the currently configured IPs. This would also mean a huge implementation + * overhead, that is not intended to be added. Therefore, Deep Sleep is almost + * identical to Sleep, representing a "Waiting For Interrupt" state, and + * disabling the Microsec ticker in addition. + */ +void hal_deepsleep(void) +{ +#ifdef USEC_TIMER_DEV + timer_cmsdk_disable(&USEC_TIMER_DEV); +#endif + __WFI(); +#ifdef USEC_TIMER_DEV + timer_cmsdk_enable(&USEC_TIMER_DEV); +#endif +} + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/us_ticker.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/us_ticker.c new file mode 100644 index 0000000000..006d7fbc50 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/us_ticker.c @@ -0,0 +1,124 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Supports the High-resolution Ticker for mbed by implementing + * \ref us_ticker_api.h, using a CMSDK Timer \ref timer_cmsdk_dev_t. + */ + +#include "device.h" +#include "mbed_critical.h" +#include "timer_cmsdk_drv.h" +#include "us_ticker_api.h" + +static uint64_t total_ticks = 0; +/* Stores the last reload value, or the last tick value read when a read API + * call occurs from the upper layer, needed to keep total_ticks + * accumulated properly. + */ +static uint32_t previous_ticks = 0; + +static void restart_timer(uint32_t new_reload) +{ + timer_cmsdk_disable(&USEC_TIMER_DEV); + timer_cmsdk_set_reload_value(&USEC_TIMER_DEV, + new_reload); + timer_cmsdk_reset(&USEC_TIMER_DEV); + timer_cmsdk_clear_interrupt(&USEC_TIMER_DEV); + timer_cmsdk_enable_interrupt(&USEC_TIMER_DEV); + timer_cmsdk_enable(&USEC_TIMER_DEV); +} + +static void update_ticker(void) +{ + if (timer_cmsdk_is_interrupt_active(&USEC_TIMER_DEV)) { + total_ticks += previous_ticks; + previous_ticks = TIMER_CMSDK_MAX_RELOAD; + restart_timer(previous_ticks); + } else { + uint32_t tick = timer_cmsdk_get_current_value(&USEC_TIMER_DEV); + + if (tick < previous_ticks) { + uint32_t delta = previous_ticks - tick; + total_ticks += delta; + previous_ticks = tick; + } + } +} + +void us_ticker_init(void) +{ + timer_cmsdk_init(&USEC_TIMER_DEV); + previous_ticks = TIMER_CMSDK_MAX_RELOAD; + NVIC_EnableIRQ(USEC_INTERVAL_IRQ); + restart_timer(previous_ticks); +} + +void us_ticker_free(void) +{ + timer_cmsdk_disable(&USEC_TIMER_DEV); +} + +uint32_t us_ticker_read(void) +{ + core_util_critical_section_enter(); + update_ticker(); + core_util_critical_section_exit(); + + return (uint32_t)(total_ticks >> USEC_REPORTED_SHIFT); +} + +void us_ticker_set_interrupt(timestamp_t timestamp) +{ + uint32_t reload = (timestamp - us_ticker_read()) << USEC_REPORTED_SHIFT; + previous_ticks = reload; + restart_timer(previous_ticks); +} + +void us_ticker_disable_interrupt(void) +{ + timer_cmsdk_disable_interrupt(&USEC_TIMER_DEV); +} + +void us_ticker_clear_interrupt(void) +{ + timer_cmsdk_clear_interrupt(&USEC_TIMER_DEV); +} + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(USEC_INTERVAL_IRQ); +} + +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + USEC_REPORTED_FREQ_HZ, + USEC_REPORTED_BITS + }; + return &info; +} + +#ifndef usec_interval_irq_handler +#error "usec_interval_irq_handler should be defined, check device_cfg.h!" +#endif +void usec_interval_irq_handler(void) +{ + update_ticker(); + us_ticker_irq_handler(); +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Config/RTE_Device.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Config/RTE_Device.h new file mode 100644 index 0000000000..183fa7ecf4 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Config/RTE_Device.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2018-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- + +#ifndef __RTE_DEVICE_H +#define __RTE_DEVICE_H + +// MPC (Memory Protection Controller) [Driver_ISRAM0_MPC] +// Configuration settings for Driver_ISRAM0_MPC in component ::Drivers:MPC +#define RTE_ISRAM0_MPC 1 +// MPC (Memory Protection Controller) [Driver_ISRAM0_MPC] + +// MPC (Memory Protection Controller) [Driver_ISRAM1_MPC] +// Configuration settings for Driver_SRAM1_MPC in component ::Drivers:MPC +#define RTE_ISRAM1_MPC 1 +// MPC (Memory Protection Controller) [Driver_ISRAM1_MPC] + +// MPC (Memory Protection Controller) [Driver_ISRAM2_MPC] +// Configuration settings for Driver_ISRAM2_MPC in component ::Drivers:MPC +#define RTE_ISRAM2_MPC 1 +// MPC (Memory Protection Controller) [Driver_ISRAM2_MPC] + +// MPC (Memory Protection Controller) [Driver_ISRAM3_MPC] +// Configuration settings for Driver_SRAM2_MPC in component ::Drivers:MPC +#define RTE_ISRAM3_MPC 1 +// MPC (Memory Protection Controller) [Driver_SRAM3_MPC] + +// MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC] +// Configuration settings for Driver_CODE_SRAM_MPC in component ::Drivers:MPC +#define RTE_CODE_SRAM_MPC 1 +// MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC] + +// MPC (Memory Protection Controller) [Driver_QSPI_MPC] +// Configuration settings for Driver_QSPI_MPC in component ::Drivers:MPC +#define RTE_QSPI_MPC 1 +// MPC (Memory Protection Controller) [Driver_QSPI_MPC] + +// USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0] +// Configuration settings for Driver_USART0 in component ::Drivers:USART +#define RTE_USART0 1 +// USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0] + +// USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1] +// Configuration settings for Driver_USART1 in component ::Drivers:USART +#define RTE_USART1 1 +// USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1] + +// PPC (Peripheral Protection Controller) [Driver_AHB_PPC0] +// Configuration settings for Driver_AHB_PPC0 in component ::Drivers:PPC +#define RTE_AHB_PPC0 1 +// PPC (Peripheral Protection Controller) [Driver_AHB_PPC0] + +// PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0] +// Configuration settings for Driver_AHB_PPCEXP0 in component ::Drivers:PPC +#define RTE_AHB_PPCEXP0 0 +// PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0] + +// PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1] +// Configuration settings for Driver_AHB_PPCEXP1 in component ::Drivers:PPC +#define RTE_AHB_PPCEXP1 0 +// PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1] + +// PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2] +// Configuration settings for Driver_AHB_PPCEXP2 in component ::Drivers:PPC +#define RTE_AHB_PPCEXP2 0 +// PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2] + +// PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3] +// Configuration settings for Driver_AHB_PPCEXP3 in component ::Drivers:PPC +#define RTE_AHB_PPCEXP3 0 +// PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3] + +// PPC (Peripheral Protection Controller) [Driver_APB_PPC0] +// Configuration settings for Driver_APB_PPC0 in component ::Drivers:PPC +#define RTE_APB_PPC0 1 +// PPC (Peripheral Protection Controller) [Driver_APB_PPC0] + +// PPC (Peripheral Protection Controller) [Driver_APB_PPC1] +// Configuration settings for Driver_APB_PPC1 in component ::Drivers:PPC +#define RTE_APB_PPC1 1 +// PPC (Peripheral Protection Controller) [Driver_APB_PPC1] + +// PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0] +// Configuration settings for Driver_APB_PPCEXP0 in component ::Drivers:PPC +#define RTE_APB_PPCEXP0 0 +// PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0] + +// PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1] +// Configuration settings for Driver_APB_PPCEXP1 in component ::Drivers:PPC +#define RTE_APB_PPCEXP1 0 +// PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1] + +// PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2] +// Configuration settings for Driver_APB_PPCEXP2 in component ::Drivers:PPC +#define RTE_APB_PPCEXP2 0 +// PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2] + +// PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3] +// Configuration settings for Driver_APB_PPCEXP3 in component ::Drivers:PPC +#define RTE_APB_PPCEXP3 0 +// PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3] + +// FLASH (Flash Memory) [Driver_FLASH0] +// Configuration settings for Driver_FLASH0 in component ::Drivers:FLASH +#define RTE_FLASH0 1 +// FLASH (Flash Memory) [Driver_FLASH0] + +#endif /* __RTE_DEVICE_H */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Config/cmsis_driver_config.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Config/cmsis_driver_config.h new file mode 100644 index 0000000000..e50850a407 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Config/cmsis_driver_config.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_DRIVER_CONFIG_H__ +#define __CMSIS_DRIVER_CONFIG_H__ + +#include "device_cfg.h" +#include "platform_retarget_dev.h" +#include "platform_retarget_pins.h" +#include "RTE_Device.h" +#include "target_cfg.h" + +#define UART0_DEV UART0_PL011_DEV_NS +#define UART1_DEV UART1_PL011_DEV_NS + +#define FLASH0_DEV MT25QL_DEV_NS + +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S +#define MPC_ISRAM1_DEV MPC_ISRAM1_DEV_S +#define MPC_ISRAM2_DEV MPC_ISRAM2_DEV_S +#define MPC_ISRAM3_DEV MPC_ISRAM3_DEV_S +#define MPC_CODE_SRAM_DEV MPC_CODE_SRAM_DEV_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S + +#define AHB_PPC0_DEV AHB_PPC0_DEV_S +#define AHB_PPCEXP0_DEV AHB_PPCEXP0_DEV_S +#define AHB_PPCEXP1_DEV AHB_PPCEXP1_DEV_S +#define AHB_PPCEXP2_DEV AHB_PPCEXP2_DEV_S +#define AHB_PPCEXP3_DEV AHB_PPCEXP3_DEV_S +#define APB_PPC0_DEV APB_PPC0_DEV_S +#define APB_PPC1_DEV APB_PPC1_DEV_S +#define APB_PPCEXP0_DEV APB_PPCEXP0_DEV_S +#define APB_PPCEXP1_DEV APB_PPCEXP1_DEV_S +#define APB_PPCEXP2_DEV APB_PPCEXP2_DEV_S +#define APB_PPCEXP3_DEV APB_PPCEXP3_DEV_S + +#define MUSCA_A1_SCC_DEV MUSCA_A1_SCC_DEV_S + +#endif /* __CMSIS_DRIVER_CONFIG_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_Common.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_Common.h new file mode 100644 index 0000000000..cdf44b3325 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_Common.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013-2016 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Date: 2. Jan 2014 + * $Revision: V2.00 + * + * Project: Common Driver definitions + */ + +/* History: + * Version 2.00 + * Changed prefix ARM_DRV -> ARM_DRIVER + * Added General return codes definitions + * Version 1.10 + * Namespace prefix ARM_ added + * Version 1.00 + * Initial release + */ + +#ifndef __DRIVER_COMMON_H +#define __DRIVER_COMMON_H + +#include +#include +#include + +#define ARM_DRIVER_VERSION_MAJOR_MINOR(major,minor) (((major) << 8) | (minor)) + +/** +\brief Driver Version +*/ +typedef struct _ARM_DRIVER_VERSION { + uint16_t api; ///< API version + uint16_t drv; ///< Driver version +} ARM_DRIVER_VERSION; + +/* General return codes */ +#define ARM_DRIVER_OK 0 ///< Operation succeeded +#define ARM_DRIVER_ERROR -1 ///< Unspecified error +#define ARM_DRIVER_ERROR_BUSY -2 ///< Driver is busy +#define ARM_DRIVER_ERROR_TIMEOUT -3 ///< Timeout occurred +#define ARM_DRIVER_ERROR_UNSUPPORTED -4 ///< Operation not supported +#define ARM_DRIVER_ERROR_PARAMETER -5 ///< Parameter error +#define ARM_DRIVER_ERROR_SPECIFIC -6 ///< Start of driver specific errors + +/** +\brief General power states +*/ +typedef enum _ARM_POWER_STATE { + ARM_POWER_OFF, ///< Power off: no operation possible + ARM_POWER_LOW, ///< Low Power mode: retain state, detect and signal wake-up events + ARM_POWER_FULL ///< Power on: full operation at maximum performance +} ARM_POWER_STATE; + +#endif /* __DRIVER_COMMON_H */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_MPC.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_MPC.c new file mode 100644 index 0000000000..f143bec58e --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_MPC.c @@ -0,0 +1,1169 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "Driver_MPC.h" + +#include "cmsis.h" +#include "cmsis_driver_config.h" +#include "RTE_Device.h" + +/* driver version */ +#define ARM_MPC_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0) + +/* Driver Version */ +static const ARM_DRIVER_VERSION DriverVersion = { + ARM_MPC_API_VERSION, + ARM_MPC_DRV_VERSION +}; + +static ARM_DRIVER_VERSION ARM_MPC_GetVersion(void) +{ + return DriverVersion; +} + +/* + * \brief Translates error codes from native API to CMSIS API. + * + * \param[in] err Error code to translate (\ref mpc_sie200_error_t). + * + * \return Returns CMSIS error code. + */ +static int32_t error_trans(enum mpc_sie200_error_t err) +{ + switch(err) { + case MPC_SIE200_ERR_NONE: + return ARM_DRIVER_OK; + case MPC_SIE200_INVALID_ARG: + return ARM_DRIVER_ERROR_PARAMETER; + case MPC_SIE200_NOT_INIT: + return ARM_MPC_ERR_NOT_INIT; + case MPC_SIE200_ERR_NOT_IN_RANGE: + return ARM_MPC_ERR_NOT_IN_RANGE; + case MPC_SIE200_ERR_NOT_ALIGNED: + return ARM_MPC_ERR_NOT_ALIGNED; + case MPC_SIE200_ERR_INVALID_RANGE: + return ARM_MPC_ERR_INVALID_RANGE; + case MPC_SIE200_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE: + return ARM_MPC_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE; + default: + return ARM_MPC_ERR_UNSPECIFIED; + } +} + +#if (RTE_ISRAM0_MPC) +/* Ranges controlled by this ISRAM0_MPC */ +static const struct mpc_sie200_memory_range_t MPC_ISRAM0_RANGE_S = { + .base = MPC_ISRAM0_RANGE_BASE_S, + .limit = MPC_ISRAM0_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_SECURE +}; + +static const struct mpc_sie200_memory_range_t MPC_ISRAM0_RANGE_NS = { + .base = MPC_ISRAM0_RANGE_BASE_NS, + .limit = MPC_ISRAM0_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_NONSECURE +}; + +#define MPC_ISRAM0_RANGE_LIST_LEN 2u +static const struct mpc_sie200_memory_range_t* MPC_ISRAM0_RANGE_LIST[MPC_ISRAM0_RANGE_LIST_LEN]= + {&MPC_ISRAM0_RANGE_S, &MPC_ISRAM0_RANGE_NS}; + +/* ISRAM0_MPC Driver wrapper functions */ +static int32_t ISRAM0_MPC_Initialize(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_init(&MPC_ISRAM0_DEV, + MPC_ISRAM0_RANGE_LIST, + MPC_ISRAM0_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ISRAM0_MPC_GetBlockSize(uint32_t* blk_size) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_block_size(&MPC_ISRAM0_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_GetCtrlConfig(uint32_t* ctrl_val) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_ctrl(&MPC_ISRAM0_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_set_ctrl(&MPC_ISRAM0_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR* attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_region_config(&MPC_ISRAM0_DEV, base, limit, + (enum mpc_sie200_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_config_region(&MPC_ISRAM0_DEV, base, limit, + (enum mpc_sie200_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_EnableInterrupt(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_irq_enable(&MPC_ISRAM0_DEV); + + return error_trans(ret); +} + +static void ISRAM0_MPC_DisableInterrupt(void) +{ + mpc_sie200_irq_disable(&MPC_ISRAM0_DEV); +} + + +static void ISRAM0_MPC_ClearInterrupt(void) +{ + mpc_sie200_clear_irq(&MPC_ISRAM0_DEV); +} + +static uint32_t ISRAM0_MPC_InterruptState(void) +{ + return mpc_sie200_irq_state(&MPC_ISRAM0_DEV); +} + +static int32_t ISRAM0_MPC_LockDown(void) +{ + return mpc_sie200_lock_down(&MPC_ISRAM0_DEV); +} + +/* ISRAM0_MPC Driver CMSIS access structure */ +extern ARM_DRIVER_MPC Driver_ISRAM0_MPC; +ARM_DRIVER_MPC Driver_ISRAM0_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = ISRAM0_MPC_Initialize, + .Uninitialize = ISRAM0_MPC_Uninitialize, + .GetBlockSize = ISRAM0_MPC_GetBlockSize, + .GetCtrlConfig = ISRAM0_MPC_GetCtrlConfig, + .SetCtrlConfig = ISRAM0_MPC_SetCtrlConfig, + .ConfigRegion = ISRAM0_MPC_ConfigRegion, + .GetRegionConfig = ISRAM0_MPC_GetRegionConfig, + .EnableInterrupt = ISRAM0_MPC_EnableInterrupt, + .DisableInterrupt = ISRAM0_MPC_DisableInterrupt, + .ClearInterrupt = ISRAM0_MPC_ClearInterrupt, + .InterruptState = ISRAM0_MPC_InterruptState, + .LockDown = ISRAM0_MPC_LockDown, +}; +#endif /* RTE_ISRAM0_MPC */ + +#if (RTE_ISRAM1_MPC) +/* Ranges controlled by this ISRAM1_MPC */ +static const struct mpc_sie200_memory_range_t MPC_ISRAM1_RANGE_S = { + .base = MPC_ISRAM1_RANGE_BASE_S, + .limit = MPC_ISRAM1_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_SECURE +}; + +static const struct mpc_sie200_memory_range_t MPC_ISRAM1_RANGE_NS = { + .base = MPC_ISRAM1_RANGE_BASE_NS, + .limit = MPC_ISRAM1_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_NONSECURE +}; + +#define MPC_ISRAM1_RANGE_LIST_LEN 2u +static const struct mpc_sie200_memory_range_t* MPC_ISRAM1_RANGE_LIST[MPC_ISRAM1_RANGE_LIST_LEN]= + {&MPC_ISRAM1_RANGE_S, &MPC_ISRAM1_RANGE_NS}; + +/* ISRAM1_MPC Driver wrapper functions */ +static int32_t ISRAM1_MPC_Initialize(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_init(&MPC_ISRAM1_DEV, + MPC_ISRAM1_RANGE_LIST, + MPC_ISRAM1_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ISRAM1_MPC_GetBlockSize(uint32_t* blk_size) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_block_size(&MPC_ISRAM1_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_GetCtrlConfig(uint32_t* ctrl_val) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_ctrl(&MPC_ISRAM1_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_set_ctrl(&MPC_ISRAM1_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR* attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_region_config(&MPC_ISRAM1_DEV, base, limit, + (enum mpc_sie200_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_config_region(&MPC_ISRAM1_DEV, base, limit, + (enum mpc_sie200_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_EnableInterrupt(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_irq_enable(&MPC_ISRAM1_DEV); + + return error_trans(ret); +} + +static void ISRAM1_MPC_DisableInterrupt(void) +{ + mpc_sie200_irq_disable(&MPC_ISRAM1_DEV); +} + + +static void ISRAM1_MPC_ClearInterrupt(void) +{ + mpc_sie200_clear_irq(&MPC_ISRAM1_DEV); +} + +static uint32_t ISRAM1_MPC_InterruptState(void) +{ + return mpc_sie200_irq_state(&MPC_ISRAM1_DEV); +} + +static int32_t ISRAM1_MPC_LockDown(void) +{ + return mpc_sie200_lock_down(&MPC_ISRAM1_DEV); +} + +/* ISRAM1_MPC Driver CMSIS access structure */ +extern ARM_DRIVER_MPC Driver_ISRAM1_MPC; +ARM_DRIVER_MPC Driver_ISRAM1_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = ISRAM1_MPC_Initialize, + .Uninitialize = ISRAM1_MPC_Uninitialize, + .GetBlockSize = ISRAM1_MPC_GetBlockSize, + .GetCtrlConfig = ISRAM1_MPC_GetCtrlConfig, + .SetCtrlConfig = ISRAM1_MPC_SetCtrlConfig, + .ConfigRegion = ISRAM1_MPC_ConfigRegion, + .GetRegionConfig = ISRAM1_MPC_GetRegionConfig, + .EnableInterrupt = ISRAM1_MPC_EnableInterrupt, + .DisableInterrupt = ISRAM1_MPC_DisableInterrupt, + .ClearInterrupt = ISRAM1_MPC_ClearInterrupt, + .InterruptState = ISRAM1_MPC_InterruptState, + .LockDown = ISRAM1_MPC_LockDown, +}; +#endif /* RTE_ISRAM1_MPC */ + +#if (RTE_ISRAM2_MPC) +/* Ranges controlled by this ISRAM2_MPC */ +static const struct mpc_sie200_memory_range_t MPC_ISRAM2_RANGE_S = { + .base = MPC_ISRAM2_RANGE_BASE_S, + .limit = MPC_ISRAM2_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_SECURE +}; + +static const struct mpc_sie200_memory_range_t MPC_ISRAM2_RANGE_NS = { + .base = MPC_ISRAM2_RANGE_BASE_NS, + .limit = MPC_ISRAM2_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_NONSECURE +}; + +#define MPC_ISRAM2_RANGE_LIST_LEN 2u +static const struct mpc_sie200_memory_range_t* MPC_ISRAM2_RANGE_LIST[MPC_ISRAM2_RANGE_LIST_LEN]= + {&MPC_ISRAM2_RANGE_S, &MPC_ISRAM2_RANGE_NS}; + +/* ISRAM2_MPC Driver wrapper functions */ +static int32_t ISRAM2_MPC_Initialize(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_init(&MPC_ISRAM2_DEV, + MPC_ISRAM2_RANGE_LIST, + MPC_ISRAM2_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t ISRAM2_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ISRAM2_MPC_GetBlockSize(uint32_t* blk_size) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_block_size(&MPC_ISRAM2_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t ISRAM2_MPC_GetCtrlConfig(uint32_t* ctrl_val) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_ctrl(&MPC_ISRAM2_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t ISRAM2_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_set_ctrl(&MPC_ISRAM2_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t ISRAM2_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR* attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_region_config(&MPC_ISRAM2_DEV, base, limit, + (enum mpc_sie200_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t ISRAM2_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_config_region(&MPC_ISRAM2_DEV, base, limit, + (enum mpc_sie200_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t ISRAM2_MPC_EnableInterrupt(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_irq_enable(&MPC_ISRAM2_DEV); + + return error_trans(ret); +} + +static void ISRAM2_MPC_DisableInterrupt(void) +{ + mpc_sie200_irq_disable(&MPC_ISRAM2_DEV); +} + +static void ISRAM2_MPC_ClearInterrupt(void) +{ + mpc_sie200_clear_irq(&MPC_ISRAM2_DEV); +} + +static uint32_t ISRAM2_MPC_InterruptState(void) +{ + return mpc_sie200_irq_state(&MPC_ISRAM2_DEV); +} + +static int32_t ISRAM2_MPC_LockDown(void) +{ + return mpc_sie200_lock_down(&MPC_ISRAM2_DEV); +} + +/* ISRAM2_MPC Driver CMSIS access structure */ +extern ARM_DRIVER_MPC Driver_ISRAM2_MPC; +ARM_DRIVER_MPC Driver_ISRAM2_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = ISRAM2_MPC_Initialize, + .Uninitialize = ISRAM2_MPC_Uninitialize, + .GetBlockSize = ISRAM2_MPC_GetBlockSize, + .GetCtrlConfig = ISRAM2_MPC_GetCtrlConfig, + .SetCtrlConfig = ISRAM2_MPC_SetCtrlConfig, + .ConfigRegion = ISRAM2_MPC_ConfigRegion, + .GetRegionConfig = ISRAM2_MPC_GetRegionConfig, + .EnableInterrupt = ISRAM2_MPC_EnableInterrupt, + .DisableInterrupt = ISRAM2_MPC_DisableInterrupt, + .ClearInterrupt = ISRAM2_MPC_ClearInterrupt, + .InterruptState = ISRAM2_MPC_InterruptState, + .LockDown = ISRAM2_MPC_LockDown, +}; +#endif /* RTE_ISRAM2_MPC */ + +#if (RTE_ISRAM3_MPC) +/* Ranges controlled by this ISRAM3_MPC */ +static const struct mpc_sie200_memory_range_t MPC_ISRAM3_RANGE_S = { + .base = MPC_ISRAM3_RANGE_BASE_S, + .limit = MPC_ISRAM3_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_SECURE +}; + +static const struct mpc_sie200_memory_range_t MPC_ISRAM3_RANGE_NS = { + .base = MPC_ISRAM3_RANGE_BASE_NS, + .limit = MPC_ISRAM3_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_NONSECURE +}; + +#define MPC_ISRAM3_RANGE_LIST_LEN 2u +static const struct mpc_sie200_memory_range_t* MPC_ISRAM3_RANGE_LIST[MPC_ISRAM3_RANGE_LIST_LEN]= + {&MPC_ISRAM3_RANGE_S, &MPC_ISRAM3_RANGE_NS}; + +/* ISRAM3_MPC Driver wrapper functions */ +static int32_t ISRAM3_MPC_Initialize(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_init(&MPC_ISRAM3_DEV, + MPC_ISRAM3_RANGE_LIST, + MPC_ISRAM3_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t ISRAM3_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ISRAM3_MPC_GetBlockSize(uint32_t* blk_size) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_block_size(&MPC_ISRAM3_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t ISRAM3_MPC_GetCtrlConfig(uint32_t* ctrl_val) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_ctrl(&MPC_ISRAM3_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t ISRAM3_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_set_ctrl(&MPC_ISRAM3_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t ISRAM3_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR* attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_region_config(&MPC_ISRAM3_DEV, base, limit, + (enum mpc_sie200_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t ISRAM3_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_config_region(&MPC_ISRAM3_DEV, base, limit, + (enum mpc_sie200_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t ISRAM3_MPC_EnableInterrupt(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_irq_enable(&MPC_ISRAM3_DEV); + + return error_trans(ret); +} + +static void ISRAM3_MPC_DisableInterrupt(void) +{ + mpc_sie200_irq_disable(&MPC_ISRAM3_DEV); +} + + +static void ISRAM3_MPC_ClearInterrupt(void) +{ + mpc_sie200_clear_irq(&MPC_ISRAM3_DEV); +} + +static uint32_t ISRAM3_MPC_InterruptState(void) +{ + return mpc_sie200_irq_state(&MPC_ISRAM3_DEV); +} + +static int32_t ISRAM3_MPC_LockDown(void) +{ + return mpc_sie200_lock_down(&MPC_ISRAM3_DEV); +} + +/* ISRAM3_MPC Driver CMSIS access structure */ +extern ARM_DRIVER_MPC Driver_ISRAM3_MPC; +ARM_DRIVER_MPC Driver_ISRAM3_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = ISRAM3_MPC_Initialize, + .Uninitialize = ISRAM3_MPC_Uninitialize, + .GetBlockSize = ISRAM3_MPC_GetBlockSize, + .GetCtrlConfig = ISRAM3_MPC_GetCtrlConfig, + .SetCtrlConfig = ISRAM3_MPC_SetCtrlConfig, + .ConfigRegion = ISRAM3_MPC_ConfigRegion, + .GetRegionConfig = ISRAM3_MPC_GetRegionConfig, + .EnableInterrupt = ISRAM3_MPC_EnableInterrupt, + .DisableInterrupt = ISRAM3_MPC_DisableInterrupt, + .ClearInterrupt = ISRAM3_MPC_ClearInterrupt, + .InterruptState = ISRAM3_MPC_InterruptState, + .LockDown = ISRAM3_MPC_LockDown, +}; +#endif /* RTE_ISRAM3_MPC */ + +#if (RTE_CODE_SRAM_MPC) +/* Ranges controlled by this CODE_SRAM_MPC */ +static const struct mpc_sie200_memory_range_t MPC_CODE_SRAM_RANGE_S = { + .base = MPC_CODE_SRAM_RANGE_BASE_S, + .limit = MPC_CODE_SRAM_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_SECURE +}; + +static const struct mpc_sie200_memory_range_t MPC_CODE_SRAM_RANGE_NS = { + .base = MPC_CODE_SRAM_RANGE_BASE_NS, + .limit = MPC_CODE_SRAM_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_NONSECURE +}; + +#define MPC_CODE_SRAM_RANGE_LIST_LEN 2u +static const struct mpc_sie200_memory_range_t* MPC_CODE_SRAM_RANGE_LIST[MPC_CODE_SRAM_RANGE_LIST_LEN]= + {&MPC_CODE_SRAM_RANGE_S, &MPC_CODE_SRAM_RANGE_NS}; + +/* CODE_SRAM_MPC Driver wrapper functions */ +static int32_t CODE_SRAM_MPC_Initialize(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_init(&MPC_CODE_SRAM_DEV, + MPC_CODE_SRAM_RANGE_LIST, + MPC_CODE_SRAM_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t CODE_SRAM_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t CODE_SRAM_MPC_GetBlockSize(uint32_t* blk_size) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_block_size(&MPC_CODE_SRAM_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t CODE_SRAM_MPC_GetCtrlConfig(uint32_t* ctrl_val) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_ctrl(&MPC_CODE_SRAM_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t CODE_SRAM_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_set_ctrl(&MPC_CODE_SRAM_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t CODE_SRAM_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR* attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_region_config(&MPC_CODE_SRAM_DEV, base, limit, + (enum mpc_sie200_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t CODE_SRAM_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_config_region(&MPC_CODE_SRAM_DEV, base, limit, + (enum mpc_sie200_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t CODE_SRAM_MPC_EnableInterrupt(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_irq_enable(&MPC_CODE_SRAM_DEV); + + return error_trans(ret); +} + +static void CODE_SRAM_MPC_DisableInterrupt(void) +{ + mpc_sie200_irq_disable(&MPC_CODE_SRAM_DEV); +} + + +static void CODE_SRAM_MPC_ClearInterrupt(void) +{ + mpc_sie200_clear_irq(&MPC_CODE_SRAM_DEV); +} + +static uint32_t CODE_SRAM_MPC_InterruptState(void) +{ + return mpc_sie200_irq_state(&MPC_CODE_SRAM_DEV); +} + +static int32_t CODE_SRAM_MPC_LockDown(void) +{ + return mpc_sie200_lock_down(&MPC_CODE_SRAM_DEV); +} + +/* CODE_SRAM_MPC Driver CMSIS access structure */ +extern ARM_DRIVER_MPC Driver_CODE_SRAM_MPC; +ARM_DRIVER_MPC Driver_CODE_SRAM_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = CODE_SRAM_MPC_Initialize, + .Uninitialize = CODE_SRAM_MPC_Uninitialize, + .GetBlockSize = CODE_SRAM_MPC_GetBlockSize, + .GetCtrlConfig = CODE_SRAM_MPC_GetCtrlConfig, + .SetCtrlConfig = CODE_SRAM_MPC_SetCtrlConfig, + .ConfigRegion = CODE_SRAM_MPC_ConfigRegion, + .GetRegionConfig = CODE_SRAM_MPC_GetRegionConfig, + .EnableInterrupt = CODE_SRAM_MPC_EnableInterrupt, + .DisableInterrupt = CODE_SRAM_MPC_DisableInterrupt, + .ClearInterrupt = CODE_SRAM_MPC_ClearInterrupt, + .InterruptState = CODE_SRAM_MPC_InterruptState, + .LockDown = CODE_SRAM_MPC_LockDown, +}; +#endif /* RTE_CODE_SRAM_MPC */ + +#if (RTE_SSRAM2_MPC) +/* Ranges controlled by this SSRAM2_MPC */ +static const struct mpc_sie200_memory_range_t MPC_SSRAM2_RANGE_S = { + .base = MPC_SSRAM2_RANGE_BASE_S, + .limit = MPC_SSRAM2_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_SECURE +}; + +static const struct mpc_sie200_memory_range_t MPC_SSRAM2_RANGE_NS = { + .base = MPC_SSRAM2_RANGE_BASE_NS, + .limit = MPC_SSRAM2_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_NONSECURE +}; + +#define MPC_SSRAM2_RANGE_LIST_LEN 2u +static const struct mpc_sie200_memory_range_t* MPC_SSRAM2_RANGE_LIST[MPC_SSRAM2_RANGE_LIST_LEN]= + {&MPC_SSRAM2_RANGE_S, &MPC_SSRAM2_RANGE_NS}; + +/* SSRAM2_MPC Driver wrapper functions */ +static int32_t SSRAM2_MPC_Initialize(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_init(&MPC_SSRAM2_DEV, + MPC_SSRAM2_RANGE_LIST, + MPC_SSRAM2_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t SSRAM2_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t SSRAM2_MPC_GetBlockSize(uint32_t* blk_size) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_block_size(&MPC_SSRAM2_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t SSRAM2_MPC_GetCtrlConfig(uint32_t* ctrl_val) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_ctrl(&MPC_SSRAM2_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t SSRAM2_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_set_ctrl(&MPC_SSRAM2_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t SSRAM2_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR* attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_region_config(&MPC_SSRAM2_DEV, base, limit, + (enum mpc_sie200_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t SSRAM2_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_config_region(&MPC_SSRAM2_DEV, base, limit, + (enum mpc_sie200_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t SSRAM2_MPC_EnableInterrupt(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_irq_enable(&MPC_SSRAM2_DEV); + + return error_trans(ret); +} + +static void SSRAM2_MPC_DisableInterrupt(void) +{ + mpc_sie200_irq_disable(&MPC_SSRAM2_DEV); +} + + +static void SSRAM2_MPC_ClearInterrupt(void) +{ + mpc_sie200_clear_irq(&MPC_SSRAM2_DEV); +} + +static uint32_t SSRAM2_MPC_InterruptState(void) +{ + return mpc_sie200_irq_state(&MPC_SSRAM2_DEV); +} + +static int32_t SSRAM2_MPC_LockDown(void) +{ + return mpc_sie200_lock_down(&MPC_SSRAM2_DEV); +} + +/* SSRAM2_MPC Driver CMSIS access structure */ +extern ARM_DRIVER_MPC Driver_SRAM2_MPC; +ARM_DRIVER_MPC Driver_SRAM2_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = SSRAM2_MPC_Initialize, + .Uninitialize = SSRAM2_MPC_Uninitialize, + .GetBlockSize = SSRAM2_MPC_GetBlockSize, + .GetCtrlConfig = SSRAM2_MPC_GetCtrlConfig, + .SetCtrlConfig = SSRAM2_MPC_SetCtrlConfig, + .ConfigRegion = SSRAM2_MPC_ConfigRegion, + .GetRegionConfig = SSRAM2_MPC_GetRegionConfig, + .EnableInterrupt = SSRAM2_MPC_EnableInterrupt, + .DisableInterrupt = SSRAM2_MPC_DisableInterrupt, + .ClearInterrupt = SSRAM2_MPC_ClearInterrupt, + .InterruptState = SSRAM2_MPC_InterruptState, + .LockDown = SSRAM2_MPC_LockDown, +}; +#endif /* RTE_SSRAM2_MPC */ + +#if (RTE_SSRAM3_MPC) +/* Ranges controlled by this SSRAM3_MPC */ +static const struct mpc_sie200_memory_range_t MPC_SSRAM3_RANGE_S = { + .base = MPC_SSRAM3_RANGE_BASE_S, + .limit = MPC_SSRAM3_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_SECURE +}; + +static const struct mpc_sie200_memory_range_t MPC_SSRAM3_RANGE_NS = { + .base = MPC_SSRAM3_RANGE_BASE_NS, + .limit = MPC_SSRAM3_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_NONSECURE +}; + +#define MPC_SSRAM3_RANGE_LIST_LEN 2u +static const struct mpc_sie200_memory_range_t* MPC_SSRAM3_RANGE_LIST[MPC_SSRAM3_RANGE_LIST_LEN]= + {&MPC_SSRAM3_RANGE_S, &MPC_SSRAM3_RANGE_NS}; + +/* SSRAM3_MPC Driver wrapper functions */ +static int32_t SSRAM3_MPC_Initialize(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_init(&MPC_SSRAM3_DEV, + MPC_SSRAM3_RANGE_LIST, + MPC_SSRAM3_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t SSRAM3_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t SSRAM3_MPC_GetBlockSize(uint32_t* blk_size) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_block_size(&MPC_SSRAM3_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t SSRAM3_MPC_GetCtrlConfig(uint32_t* ctrl_val) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_ctrl(&MPC_SSRAM3_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t SSRAM3_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_set_ctrl(&MPC_SSRAM3_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t SSRAM3_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR* attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_region_config(&MPC_SSRAM3_DEV, base, limit, + (enum mpc_sie200_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t SSRAM3_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_config_region(&MPC_SSRAM3_DEV, base, limit, + (enum mpc_sie200_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t SSRAM3_MPC_EnableInterrupt(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_irq_enable(&MPC_SSRAM3_DEV); + + return error_trans(ret); +} + +static void SSRAM3_MPC_DisableInterrupt(void) +{ + mpc_sie200_irq_disable(&MPC_SSRAM3_DEV); +} + + +static void SSRAM3_MPC_ClearInterrupt(void) +{ + mpc_sie200_clear_irq(&MPC_SSRAM3_DEV); +} + +static uint32_t SSRAM3_MPC_InterruptState(void) +{ + return mpc_sie200_irq_state(&MPC_SSRAM3_DEV); +} + +static int32_t SSRAM3_MPC_LockDown(void) +{ + return mpc_sie200_lock_down(&MPC_SSRAM3_DEV); +} + +/* SSRAM3_MPC Driver CMSIS access structure */ +extern ARM_DRIVER_MPC Driver_SSRAM3_MPC; +ARM_DRIVER_MPC Driver_SSRAM3_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = SSRAM3_MPC_Initialize, + .Uninitialize = SSRAM3_MPC_Uninitialize, + .GetBlockSize = SSRAM3_MPC_GetBlockSize, + .GetCtrlConfig = SSRAM3_MPC_GetCtrlConfig, + .SetCtrlConfig = SSRAM3_MPC_SetCtrlConfig, + .ConfigRegion = SSRAM3_MPC_ConfigRegion, + .GetRegionConfig = SSRAM3_MPC_GetRegionConfig, + .EnableInterrupt = SSRAM3_MPC_EnableInterrupt, + .DisableInterrupt = SSRAM3_MPC_DisableInterrupt, + .ClearInterrupt = SSRAM3_MPC_ClearInterrupt, + .InterruptState = SSRAM3_MPC_InterruptState, + .LockDown = SSRAM3_MPC_LockDown, +}; +#endif /* RTE_SSRAM3_MPC */ + + +#if (RTE_QSPI_MPC) +/* Ranges controlled by this QSPI_MPC */ +static const struct mpc_sie200_memory_range_t MPC_QSPI_RANGE_S = { + .base = MPC_QSPI_RANGE_BASE_S, + .limit = MPC_QSPI_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_SECURE +}; + +static const struct mpc_sie200_memory_range_t MPC_QSPI_RANGE_NS = { + .base = MPC_QSPI_RANGE_BASE_NS, + .limit = MPC_QSPI_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE200_SEC_ATTR_NONSECURE +}; + +#define MPC_QSPI_RANGE_LIST_LEN 2u +static const struct mpc_sie200_memory_range_t* MPC_QSPI_RANGE_LIST[MPC_QSPI_RANGE_LIST_LEN]= + {&MPC_QSPI_RANGE_S, &MPC_QSPI_RANGE_NS}; + +/* QSPI_MPC Driver wrapper functions */ +static int32_t QSPI_MPC_Initialize(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_init(&MPC_QSPI_DEV, + MPC_QSPI_RANGE_LIST, + MPC_QSPI_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t QSPI_MPC_GetBlockSize(uint32_t* blk_size) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_block_size(&MPC_QSPI_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_GetCtrlConfig(uint32_t* ctrl_val) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_ctrl(&MPC_QSPI_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_set_ctrl(&MPC_QSPI_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR* attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_get_region_config(&MPC_QSPI_DEV, base, limit, + (enum mpc_sie200_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_config_region(&MPC_QSPI_DEV, base, limit, + (enum mpc_sie200_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_EnableInterrupt(void) +{ + enum mpc_sie200_error_t ret; + + ret = mpc_sie200_irq_enable(&MPC_QSPI_DEV); + + return error_trans(ret); +} + +static void QSPI_MPC_DisableInterrupt(void) +{ + mpc_sie200_irq_disable(&MPC_QSPI_DEV); +} + + +static void QSPI_MPC_ClearInterrupt(void) +{ + mpc_sie200_clear_irq(&MPC_QSPI_DEV); +} + +static uint32_t QSPI_MPC_InterruptState(void) +{ + return mpc_sie200_irq_state(&MPC_QSPI_DEV); +} + +static int32_t QSPI_MPC_LockDown(void) +{ + return mpc_sie200_lock_down(&MPC_QSPI_DEV); +} + +/* QSPI1_MPC Driver CMSIS access structure */ +extern ARM_DRIVER_MPC Driver_QSPI_MPC; +ARM_DRIVER_MPC Driver_QSPI_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = QSPI_MPC_Initialize, + .Uninitialize = QSPI_MPC_Uninitialize, + .GetBlockSize = QSPI_MPC_GetBlockSize, + .GetCtrlConfig = QSPI_MPC_GetCtrlConfig, + .SetCtrlConfig = QSPI_MPC_SetCtrlConfig, + .ConfigRegion = QSPI_MPC_ConfigRegion, + .GetRegionConfig = QSPI_MPC_GetRegionConfig, + .EnableInterrupt = QSPI_MPC_EnableInterrupt, + .DisableInterrupt = QSPI_MPC_DisableInterrupt, + .ClearInterrupt = QSPI_MPC_ClearInterrupt, + .InterruptState = QSPI_MPC_InterruptState, + .LockDown = QSPI_MPC_LockDown, +}; +#endif /* RTE_QSPI_MPC */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_MPC.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_MPC.h new file mode 100644 index 0000000000..9ed84ba745 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_MPC.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2016-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __DRIVER_MPC_H +#define __DRIVER_MPC_H + +#include "Driver_Common.h" + +/* API version */ +#define ARM_MPC_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0) + +/* Error code returned by the driver functions */ +#define ARM_MPC_ERR_NOT_INIT (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< MPC not initialized */ +#define ARM_MPC_ERR_NOT_IN_RANGE (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Address does not belong to a range controlled by the MPC */ +#define ARM_MPC_ERR_NOT_ALIGNED (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Address is not aligned on the block size of this MPC */ +#define ARM_MPC_ERR_INVALID_RANGE (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< The given address range to configure is invalid +#define ARM_MPC_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< The given range cannot be accessed with the wanted security attributes */ +#define ARM_MPC_ERR_UNSPECIFIED (ARM_DRIVER_ERROR_SPECIFIC - 5) ///< Unspecified error */ + +/* Security attribute used in various place of the API */ +typedef enum _ARM_MPC_SEC_ATTR { + ARM_MPC_ATTR_SECURE, ///< Secure attribute + ARM_MPC_ATTR_NONSECURE, ///< Non-secure attribute + /* Used when getting the configuration of a memory range and some blocks are + * secure whereas some other are non secure */ + ARM_MPC_ATTR_MIXED, ///< Mixed attribute +} ARM_MPC_SEC_ATTR; + +/* Function documentation */ +/** + \fn ARM_DRIVER_VERSION ARM_MPC_GetVersion (void) + \brief Get driver version. + \return \ref ARM_DRIVER_VERSION + + \fn int32_t ARM_MPC_Initialize (void) + \brief Initialize MPC Interface. + \return Returns error code. + + \fn int32_t ARM_MPC_Uninitialize (void) + \brief De-initialize MPC Interface. The controlled memory region + should not be accessed after a call to this function, as + it is allowed to configure everything to be secure (to + prevent information leak for example). + \return Returns error code. + + \fn int32_t ARM_MPC_GetBlockSize (uint32_t* blk_size) + \brief Get the block size of the MPC. All regions must be aligned + on this block size (base address and limit+1 address). + \param[out] blk_size: The block size in bytes. + \return Returns error code. + + \fn int32_t ARM_MPC_GetCtrlConfig (uint32_t* ctrl_val) + \brief Get some information on how the MPC IP is configured. + \param[out] ctrl_val: MPC control configuration + \return Returns error code. + + \fn int32_t ARM_MPC_SetCtrlConfig (uint32_t ctrl) + \brief Set new control configuration for the MPC IP. + \param[in] ctrl: New control configuration. + \return Returns error code. + + \fn int32_t ARM_MPC_ConfigRegion (uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) + \brief Configure a memory region (base and limit included). + Both base and limit addresses must belong to the same + memory range, and this range must be managed by this MPC. + Also, some ranges are only allowed to be configured as + secure/non-secure, because of hardware requirements + (security aliases), and only a relevant security attribute + is therefore allowed for such ranges. + \param[in] base: Base address of the region to configure. This + bound is included in the configured region. + This must be aligned on the block size of this MPC. + \param[in] limit: Limit address of the region to configure. This + bound is included in the configured region. + Limit+1 must be aligned on the block size of this MPC. + \param[in] attr: Wanted security attribute of the region. + \return Returns error code. + + \fn int32_t ARM_MPC_GetRegionConfig (uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR *attr) + \brief Gets a memory region (base and limit included). + \param[in] base: Base address of the region to poll. This + bound is included. It does not need to be aligned + in any way. + \param[in] limit: Limit address of the region to poll. This + bound is included. (limit+1) does not need to be aligned + in any way. + \param[out] attr: Security attribute of the region. + If the region has mixed secure/non-secure, + a special value is returned (\ref ARM_MPC_SEC_ATTR). + + In case base and limit+1 addresses are not aligned on + the block size, the enclosing region with base and + limit+1 aligned on block size will be queried. + In case of early termination of the function (error), the + security attribute will be set to ARM_MPC_ATTR_MIXED. + \return Returns error code. + + \fn int32_t ARM_MPC_EnableInterrupt (void) + \brief Enable MPC interrupt. + \return Returns error code. + + \fn void ARM_MPC_DisableInterrupt (void) + \brief Disable MPC interrupt. + + \fn void ARM_MPC_ClearInterrupt (void) + \brief Clear MPC interrupt. + + \fn uint32_t ARM_MPC_InterruptState (void) + \brief MPC interrupt state. + \return Returns 1 if the interrupt is active, 0 otherwise. + + \fn int32_t ARM_MPC_LockDown (void) + \brief Lock down the MPC configuration. + \return Returns error code. +*/ + +/** + * \brief Access structure of the MPC Driver. + */ +typedef struct _ARM_DRIVER_MPC { + ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_MPC_GetVersion : Get driver version. + int32_t (*Initialize) (void); ///< Pointer to \ref ARM_MPC_Initialize : Initialize the MPC Interface. + int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_MPC_Uninitialize : De-initialize the MPC Interface. + int32_t (*GetBlockSize) (uint32_t* blk_size); ///< Pointer to \ref ARM_MPC_GetBlockSize : Get MPC block size + int32_t (*GetCtrlConfig) (uint32_t* ctrl_val); ///< Pointer to \ref ARM_MPC_GetCtrlConfig : Get the MPC control configuration flags. + int32_t (*SetCtrlConfig) (uint32_t ctrl); ///< Pointer to \ref ARM_MPC_SetCtrlConfig : Set the MPC control configuration flags. + int32_t (*ConfigRegion) (uintptr_t base, uintptr_t limit, ARM_MPC_SEC_ATTR attr); ///< Pointer to \ref ARM_MPC_ConfigRegion : Configure a region using the driver for the specific MPC. + int32_t (*GetRegionConfig) (uintptr_t base, uintptr_t limit, ARM_MPC_SEC_ATTR *attr); ///< Pointer to \ref ARM_MPC_GetRegionConfig : Get the configuration of a specific region on this MPC. + int32_t (*EnableInterrupt) (void); ///< Pointer to \ref ARM_MPC_EnableInterrupt : Enable MPC interrupt. + void (*DisableInterrupt) (void); ///< Pointer to \ref ARM_MPC_DisableInterrupt : Disable MPC interrupt. + void (*ClearInterrupt) (void); ///< Pointer to \ref ARM_MPC_ClearInterrupt : Clear MPC interrupt. + uint32_t (*InterruptState) (void); ///< Pointer to \ref ARM_MPC_InterruptState : MPC interrupt State. + int32_t (*LockDown) (void); ///< Pointer to \ref ARM_MPC_LockDown : Lock down the MPC configuration. +} const ARM_DRIVER_MPC; + +#endif /* __DRIVER_MPC_H */ + diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_PPC.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_PPC.c new file mode 100644 index 0000000000..0c9f18514c --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_PPC.c @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Driver_PPC.h" + +#include "cmsis.h" +#include "cmsis_driver_config.h" +#include "RTE_Device.h" + +/* Driver version */ +#define ARM_PPC_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0) + +/* Driver Version */ +static const ARM_DRIVER_VERSION DriverVersion = { + ARM_PPC_API_VERSION, + ARM_PPC_DRV_VERSION +}; + +static ARM_DRIVER_VERSION ARM_PPC_GetVersion(void) +{ + return DriverVersion; +} + +#if (RTE_AHB_PPC0) +/* AHB PPC0 Driver wrapper functions */ +static int32_t AHB_PPC0_Initialize(void) +{ + ppc_sse200_init(&AHB_PPC0_DEV, AHB_PPC0); + + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPC0_Uninitialize(void) +{ + /* Nothing to be done*/ + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPC0_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&AHB_PPC0_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t AHB_PPC0_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&AHB_PPC0_DEV, periph); +} + +static uint32_t AHB_PPC0_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&AHB_PPC0_DEV, periph); +} + +static int32_t AHB_PPC0_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&AHB_PPC0_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void AHB_PPC0_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&AHB_PPC0_DEV); +} + +static void AHB_PPC0_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&AHB_PPC0_DEV); +} + +static uint32_t AHB_PPC0_InterruptState(void) +{ + return ppc_sse200_irq_state(&AHB_PPC0_DEV); +} + +/* AHB PPC0 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_AHB_PPC0; +ARM_DRIVER_PPC Driver_AHB_PPC0 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = AHB_PPC0_Initialize, + .Uninitialize = AHB_PPC0_Uninitialize, + .ConfigPeriph = AHB_PPC0_ConfigPeriph, + .IsPeriphSecure = AHB_PPC0_IsPeriphSecure, + .IsPeriphPrivOnly = AHB_PPC0_IsPeriphPrivOnly, + .EnableInterrupt = AHB_PPC0_EnableInterrupt, + .DisableInterrupt = AHB_PPC0_DisableInterrupt, + .ClearInterrupt = AHB_PPC0_ClearInterrupt, + .InterruptState = AHB_PPC0_InterruptState +}; +#endif /* RTE_AHB_PPC0 */ + +#if (RTE_AHB_PPCEXP0) +/* AHB PPCEXP0 Driver wrapper functions */ +static int32_t AHB_PPCEXP0_Initialize(void) +{ + ppc_sse200_init(&AHB_PPCEXP0_DEV, AHB_PPC_EXP0); + + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPCEXP0_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPCEXP0_ConfigPeriph(uint8_t periph, + ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&AHB_PPCEXP0_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t AHB_PPCEXP0_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&AHB_PPCEXP0_DEV, periph); +} + +static uint32_t AHB_PPCEXP0_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP0_DEV, periph); +} + +static int32_t AHB_PPCEXP0_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&AHB_PPCEXP0_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void AHB_PPCEXP0_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&AHB_PPCEXP0_DEV); +} + +static void AHB_PPCEXP0_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&AHB_PPCEXP0_DEV); +} + +static uint32_t AHB_PPCEXP0_InterruptState(void) +{ + return ppc_sse200_irq_state(&AHB_PPCEXP0_DEV); +} + +/* AHB PPCEXP0 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_AHB_PPCEXP0; +ARM_DRIVER_PPC Driver_AHB_PPCEXP0 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = AHB_PPCEXP0_Initialize, + .Uninitialize = AHB_PPCEXP0_Uninitialize, + .ConfigPeriph = AHB_PPCEXP0_ConfigPeriph, + .IsPeriphSecure = AHB_PPCEXP0_IsPeriphSecure, + .IsPeriphPrivOnly = AHB_PPCEXP0_IsPeriphPrivOnly, + .EnableInterrupt = AHB_PPCEXP0_EnableInterrupt, + .DisableInterrupt = AHB_PPCEXP0_DisableInterrupt, + .ClearInterrupt = AHB_PPCEXP0_ClearInterrupt, + .InterruptState = AHB_PPCEXP0_InterruptState +}; +#endif /* RTE_AHB_PPCEXP0 */ + +#if (RTE_AHB_PPCEXP1) +/* AHB PPCEXP1 Driver wrapper functions */ +static int32_t AHB_PPCEXP1_Initialize(void) +{ + ppc_sse200_init(&AHB_PPCEXP1_DEV, AHB_PPC_EXP1); + + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPCEXP1_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPCEXP1_ConfigPeriph(uint8_t periph, + ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&AHB_PPCEXP1_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t AHB_PPCEXP1_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&AHB_PPCEXP1_DEV, periph); +} + +static uint32_t AHB_PPCEXP1_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP1_DEV, periph); +} + +static int32_t AHB_PPCEXP1_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&AHB_PPCEXP1_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void AHB_PPCEXP1_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&AHB_PPCEXP1_DEV); +} + +static void AHB_PPCEXP1_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&AHB_PPCEXP1_DEV); +} + +static uint32_t AHB_PPCEXP1_InterruptState(void) +{ + return ppc_sse200_irq_state(&AHB_PPCEXP1_DEV); +} + +/* AHB PPCEXP1 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_AHB_PPCEXP1; +ARM_DRIVER_PPC Driver_AHB_PPCEXP1 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = AHB_PPCEXP1_Initialize, + .Uninitialize = AHB_PPCEXP1_Uninitialize, + .ConfigPeriph = AHB_PPCEXP1_ConfigPeriph, + .IsPeriphSecure = AHB_PPCEXP1_IsPeriphSecure, + .IsPeriphPrivOnly = AHB_PPCEXP1_IsPeriphPrivOnly, + .EnableInterrupt = AHB_PPCEXP1_EnableInterrupt, + .DisableInterrupt = AHB_PPCEXP1_DisableInterrupt, + .ClearInterrupt = AHB_PPCEXP1_ClearInterrupt, + .InterruptState = AHB_PPCEXP1_InterruptState +}; +#endif /* RTE_AHB_PPCEXP1 */ + +#if (RTE_AHB_PPCEXP2) +/* AHB PPCEXP2 Driver wrapper functions */ +static int32_t AHB_PPCEXP2_Initialize(void) +{ + ppc_sse200_init(&AHB_PPCEXP2_DEV, AHB_PPC_EXP2); + + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPCEXP2_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPCEXP2_ConfigPeriph(uint8_t periph, + ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&AHB_PPCEXP2_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t AHB_PPCEXP2_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&AHB_PPCEXP2_DEV, periph); +} + +static uint32_t AHB_PPCEXP2_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP2_DEV, periph); +} + +static int32_t AHB_PPCEXP2_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&AHB_PPCEXP2_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void AHB_PPCEXP2_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&AHB_PPCEXP2_DEV); +} + +static void AHB_PPCEXP2_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&AHB_PPCEXP2_DEV); +} + +static uint32_t AHB_PPCEXP2_InterruptState(void) +{ + return ppc_sse200_irq_state(&AHB_PPCEXP2_DEV); +} + +/* AHB PPCEXP2 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_AHB_PPCEXP2; +ARM_DRIVER_PPC Driver_AHB_PPCEXP2 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = AHB_PPCEXP2_Initialize, + .Uninitialize = AHB_PPCEXP2_Uninitialize, + .ConfigPeriph = AHB_PPCEXP2_ConfigPeriph, + .IsPeriphSecure = AHB_PPCEXP2_IsPeriphSecure, + .IsPeriphPrivOnly = AHB_PPCEXP2_IsPeriphPrivOnly, + .EnableInterrupt = AHB_PPCEXP2_EnableInterrupt, + .DisableInterrupt = AHB_PPCEXP2_DisableInterrupt, + .ClearInterrupt = AHB_PPCEXP2_ClearInterrupt, + .InterruptState = AHB_PPCEXP2_InterruptState +}; +#endif /* RTE_AHB_PPCEXP2 */ + +#if (RTE_AHB_PPCEXP3) +/* AHB PPCEXP3 Driver wrapper functions */ +static int32_t AHB_PPCEXP3_Initialize(void) +{ + ppc_sse200_init(&AHB_PPCEXP3_DEV, AHB_PPC_EXP3); + + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPCEXP3_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t AHB_PPCEXP3_ConfigPeriph(uint8_t periph, + ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&AHB_PPCEXP3_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t AHB_PPCEXP3_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&AHB_PPCEXP3_DEV, periph); +} + +static uint32_t AHB_PPCEXP3_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP3_DEV, periph); +} + +static int32_t AHB_PPCEXP3_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&AHB_PPCEXP3_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void AHB_PPCEXP3_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&AHB_PPCEXP3_DEV); +} + +static void AHB_PPCEXP3_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&AHB_PPCEXP3_DEV); +} + +static uint32_t AHB_PPCEXP3_InterruptState(void) +{ + return ppc_sse200_irq_state(&AHB_PPCEXP3_DEV); +} + +/* AHB PPCEXP3 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_AHB_PPCEXP3; +ARM_DRIVER_PPC Driver_AHB_PPCEXP3 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = AHB_PPCEXP3_Initialize, + .Uninitialize = AHB_PPCEXP3_Uninitialize, + .ConfigPeriph = AHB_PPCEXP3_ConfigPeriph, + .IsPeriphSecure = AHB_PPCEXP3_IsPeriphSecure, + .IsPeriphPrivOnly = AHB_PPCEXP3_IsPeriphPrivOnly, + .EnableInterrupt = AHB_PPCEXP3_EnableInterrupt, + .DisableInterrupt = AHB_PPCEXP3_DisableInterrupt, + .ClearInterrupt = AHB_PPCEXP3_ClearInterrupt, + .InterruptState = AHB_PPCEXP3_InterruptState +}; +#endif /* RTE_AHB_PPCEXP3 */ + +#if (RTE_APB_PPC0) +/* APB PPC0 Driver wrapper functions */ +static int32_t APB_PPC0_Initialize(void) +{ + ppc_sse200_init(&APB_PPC0_DEV, APB_PPC0); + + return ARM_DRIVER_OK; +} + +static int32_t APB_PPC0_Uninitialize(void) +{ + /* Nothing to be done*/ + return ARM_DRIVER_OK; +} + +static int32_t APB_PPC0_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&APB_PPC0_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t APB_PPC0_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&APB_PPC0_DEV, periph); +} + +static uint32_t APB_PPC0_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&APB_PPC0_DEV, periph); +} + +static int32_t APB_PPC0_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&APB_PPC0_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void APB_PPC0_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&APB_PPC0_DEV); +} + +static void APB_PPC0_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&APB_PPC0_DEV); +} + +static uint32_t APB_PPC0_InterruptState(void) +{ + return ppc_sse200_irq_state(&APB_PPC0_DEV); +} + +/* APB PPC0 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_APB_PPC0; +ARM_DRIVER_PPC Driver_APB_PPC0 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = APB_PPC0_Initialize, + .Uninitialize = APB_PPC0_Uninitialize, + .ConfigPeriph = APB_PPC0_ConfigPeriph, + .IsPeriphSecure = APB_PPC0_IsPeriphSecure, + .IsPeriphPrivOnly = APB_PPC0_IsPeriphPrivOnly, + .EnableInterrupt = APB_PPC0_EnableInterrupt, + .DisableInterrupt = APB_PPC0_DisableInterrupt, + .ClearInterrupt = APB_PPC0_ClearInterrupt, + .InterruptState = APB_PPC0_InterruptState +}; +#endif /* RTE_APB_PPC0 */ + +#if (RTE_APB_PPC1) +/* APB PPC1 Driver wrapper functions */ +static int32_t APB_PPC1_Initialize(void) +{ + ppc_sse200_init(&APB_PPC1_DEV, APB_PPC1); + + return ARM_DRIVER_OK; +} + +static int32_t APB_PPC1_Uninitialize(void) +{ + /* Nothing to be done*/ + return ARM_DRIVER_OK; +} + +static int32_t APB_PPC1_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&APB_PPC1_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t APB_PPC1_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&APB_PPC1_DEV, periph); +} + +static uint32_t APB_PPC1_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&APB_PPC1_DEV, periph); +} +static int32_t APB_PPC1_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&APB_PPC1_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void APB_PPC1_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&APB_PPC1_DEV); +} + +static void APB_PPC1_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&APB_PPC1_DEV); +} + +static uint32_t APB_PPC1_InterruptState(void) +{ + return ppc_sse200_irq_state(&APB_PPC1_DEV); +} + +/* APB PPC1 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_APB_PPC1; +ARM_DRIVER_PPC Driver_APB_PPC1 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = APB_PPC1_Initialize, + .Uninitialize = APB_PPC1_Uninitialize, + .ConfigPeriph = APB_PPC1_ConfigPeriph, + .IsPeriphSecure = APB_PPC1_IsPeriphSecure, + .IsPeriphPrivOnly = APB_PPC1_IsPeriphPrivOnly, + .EnableInterrupt = APB_PPC1_EnableInterrupt, + .DisableInterrupt = APB_PPC1_DisableInterrupt, + .ClearInterrupt = APB_PPC1_ClearInterrupt, + .InterruptState = APB_PPC1_InterruptState +}; +#endif /* RTE_APB_PPC1 */ + +#if (RTE_APB_PPCEXP0) +/* APB PPCEXP0 Driver wrapper functions */ +static int32_t APB_PPCEXP0_Initialize(void) +{ + ppc_sse200_init(&APB_PPCEXP0_DEV, APB_PPC_EXP0); + + return ARM_DRIVER_OK; +} + +static int32_t APB_PPCEXP0_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t APB_PPCEXP0_ConfigPeriph(uint8_t periph, + ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&APB_PPCEXP0_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t APB_PPCEXP0_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&APB_PPCEXP0_DEV, periph); +} + +static uint32_t APB_PPCEXP0_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&APB_PPCEXP0_DEV, periph); +} + +static int32_t APB_PPCEXP0_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&APB_PPCEXP0_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void APB_PPCEXP0_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&APB_PPCEXP0_DEV); +} + +static void APB_PPCEXP0_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&APB_PPCEXP0_DEV); +} + +static uint32_t APB_PPCEXP0_InterruptState(void) +{ + return ppc_sse200_irq_state(&APB_PPCEXP0_DEV); +} + +/* APB PPCEXP0 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_APB_PPCEXP0; +ARM_DRIVER_PPC Driver_APB_PPCEXP0 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = APB_PPCEXP0_Initialize, + .Uninitialize = APB_PPCEXP0_Uninitialize, + .ConfigPeriph = APB_PPCEXP0_ConfigPeriph, + .IsPeriphSecure = APB_PPCEXP0_IsPeriphSecure, + .IsPeriphPrivOnly = APB_PPCEXP0_IsPeriphPrivOnly, + .EnableInterrupt = APB_PPCEXP0_EnableInterrupt, + .DisableInterrupt = APB_PPCEXP0_DisableInterrupt, + .ClearInterrupt = APB_PPCEXP0_ClearInterrupt, + .InterruptState = APB_PPCEXP0_InterruptState +}; +#endif /* RTE_APB_PPCEXP0 */ + +#if (RTE_APB_PPCEXP1) +/* APB PPCEXP1 Driver wrapper functions */ +static int32_t APB_PPCEXP1_Initialize(void) +{ + ppc_sse200_init(&APB_PPCEXP1_DEV, APB_PPC_EXP1); + + return ARM_DRIVER_OK; +} + +static int32_t APB_PPCEXP1_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t APB_PPCEXP1_ConfigPeriph(uint8_t periph, + ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&APB_PPCEXP1_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t APB_PPCEXP1_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&APB_PPCEXP1_DEV, periph); +} + +static uint32_t APB_PPCEXP1_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&APB_PPCEXP1_DEV, periph); +} + +static int32_t APB_PPCEXP1_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&APB_PPCEXP1_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void APB_PPCEXP1_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&APB_PPCEXP1_DEV); +} + +static void APB_PPCEXP1_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&APB_PPCEXP1_DEV); +} + +static uint32_t APB_PPCEXP1_InterruptState(void) +{ + return ppc_sse200_irq_state(&APB_PPCEXP1_DEV); +} + +/* APB PPCEXP1 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_APB_PPCEXP1; +ARM_DRIVER_PPC Driver_APB_PPCEXP1 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = APB_PPCEXP1_Initialize, + .Uninitialize = APB_PPCEXP1_Uninitialize, + .ConfigPeriph = APB_PPCEXP1_ConfigPeriph, + .IsPeriphSecure = APB_PPCEXP1_IsPeriphSecure, + .IsPeriphPrivOnly = APB_PPCEXP1_IsPeriphPrivOnly, + .EnableInterrupt = APB_PPCEXP1_EnableInterrupt, + .DisableInterrupt = APB_PPCEXP1_DisableInterrupt, + .ClearInterrupt = APB_PPCEXP1_ClearInterrupt, + .InterruptState = APB_PPCEXP1_InterruptState +}; +#endif /* RTE_APB_PPCEXP1 */ + +#if (RTE_APB_PPCEXP2) +/* APB PPCEXP2 Driver wrapper functions */ +static int32_t APB_PPCEXP2_Initialize(void) +{ + ppc_sse200_init(&APB_PPCEXP2_DEV, APB_PPC_EXP2); + + return ARM_DRIVER_OK; +} + +static int32_t APB_PPCEXP2_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t APB_PPCEXP2_ConfigPeriph(uint8_t periph, + ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&APB_PPCEXP2_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + + return ARM_DRIVER_OK; +} + +static uint32_t APB_PPCEXP2_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&APB_PPCEXP2_DEV, periph); +} + +static uint32_t APB_PPCEXP2_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&APB_PPCEXP2_DEV, periph); +} + +static int32_t APB_PPCEXP2_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&APB_PPCEXP2_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void APB_PPCEXP2_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&APB_PPCEXP2_DEV); +} + +static void APB_PPCEXP2_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&APB_PPCEXP2_DEV); +} + +static uint32_t APB_PPCEXP2_InterruptState(void) +{ + return ppc_sse200_irq_state(&APB_PPCEXP2_DEV); +} + +/* APB PPCEXP2 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_APB_PPCEXP2; +ARM_DRIVER_PPC Driver_APB_PPCEXP2 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = APB_PPCEXP2_Initialize, + .Uninitialize = APB_PPCEXP2_Uninitialize, + .ConfigPeriph = APB_PPCEXP2_ConfigPeriph, + .IsPeriphSecure = APB_PPCEXP2_IsPeriphSecure, + .IsPeriphPrivOnly = APB_PPCEXP2_IsPeriphPrivOnly, + .EnableInterrupt = APB_PPCEXP2_EnableInterrupt, + .DisableInterrupt = APB_PPCEXP2_DisableInterrupt, + .ClearInterrupt = APB_PPCEXP2_ClearInterrupt, + .InterruptState = APB_PPCEXP2_InterruptState +}; +#endif /* RTE_APB_PPCEXP2 */ + +#if (RTE_APB_PPCEXP3) +/* APB PPCEXP3 Driver wrapper functions */ +static int32_t APB_PPCEXP3_Initialize(void) +{ + ppc_sse200_init(&APB_PPCEXP3_DEV, APB_PPC_EXP3); + + return ARM_DRIVER_OK; +} + +static int32_t APB_PPCEXP3_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t APB_PPCEXP3_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_config_peripheral(&APB_PPCEXP3_DEV, periph, + (enum ppc_sse200_sec_attr_t)sec_attr, + (enum ppc_sse200_priv_attr_t)priv_attr); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static uint32_t APB_PPCEXP3_IsPeriphSecure(uint8_t periph) +{ + return ppc_sse200_is_periph_secure(&APB_PPCEXP3_DEV, periph); +} + +static uint32_t APB_PPCEXP3_IsPeriphPrivOnly(uint8_t periph) +{ + return ppc_sse200_is_periph_priv_only(&APB_PPCEXP3_DEV, periph); +} + +static int32_t APB_PPCEXP3_EnableInterrupt(void) +{ + enum ppc_sse200_error_t ret; + + ret = ppc_sse200_irq_enable(&APB_PPCEXP3_DEV); + + if( ret != PPC_SSE200_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void APB_PPCEXP3_DisableInterrupt(void) +{ + ppc_sse200_irq_disable(&APB_PPCEXP3_DEV); +} + +static void APB_PPCEXP3_ClearInterrupt(void) +{ + ppc_sse200_clear_irq(&APB_PPCEXP3_DEV); +} + +static uint32_t APB_PPCEXP3_InterruptState(void) +{ + return ppc_sse200_irq_state(&APB_PPCEXP3_DEV); +} + +/* APB PPCEXP3 Driver CMSIS access structure */ +extern ARM_DRIVER_PPC Driver_APB_PPCEXP3; +ARM_DRIVER_PPC Driver_APB_PPCEXP3 = { + .GetVersion = ARM_PPC_GetVersion, + .Initialize = APB_PPCEXP3_Initialize, + .Uninitialize = APB_PPCEXP3_Uninitialize, + .ConfigPeriph = APB_PPCEXP3_ConfigPeriph, + .IsPeriphSecure = APB_PPCEXP3_IsPeriphSecure, + .IsPeriphPrivOnly = APB_PPCEXP3_IsPeriphPrivOnly, + .EnableInterrupt = APB_PPCEXP3_EnableInterrupt, + .DisableInterrupt = APB_PPCEXP3_DisableInterrupt, + .ClearInterrupt = APB_PPCEXP3_ClearInterrupt, + .InterruptState = APB_PPCEXP3_InterruptState +}; +#endif /* RTE_APB_PPCEXP3 */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_PPC.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_PPC.h new file mode 100644 index 0000000000..e689b2ebde --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/CMSIS_Driver/Driver_PPC.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_PPC_DRV_H__ +#define __CMSIS_PPC_DRV_H__ + +#include "Driver_Common.h" + +/* API version */ +#define ARM_PPC_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0) + +/* Security attribute used to configure the peripheral */ +typedef enum _ARM_PPC_SecAttr { + ARM_PPC_SECURE_ONLY, ///< Secure access + ARM_PPC_NONSECURE_ONLY, ///< Non-secure access +} ARM_PPC_SecAttr; + +/* Privilege attribute used to configure the peripheral */ +typedef enum _ARM_PPC_PrivAttr { + ARM_PPC_PRIV_AND_NONPRIV, ///< Privilege and non-privilege access + ARM_PPC_PRIV_ONLY, ///< Privilege only access +} ARM_PPC_PrivAttr; + +/* Function documentation */ +/** + \fn ARM_DRIVER_VERSION ARM_PPC_GetVersion (void) + \brief Get driver version. + \return \ref ARM_DRIVER_VERSION + + \fn int32_t ARM_PPC_Initialize (void) + \brief Initialize PPC Interface. + \return Returns ARM error code. + + \fn int32_t ARM_PPC_Uninitialize (void) + \brief De-initialize MPC Interface. + \return Returns ARM error code. + + \fn int32_t ARM_PPC_ConfigPeriph (uint8_t periph, + ARM_PPC_SecAttr sec_attr, + ARM_PPC_PrivAttr priv_attr) + \brief Configures a peripheral controlled by the given PPC. + \param[in] periph: Peripheral position in SPCTRL and NSPCTRL registers. + \param[in] sec_attr: Secure attribute value. + \param[in] priv_attr: Privilege attrivute value. + + Secure Privilege Control Block ( SPCTRL ) + Non-Secure Privilege Control Block ( NSPCTRL ) + + \return Returns ARM error code. + + \fn int32_t ARM_PPC_IsPeriphSecure (uint8_t periph) + \brief Check if the peripheral is configured to be secure. + \param[in] periph: Peripheral position in SPCTRL and NSPCTRL registers. + + Secure Privilege Control Block ( SPCTRL ) + Non-Secure Privilege Control Block ( NSPCTRL ) + + \return Returns 1 if the peripheral is configured as secure, + 0 for non-secure. + + \fn uint32_t ARM_PPC_IsPeriphPrivOnly (uint8_t periph) + \brief Check if the peripheral is configured to be privilege only. + \param[in] periph: Peripheral position in SPCTRL and NSPCTRL registers. + + Secure Privilege Control Block ( SPCTRL ) + Non-Secure Privilege Control Block ( NSPCTRL ) + + \return Returns 1 if the peripheral is configured as privilege access + only, 0 for privilege and unprivilege access mode. + + \fn int32_t ARM_PPC_EnableInterrupt (void) + \brief Enable PPC interrupt. + \return Returns ARM error code. + + \fn void ARM_PPC_DisableInterrupt (void) + \brief Disable PPC interrupt. + + \fn void ARM_PPC_ClearInterrupt (void) + \brief Clear PPC interrupt. + + \fn int32_t ARM_PPC_InterruptState (void) + \brief PPC interrupt state. + \return Returns 1 if the interrupt is active, 0 otherwise. +*/ + +/** + * \brief Access structure of the MPC Driver. + */ +typedef struct _ARM_DRIVER_PPC { + ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_PPC_GetVersion : Get driver version. + int32_t (*Initialize) (void); ///< Pointer to \ref ARM_PPC_Initialize : Initialize the PPC Interface. + int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_PPC_Uninitialize : De-initialize the PPC Interface. + int32_t (*ConfigPeriph) (uint8_t periph, ARM_PPC_SecAttr sec_attr, ARM_PPC_PrivAttr priv_attr); ///< Pointer to \ref ARM_PPC_ConfigPeriph : Configure a peripheral controlled by the PPC. + uint32_t (*IsPeriphSecure) (uint8_t periph); ///< Pointer to \ref IsPeriphSecure : Check if the peripheral is configured to be secure. + uint32_t (*IsPeriphPrivOnly) (uint8_t periph); ///< Pointer to \ref IsPeriphPrivOnly : Check if the peripheral is configured to be privilege only. + int32_t (*EnableInterrupt) (void); ///< Pointer to \ref ARM_PPC_EnableInterrupt : Enable PPC interrupt. + void (*DisableInterrupt) (void); ///< Pointer to \ref ARM_PPC_DisableInterrupt : Disable PPC interrupt. + void (*ClearInterrupt) (void); ///< Pointer to \ref ARM_PPC_ClearInterrupt : Clear PPC interrupt. + uint32_t (*InterruptState) (void); ///< Pointer to \ref ARM_PPC_InterruptState : PPC interrupt State. +} const ARM_DRIVER_PPC; + +#endif /* __CMSIS_PPC_DRV_H__ */ + diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/Libraries/mt25ql_flash_lib.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/Libraries/mt25ql_flash_lib.c new file mode 100644 index 0000000000..ed82c32997 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/Libraries/mt25ql_flash_lib.c @@ -0,0 +1,944 @@ +/* + * Copyright (c) 2018-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +/* Use memcpy function */ +#include + +#include "mt25ql_flash_lib.h" + +/** Setter bit manipulation macro */ +#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX))) +/** Clearing bit manipulation macro */ +#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX))) +/** Getter bit manipulation macro */ +#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX)))) + +#define BITS_PER_WORD 32U +#define BYTES_PER_WORD 4U + +#define ARG_NOT_USED 0 +#define ARG_PTR_NOT_USED NULL + +/** MT25QL used command */ +#define WRITE_ENABLE_CMD 0x06U +#define READ_ENHANCED_VOLATILE_CFG_REG_CMD 0x65U +#define WRITE_ENHANCED_VOLATILE_CFG_REG_CMD 0x61U +#define READ_VOLATILE_CFG_REG_CMD 0x85U +#define WRITE_VOLATILE_CFG_REG_CMD 0x81U +#define READ_FLAG_STATUS_REG_CMD 0x70U +#define SUBSECTOR_ERASE_32KB_CMD 0x52U +#define SUBSECTOR_ERASE_4KB_CMD 0x20U +#define SECTOR_ERASE_CMD 0xD8U +#define BULK_ERASE_CMD 0xC7U +/* + * The baud rate divisor in \ref mt25ql_dev_t needs to be configured adequately + * to handle those commands. + */ +#define QUAD_OUTPUT_FAST_READ_CMD 0x6BU +#define FAST_READ_CMD 0x0BU +#define READ_CMD 0x03U +#define QUAD_INPUT_FAST_PROGRAM_CMD 0x32U +#define PAGE_PROGRAM_CMD 0x02U + +/** MT25QL Enhanced Volatile Configuration Register access */ +#define ENHANCED_VOLATILE_CFG_REG_LEN 1U +#define ENHANCED_VOLATILE_CFG_REG_QSPI_POS 7U +#define ENHANCED_VOLATILE_CFG_REG_DSPI_POS 6U + +/** MT25QL Volatile Configuration Register access */ +#define VOLATILE_CFG_REG_LEN 1U +#define VOLATILE_CFG_REG_DUMMY_CYCLES_POS 4U +#define VOLATILE_CFG_REG_DUMMY_CYCLES_BITS 4U + +/** MT25QL Flag Status Register access */ +#define FLAG_STATUS_REG_LEN 1U +#define FLAG_STATUS_REG_READY_POS 7U + +/* + * 8 is the minimal number of dummy clock cycles needed to reach the maximal + * frequency of the Quad Output Fast Read Command. + */ +#define QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES 8U +#define FAST_READ_DUMMY_CYCLES 8U +#define DEFAULT_READ_DUMMY_CYCLES 0U +#define QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES 0U +#define PAGE_PROGRAM_DUMMY_CYCLES 0U + +/* Only up to 8 bytes can be read or written using the Flash commands. */ +#define CMD_DATA_MAX_SIZE 8U + +/** + * \brief Change specific bits in a 32 bits word. + * + * \param[in,out] word Pointer of the word to change + * \param[in] bits bits_length bits to put at bits_pos in the word + * pointed + * \param[in] bits_length Number of bits to change + * \param[in] bits_pos Position of the bits to change + * + * \note This function will do nothing if the parameters given are incorrect: + * * word is NULL + * * bits_length + bits_pos > 32 + * * bits_length is 0 + */ +static void change_bits_in_word(volatile uint32_t *word, + uint32_t bits, + uint32_t bits_length, + uint32_t bits_pos) +{ + uint32_t mask; + + if ((word == NULL) || + ((bits_length + bits_pos) > BITS_PER_WORD) || + (bits_length == 0U)) { + /* Silently fail */ + return; + } + + /* Change all the bits */ + if (bits_length == BITS_PER_WORD) { + *word = bits; + return; + } + + mask = ((1U << bits_length) - 1); + /* + * We change the bits in three steps: + * - clear bits_length bits with zeroes at bits_pos in the word + * - mask bits in case it contains more than bits_length bits + * - set the new bits in the cleared word + * Because the data pointed by word is only read once, the data will still + * be coherent after an interruption that changes it. + */ + *word = ((*word & ~(mask << bits_pos)) | ((bits & mask) << bits_pos)); +} + +/** + * \brief Send the Write Enable command, needed before any write. + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + */ +static void send_write_enable(struct mt25ql_dev_t* dev) +{ + qspi_ip6514e_send_simple_cmd(dev->controller, WRITE_ENABLE_CMD); +} + +/** + * \brief Set SPI mode on the flash device and on the controller. + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * \param[in] spi_mode SPI mode to be set on flash device and controller + * \ref qspi_ip6514e_spi_mode_t + * + * \return Return error code as specified in \ref mt25ql_error_t + */ +static enum mt25ql_error_t set_spi_mode(struct mt25ql_dev_t* dev, + enum qspi_ip6514e_spi_mode_t spi_mode) +{ + uint8_t enhanced_volatile_cfg_reg = 0; + enum qspi_ip6514e_error_t controller_error; + + /* Read the Enhanced Volatile Configuration Register, modify it according + * to the requested SPI mode then write back the modified value to the + * register. This will activate the SPI mode on the flash side. + */ + controller_error = qspi_ip6514e_send_read_cmd( + dev->controller, + READ_ENHANCED_VOLATILE_CFG_REG_CMD, + &enhanced_volatile_cfg_reg, + ENHANCED_VOLATILE_CFG_REG_LEN, + ARG_NOT_USED, + ARG_NOT_USED, + 0); /* No dummy cycles needed for + this command. */ + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + switch(spi_mode) { + case QSPI_IP6514E_SPI_MODE: + /* Disable the Dual- and Quad-SPI modes. + * Clearing the bit enables the mode, setting it disables it. + */ + SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS); + SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS); + break; + case QSPI_IP6514E_DSPI_MODE: + /* Disable the Quad-SPI mode and activate DSPI mode. + * Clearing the bit enables the mode, setting it disables it. + */ + CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS); + SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS); + break; + case QSPI_IP6514E_QSPI_MODE: + /* Disable the Dual-SPI mode and activate QSPI mode. + * Clearing the bit enables the mode, setting it disables it. + */ + SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS); + CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS); + break; + default: + return MT25QL_ERR_WRONG_ARGUMENT; + } + + send_write_enable(dev); + + controller_error = qspi_ip6514e_send_write_cmd( + dev->controller, + WRITE_ENHANCED_VOLATILE_CFG_REG_CMD, + &enhanced_volatile_cfg_reg, + ENHANCED_VOLATILE_CFG_REG_LEN, + ARG_NOT_USED, + ARG_NOT_USED, + 0); /* No dummy cycles needed for + this command. */ + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + /* Activate the requested SPI mode on the controller side as well. */ + controller_error = qspi_ip6514e_set_spi_mode(dev->controller, + spi_mode, + spi_mode, + spi_mode); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + return MT25QL_ERR_NONE; +} + +/** + * \brief Change the number of dummy clock cycles subsequent to all FAST READ + * commands. + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * \param[in] dummy_cycles Dummy clock cycles to set + * + * \return Return error code as specified in \ref mt25ql_error_t + */ +static enum mt25ql_error_t change_dummy_cycles(struct mt25ql_dev_t* dev, + uint32_t dummy_cycles) +{ + uint32_t volatile_cfg_reg = 0; + enum qspi_ip6514e_error_t controller_error; + + /* + * Changes the number of dummy cycles in the Volatile Configuration + * Register. + */ + controller_error = qspi_ip6514e_send_read_cmd(dev->controller, + READ_VOLATILE_CFG_REG_CMD, + &volatile_cfg_reg, + VOLATILE_CFG_REG_LEN, + ARG_NOT_USED, + ARG_NOT_USED, + 0); /* No dummy cycles needed + for this command. */ + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + change_bits_in_word(&volatile_cfg_reg, + dummy_cycles, + VOLATILE_CFG_REG_DUMMY_CYCLES_BITS, + VOLATILE_CFG_REG_DUMMY_CYCLES_POS); + + send_write_enable(dev); + + controller_error = qspi_ip6514e_send_write_cmd(dev->controller, + WRITE_VOLATILE_CFG_REG_CMD, + &volatile_cfg_reg, + VOLATILE_CFG_REG_LEN, + ARG_NOT_USED, + ARG_NOT_USED, + 0); /* No dummy cycles needed + for this command. */ + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + return MT25QL_ERR_NONE; +} + +/** + * \brief Wait until the current program/erase is finished. + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * + * \return Return error code as specified in \ref mt25ql_error_t + */ +static enum mt25ql_error_t wait_program_or_erase_complete( + struct mt25ql_dev_t* dev) +{ + enum qspi_ip6514e_error_t controller_error; + uint8_t flag_status_reg = 0; + + /* Wait until the ready bit of the Flag Status Register is set */ + while (!GET_BIT(flag_status_reg, FLAG_STATUS_REG_READY_POS)) { + controller_error = qspi_ip6514e_send_read_cmd(dev->controller, + READ_FLAG_STATUS_REG_CMD, + &flag_status_reg, + FLAG_STATUS_REG_LEN, + ARG_NOT_USED, + ARG_NOT_USED, + 0); /* No dummy cycles + needed for this + command. */ + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + } + + return MT25QL_ERR_NONE; +} + +/** + * \brief Execute a program command that crosses the page size boundary. + * + * \param[in] dev Pointer to MT25QL device structure + * \ref mt25ql_dev_t + * \param[in] opcode Opcode for the command. + * \param[in] write_data Pointer to a memory zone where the write_len + * number of bytes are located to write for this + * command. + * \param[in] write_len Number of bytes to write for the command. + * Between 1 and 8 bytes (both included) can be + * written. + * \param[in] addr Address used for the command + * \param[in] addr_bytes_number Number of address bytes for this command. + * If an address is not needed for the command, + * use 0 for argument, otherwise between 1 and + * 4 bytes (both included) can be used. + * \param[in] dummy_cycles Number of dummy cycles required for the + * command, between 0 and 31 (both included). + * + * \return Return error code as specified in \ref mt25ql_error_t + * + * \note This function will execute two commands: one to program the bytes up to + * the page boundary and another one to program the rest. It will wait + * that bytes are programmed from first command before triggering the + * second one. + * \note This function does not send a write enable command before the first + * command and does not check that bytes were programmed after the second + * command. + */ +static enum mt25ql_error_t send_boundary_cross_write_cmd( + struct mt25ql_dev_t* dev, + uint8_t opcode, + const void *write_data, + uint32_t write_len, + uint32_t addr, + uint32_t addr_bytes_number, + uint32_t dummy_cycles) +{ + enum qspi_ip6514e_error_t controller_error; + enum mt25ql_error_t library_error; + /* + * Remaining bytes between the current address and the end of the current + * page. + */ + uint32_t page_remainder = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE); + + /* First write up to the end of the current page. */ + controller_error = qspi_ip6514e_send_write_cmd(dev->controller, + opcode, + write_data, + page_remainder, + addr, + addr_bytes_number, + dummy_cycles); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + write_data = (void *)((uint32_t)write_data + page_remainder); + addr += page_remainder; + + /* Wait for the page to be written before sending new commands. */ + library_error = wait_program_or_erase_complete(dev); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + + /* Then write the remaining data of the write_len bytes. */ + send_write_enable(dev); + controller_error = qspi_ip6514e_send_write_cmd(dev->controller, + opcode, + write_data, + write_len - page_remainder, + addr, + addr_bytes_number, + dummy_cycles); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + return MT25QL_ERR_NONE; +} + +enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev, + enum mt25ql_functional_state_t config) +{ + enum qspi_ip6514e_spi_mode_t spi_mode; + enum qspi_ip6514e_error_t controller_error; + enum mt25ql_error_t library_error; + uint8_t opcode_read; + uint8_t opcode_write; + uint32_t dummy_cycles_read; + uint32_t dummy_cycles_write; + + switch(config) { + case MT25QL_FUNC_STATE_DEFAULT: + spi_mode = QSPI_IP6514E_SPI_MODE; + opcode_read = READ_CMD; + dummy_cycles_read = DEFAULT_READ_DUMMY_CYCLES; + opcode_write = PAGE_PROGRAM_CMD; + dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES; + break; + case MT25QL_FUNC_STATE_FAST: + spi_mode = QSPI_IP6514E_SPI_MODE; + opcode_read = FAST_READ_CMD; + dummy_cycles_read = FAST_READ_DUMMY_CYCLES; + opcode_write = PAGE_PROGRAM_CMD; + dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES; + break; + case MT25QL_FUNC_STATE_QUAD_FAST: + spi_mode = QSPI_IP6514E_QSPI_MODE; + opcode_read = QUAD_OUTPUT_FAST_READ_CMD; + dummy_cycles_read = QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES; + opcode_write = QUAD_INPUT_FAST_PROGRAM_CMD; + dummy_cycles_write = QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES; + break; + default: + return MT25QL_ERR_WRONG_ARGUMENT; + } + + /* This function will first set the Flash memory SPI mode and then set + * the controller's SPI mode. It will fail if the two sides do not have + * the same mode when this function is called. + */ + library_error = set_spi_mode(dev, spi_mode); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + + /* Set the number of dummy cycles for read commands. */ + library_error = change_dummy_cycles(dev, dummy_cycles_read); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + + /* The rest of the configuration needs the controller to be disabled */ + while(!qspi_ip6514e_is_idle(dev->controller)); + qspi_ip6514e_disable(dev->controller); + + /* Set the baud rate divisor as configured in the device structure. */ + controller_error = qspi_ip6514e_set_baud_rate_div(dev->controller, + dev->baud_rate_div); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + /* Set opcode and dummy cycles needed for read commands. */ + controller_error = qspi_ip6514e_cfg_reads(dev->controller, + opcode_read, + dummy_cycles_read); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + /* Set opcode and dummy cycles needed for write commands. */ + controller_error = qspi_ip6514e_cfg_writes(dev->controller, + opcode_write, + dummy_cycles_write); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + /* Set Flash memory constants: bytes per page and address bytes. */ + controller_error = qspi_ip6514e_cfg_page_size(dev->controller, + FLASH_PAGE_SIZE); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + controller_error = qspi_ip6514e_cfg_addr_bytes(dev->controller, + ADDR_BYTES); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + qspi_ip6514e_enable(dev->controller); + + dev->func_state = config; + + return MT25QL_ERR_NONE; +} + +enum mt25ql_error_t mt25ql_restore_default_state(struct mt25ql_dev_t* dev) +{ + enum mt25ql_error_t library_error; + + /* + * This function will first change the Flash memory mode to single SPI and + * then change the controller to single SPI. It will fail if the two sides + * do not have the same mode when this function is called. + */ + library_error = set_spi_mode(dev, QSPI_IP6514E_SPI_MODE); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + + /* Set the default number of dummy cycles for read commands. */ + library_error = change_dummy_cycles(dev, DEFAULT_READ_DUMMY_CYCLES); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + + /* The rest of the configuration needs the controller to be disabled */ + while(!qspi_ip6514e_is_idle(dev->controller)); + qspi_ip6514e_disable(dev->controller); + + /* Restore the default value of the QSPI controller registers. */ + qspi_ip6514e_reset_regs(dev->controller); + + qspi_ip6514e_enable(dev->controller); + + dev->func_state = MT25QL_FUNC_STATE_DEFAULT; + + return MT25QL_ERR_NONE; +} + +enum mt25ql_error_t mt25ql_direct_read(struct mt25ql_dev_t* dev, + uint32_t addr, + void *data, + uint32_t len) +{ + /* + * The direct access window size is the size of the memory that can be + * accessed with a direct access. + */ + uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1; + /* + * The window number is the number of times it will be needed to remap the + * address with the remap register. We move this Direct Access window first + * window_number times starting at the beginning address to read full + * windows of direct_access_window_size bytes. Then we read the remainder + * bytes. + */ + uint32_t window_number = len / direct_access_window_size; + + if (data == NULL || len == 0) { + return MT25QL_ERR_WRONG_ARGUMENT; + } + + if ((addr + len) >= dev->size) { + return MT25QL_ERR_ADDR_TOO_BIG; + } + + /* + * There is no limitation reading through a Flash page boundary hence we + * do not add the same logic here than in the write function. + */ + + /* Transfer the bytes for the window_number windows first. */ + for (uint32_t window = 0; window < window_number; window++) { + qspi_ip6514e_remap_addr(dev->controller, addr); + + /* + * The AHB address to access the Flash memory does not change but it + * will be translated differently thanks to the remap function. + */ + memcpy(data, + (void *)dev->direct_access_start_addr, + direct_access_window_size); + + len -= direct_access_window_size; + data = (void *)((uint32_t)data + direct_access_window_size); + addr += direct_access_window_size; + } + + if (len) { + /* Transfer the reminder bytes */ + qspi_ip6514e_remap_addr(dev->controller, addr); + + memcpy(data, (void *)dev->direct_access_start_addr, len); + } + + /* Disable remapping for direct accesses outside of this function. */ + qspi_ip6514e_disable_remap(dev->controller); + + return MT25QL_ERR_NONE; +} + +enum mt25ql_error_t mt25ql_direct_write(struct mt25ql_dev_t* dev, + uint32_t addr, + const void *data, + uint32_t len) +{ + enum mt25ql_error_t library_error; + /* + * The direct access window size is the size of the memory that can be + * accessed with a direct access. + */ + uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1; + uint32_t window_number; + /* Offset between address and the previous 32 bits aligned word */ + uint32_t word_offset; + + if (data == NULL || len == 0) { + return MT25QL_ERR_WRONG_ARGUMENT; + } + + if ((addr + len) >= dev->size) { + return MT25QL_ERR_ADDR_TOO_BIG; + } + + /* + * If the remapping address is not aligned on a 32 bits boundary, a direct + * access of one word could cross a Flash page boundary. If that happens, + * the bytes of that word that are over the page boundary will instead be + * written at the beginning of the same page. + * To counter this problem, we align the remapping address and add the word + * offset to the address of the direct access for the first window only. + */ + word_offset = addr % BYTES_PER_WORD; + /* Make address aligned on a 32 bits alignment. */ + addr -= word_offset; + /* + * Only direct_access_window_size address locations are available by direct + * access. We calculate the number of windows that we will need to transfer + * len bytes. We have to add in the window the offset that we add in the + * beginning. + */ + window_number = (len + word_offset) / direct_access_window_size; + + /* + * This function assumes that the flash has already been erased. + * Transfer the bytes for the window_number windows first. + */ + for (uint32_t window = 0; window < window_number; window++) { + /* The controller needs to be disabled while remapping is done. */ + qspi_ip6514e_remap_addr(dev->controller, addr); + + /* + * The AHB address to access the Flash memory does not change but it + * will be translated differently thanks to the remap function. + */ + memcpy((void *)(dev->direct_access_start_addr + word_offset), + data, + direct_access_window_size - word_offset); + + len -= (direct_access_window_size - word_offset); + data = (void *)((uint32_t)data + + (direct_access_window_size - word_offset)); + addr += direct_access_window_size; + + /* + * The address is now aligned, there is no need to add an offset for the + * remaining windows. + */ + word_offset = 0; + + /* + * Wait until the last program operation is complete before changing + * the remap address. + */ + library_error = wait_program_or_erase_complete(dev); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + } + + if (len) { + /* Transfer the reminder bytes */ + qspi_ip6514e_remap_addr(dev->controller, addr); + + memcpy((void *)(dev->direct_access_start_addr + word_offset), + data, + len); + + /* Wait until the last program operation is complete */ + library_error = wait_program_or_erase_complete(dev); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + } + + /* + * Disable the default remap address for direct accesses outside of this + * function. + */ + qspi_ip6514e_disable_remap(dev->controller); + + return MT25QL_ERR_NONE; +} + +enum mt25ql_error_t mt25ql_command_read(struct mt25ql_dev_t* dev, + uint32_t addr, + void *data, + uint32_t len) +{ + /* With one single command only 8 bytes can be read. */ + uint32_t cmd_number = len / CMD_DATA_MAX_SIZE; + enum qspi_ip6514e_error_t controller_error; + uint8_t opcode; + uint32_t dummy_cycles; + + switch (dev->func_state) { + case MT25QL_FUNC_STATE_QUAD_FAST: + opcode = QUAD_OUTPUT_FAST_READ_CMD; + dummy_cycles = QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES; + break; + case MT25QL_FUNC_STATE_FAST: + opcode = FAST_READ_CMD; + dummy_cycles = FAST_READ_DUMMY_CYCLES; + break; + case MT25QL_FUNC_STATE_DEFAULT: + default: + opcode = READ_CMD; + dummy_cycles = DEFAULT_READ_DUMMY_CYCLES; + break; + } + + for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) { + controller_error = qspi_ip6514e_send_read_cmd( + dev->controller, + opcode, + data, + CMD_DATA_MAX_SIZE, + addr, + ADDR_BYTES, + dummy_cycles); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE); + addr += CMD_DATA_MAX_SIZE; + len -= CMD_DATA_MAX_SIZE; + } + + if (len) { + /* Read the remainder. */ + controller_error = qspi_ip6514e_send_read_cmd( + dev->controller, + opcode, + data, + len, + addr, + ADDR_BYTES, + dummy_cycles); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + } + + return MT25QL_ERR_NONE; +} + +enum mt25ql_error_t mt25ql_command_write(struct mt25ql_dev_t* dev, + uint32_t addr, + const void *data, + uint32_t len) +{ + /* With one single command only 8 bytes can be written. */ + uint32_t cmd_number = len / CMD_DATA_MAX_SIZE; + enum qspi_ip6514e_error_t controller_error; + enum mt25ql_error_t library_error; + uint8_t opcode; + uint32_t dummy_cycles; + + switch (dev->func_state) { + case MT25QL_FUNC_STATE_QUAD_FAST: + opcode = QUAD_INPUT_FAST_PROGRAM_CMD; + dummy_cycles = QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES; + break; + case MT25QL_FUNC_STATE_FAST: + case MT25QL_FUNC_STATE_DEFAULT: + default: + opcode = PAGE_PROGRAM_CMD; + dummy_cycles = PAGE_PROGRAM_DUMMY_CYCLES; + break; + } + + for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) { + send_write_enable(dev); + + /* + * Check if this command is not writing over a page boundary: first and + * last bytes are in the same page. + */ + if ((addr / FLASH_PAGE_SIZE) != + ((addr + CMD_DATA_MAX_SIZE - 1) / FLASH_PAGE_SIZE)) { + /* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */ + library_error = send_boundary_cross_write_cmd( + dev, + opcode, + data, + CMD_DATA_MAX_SIZE, + addr, + ADDR_BYTES, + dummy_cycles); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + } else { + /* Normal case: not crossing the boundary. */ + controller_error = qspi_ip6514e_send_write_cmd( + dev->controller, + opcode, + data, + CMD_DATA_MAX_SIZE, + addr, + ADDR_BYTES, + dummy_cycles); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + } + + /* Wait until the write operation is complete. */ + library_error = wait_program_or_erase_complete(dev); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + + data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE); + addr += CMD_DATA_MAX_SIZE; + len -= CMD_DATA_MAX_SIZE; + } + + if (len) { + /* Write the remainder. */ + send_write_enable(dev); + /* + * Check if this command is not writing over a page boundary: first and + * last bytes are in the same page. + */ + if ((addr / FLASH_PAGE_SIZE) != ((addr + len - 1) / FLASH_PAGE_SIZE)) { + /* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */ + library_error = send_boundary_cross_write_cmd( + dev, + opcode, + data, + len, + addr, + ADDR_BYTES, + dummy_cycles); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + } else { + /* Normal case: not crossing the boundary. */ + controller_error = qspi_ip6514e_send_write_cmd( + dev->controller, + opcode, + data, + len, + addr, + ADDR_BYTES, + dummy_cycles); + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + } + + /* Wait until the write operation is complete. */ + library_error = wait_program_or_erase_complete(dev); + if (library_error != MT25QL_ERR_NONE) { + return library_error; + } + } + + + return MT25QL_ERR_NONE; +} + +enum mt25ql_error_t mt25ql_erase(struct mt25ql_dev_t* dev, + uint32_t addr, + enum mt25ql_erase_t erase_type) +{ + enum qspi_ip6514e_error_t controller_error; + enum mt25ql_error_t library_error; + uint8_t erase_cmd; + uint32_t addr_bytes; + + send_write_enable(dev); + + switch (erase_type) { + case MT25QL_ERASE_ALL_FLASH: + if (addr != 0) { + return MT25QL_ERR_ADDR_NOT_ALIGNED; + } + erase_cmd = BULK_ERASE_CMD; + addr_bytes = ARG_NOT_USED; + break; + case MT25QL_ERASE_SECTOR_64K: + erase_cmd = SECTOR_ERASE_CMD; + addr_bytes = ADDR_BYTES; + if ((addr % SECTOR_64KB) != 0) { + return MT25QL_ERR_ADDR_NOT_ALIGNED; + } + break; + case MT25QL_ERASE_SUBSECTOR_32K: + erase_cmd = SUBSECTOR_ERASE_32KB_CMD; + addr_bytes = ADDR_BYTES; + if ((addr % SUBSECTOR_32KB) != 0) { + return MT25QL_ERR_ADDR_NOT_ALIGNED; + } + break; + case MT25QL_ERASE_SUBSECTOR_4K: + erase_cmd = SUBSECTOR_ERASE_4KB_CMD; + addr_bytes = ADDR_BYTES; + if ((addr % SUBSECTOR_4KB) != 0) { + return MT25QL_ERR_ADDR_NOT_ALIGNED; + } + break; + default: + return MT25QL_ERR_WRONG_ARGUMENT; + } + + if (addr >= dev->size) { + return MT25QL_ERR_ADDR_TOO_BIG; + } + + controller_error = qspi_ip6514e_send_cmd(dev->controller, + erase_cmd, + ARG_PTR_NOT_USED, + ARG_NOT_USED, + ARG_PTR_NOT_USED, + ARG_NOT_USED, + addr, + addr_bytes, + 0); /* No dummy cycles needed for + any erase command. */ + if (controller_error != QSPI_IP6514E_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + /* Wait until the erase operation is complete */ + library_error = wait_program_or_erase_complete(dev); + if (library_error != MT25QL_ERR_NONE) { + return (enum mt25ql_error_t)controller_error; + } + + return MT25QL_ERR_NONE; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/Libraries/mt25ql_flash_lib.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/Libraries/mt25ql_flash_lib.h new file mode 100644 index 0000000000..f62424ccfe --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/Libraries/mt25ql_flash_lib.h @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2018-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This library provides functions to control the MT25QL256ABA-1EW7-OSIT flash + * memory from Micron and should work for similar devices from the same vendor. + */ + +#ifndef __MT25QL_H__ +#define __MT25QL_H__ + +#include "qspi_ip6514e_drv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MT25QL Flash Memory documentation defined values. + */ +#define FLASH_PAGE_SIZE (256U) /* 256B */ +#define SUBSECTOR_4KB (0x00001000U) /* 4KB */ +#define SUBSECTOR_32KB (0x00008000U) /* 32KB */ +#define SECTOR_64KB (0x00010000U) /* 64KB */ +#define ADDR_BYTES (3U) + +enum mt25ql_error_t { + MT25QL_ERR_NONE = QSPI_IP6514E_ERR_NONE, + MT25QL_ERR_WRONG_ARGUMENT = QSPI_IP6514E_ERR_WRONG_ARGUMENT, + MT25QL_ERR_CTRL_NOT_DISABLED = QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED, + MT25QL_ERR_READ_IN_PROGRESS = QSPI_IP6514E_ERR_READ_IN_PROGRESS, + MT25QL_ERR_WRITE_IN_PROGRESS = QSPI_IP6514E_ERR_WRITE_IN_PROGRESS, + MT25QL_ERR_ADDR_NOT_ALIGNED, + MT25QL_ERR_ADDR_TOO_BIG, +}; + +enum mt25ql_erase_t { + MT25QL_ERASE_ALL_FLASH = 0U, /*!< Erase all flash */ + MT25QL_ERASE_SUBSECTOR_4K = SUBSECTOR_4KB, /*!< Erase a 4 KB subsector */ + MT25QL_ERASE_SUBSECTOR_32K = SUBSECTOR_32KB, /*!< Erase a 32 KB subsector */ + MT25QL_ERASE_SECTOR_64K = SECTOR_64KB, /*!< Erase a sector (64 KB) */ +}; + +enum mt25ql_functional_state_t { + MT25QL_FUNC_STATE_DEFAULT = 0U, + /*!< The QSPI Flash controller and memory is in default state, + * in the same state as after reset. + */ + MT25QL_FUNC_STATE_FAST = 1U, + /*!< The QSPI Flash controller and memory is configured to operate in + * single SPI mode and fast Flash commands could be used for read and + * program operations. + */ + MT25QL_FUNC_STATE_QUAD_FAST = 2U, + /*!< The QSPI Flash controller and memory is configured to operate in + * Quad SPI mode and fast Flash commands could be used for read and + * program operations. + */ +}; + +struct mt25ql_dev_t { + struct qspi_ip6514e_dev_t *controller; + /*!< QSPI Flash controller. */ + uint32_t direct_access_start_addr; + /*!< AHB address to directly access the contents of the Flash memory + * through the QSPI Controller. + */ + uint32_t baud_rate_div; + /*!< Clock divisor that will be used to configure the QSPI Flash + * Controller to access the Flash memory. The clock which frequency is + * divived is the one linked to the QSPI Flash controller. It can only + * be an even number between 2 and 32 (both included). It needs to be + * high enough to support the Quad Output Fast Read command with 8 + * dummy cycles and the Quad Input Fast Program with 0 dummy cycles. + */ + uint32_t size; /*!< Total size of the MT25QL Flash memory */ + enum mt25ql_functional_state_t func_state; + /*!< Functional state (operational parameter settings) of the + * QSPI Flash controller and memory. + */ +}; + +/** + * \brief Change configuration of the QSPI Flash controller and MT25QL memory + * + * Changes the configuration of the QSPI Flash controller and MT25QL + * Flash memory to operate in the specified SPI mode and to use the + * appropriate Flash commands for read and program operations. + * It also sets: + * + The number of dummy cycles for each operation + * + The bytes per page constant to 256 (MT25QL Flash specific) + * + The number of address bytes to 3 + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * \param[in] config Operational configuration to be set on flash controller + * and device \ref mt25ql_functional_state_t + * + * \return Return error code as specified in \ref mt25ql_error_t + * + * \note This function assumes that the Flash memory device and the QSPI Flash + * controller operates with the same SPI protocol. This function will fail + * if the Flash device is in a different configuration. + */ +enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev, + enum mt25ql_functional_state_t config); + +/** + * \brief Restore the QSPI Flash controller and MT25QL to default state. + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * + * \return Return error code as specified in \ref mt25ql_error_t + * + * \note This function assumes that the Flash memory device and the QSPI Flash + * controller operates with the same SPI protocol. This function will fail + * if the Flash device is in a different configuration. + */ +enum mt25ql_error_t mt25ql_restore_default_state(struct mt25ql_dev_t* dev); + +/** + * \brief Read bytes from the flash memory (direct access) + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * \param[in] addr Flash memory address for the read operation + * \param[out] data Pointer where len bytes read from the flash memory will be + * written to + * \param[in] len Number of bytes to read + * + * \return Return error code as specified in \ref mt25ql_error_t + * + * \note This function will use direct access to read from the Flash memory. It + * can be used to access above the direct accessible memory zone if + * not all the AHB address wires are connected. + * \note The address given should be the address of the data inside the flash + * memory. To read the first byte inside the memory, use 0x00000000. + */ +enum mt25ql_error_t mt25ql_direct_read(struct mt25ql_dev_t* dev, + uint32_t addr, + void *data, + uint32_t len); + +/** + * \brief Write bytes in the flash memory, at a location where data has already + * been erased (direct access) + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * \param[in] addr Flash memory address for the write operation + * \param[in] data Pointer to the len bytes that will be written to the flash + * memory + * \param[in] len Number of bytes to write + * + * \return Return error code as specified in \ref mt25ql_error_t + * + * \note This function will use direct access to write to the Flash memory. It + * can be used to access outside of the direct accessible memory zone if + * not all the AHB address wires are connected. + * \note The address given should be the address of the data inside the flash + * memory. To write the first byte inside the memory, use 0x00000000. + * \note Writing bytes in the flash memory clear them from 1 to 0, for that + * matter the location where data is written needs to be erased + * beforehand. + */ +enum mt25ql_error_t mt25ql_direct_write(struct mt25ql_dev_t* dev, + uint32_t addr, + const void *data, + uint32_t len); + +/** + * \brief Read bytes from the flash memory (using Flash commands) + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * \param[in] addr Flash memory address for the read operation + * \param[out] data Pointer where len bytes read from the flash memory will be + * written to + * \param[in] len Number of bytes to read + * + * \return Return error code as specified in \ref mt25ql_error_t + * + * \note This function will use the Software Triggered Instruction Generator to + * read from the Flash memory using Flash commands. + * \note The address given should be the address of the data inside the flash + * memory. To read the first byte inside the memory, use 0x00000000. + */ +enum mt25ql_error_t mt25ql_command_read(struct mt25ql_dev_t* dev, + uint32_t addr, + void *data, + uint32_t len); + +/** + * \brief Write bytes in the flash memory, at a location where data has already + * been erased (using Flash commands) + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * \param[in] addr Flash memory address for the write operation + * \param[in] data Pointer to the len bytes that will be written to the flash + * memory + * \param[in] len Number of bytes to write + * + * \return Return error code as specified in \ref mt25ql_error_t + * + * \note This function will use the Software Triggered Instruction Generator to + * write to the Flash memory using Flash commands. + * \note The address given should be the address of the data inside the flash + * memory. To write the first byte inside the memory, use 0x00000000. + * \note Writing bytes in the flash memory clear them from 1 to 0, for that + * matter the location where data is written needs to be erased + * beforehand. + */ +enum mt25ql_error_t mt25ql_command_write(struct mt25ql_dev_t* dev, + uint32_t addr, + const void *data, + uint32_t len); + +/** + * \brief Erase all flash memory, a sector (64 KiB) or a subsector + * (32 KiB or 4 KiB) + * + * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t + * \param[in] addr Address where to erase in the flash memory + * \param[in] erase_type Type of what to erase at the specified address: + * * whole flash memory + * * a subsector (4 KiB or 32 KiB) + * * a sector (64 KiB) + * \return Return error code as specified in \ref mt25ql_error_t + * + * \note The address need to be aligned with the size of what is erased or 0 if + * all flash memory is to be erased. + */ +enum mt25ql_error_t mt25ql_erase(struct mt25ql_dev_t* dev, + uint32_t addr, + enum mt25ql_erase_t erase_type); + +#ifdef __cplusplus +} +#endif + +#endif /* __MT25QL_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_ARMC6/musca_s.sct b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_ARMC6/musca_s.sct new file mode 100644 index 0000000000..245773f38f --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_ARMC6/musca_s.sct @@ -0,0 +1,153 @@ +#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc + +/* + * Copyright (c) 2018-2019 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../../../partition/region_defs.h" + +#if !defined(TFM_LVL) + #define TFM_LVL 1 +#endif + +#if !defined(MBED_ROM_START) + #define MBED_ROM_START S_CODE_START // 0x10020400 +#endif + +#if !defined(MBED_ROM_SIZE) + #define MBED_ROM_SIZE IMAGE_CODE_SIZE // 0x7f800 +#endif + +#if !defined(MBED_RAM_START) + #define MBED_RAM_START S_DATA_START // 0x30000000 +#endif + +#if !defined(MBED_RAM_SIZE) + #define MBED_RAM_SIZE S_DATA_SIZE // 0x11000 +#endif + +LR_CODE MBED_ROM_START MBED_ROM_SIZE { + + /**** This initial section contains common code for TEE */ + ER_TFM_CODE MBED_ROM_START S_CODE_SIZE { + *.o (RESET +First) + .ANY (+RO) + } + +#if TFM_LVL == 1 + + /* Shared area between BL2 and runtime to exchange data */ + TFM_SHARED_DATA MBED_RAM_START ALIGN 32 OVERLAY EMPTY BOOT_TFM_SHARED_DATA_SIZE { + } + + /* MSP */ + ARM_LIB_STACK_MSP MBED_RAM_START ALIGN 32 OVERLAY EMPTY S_MSP_STACK_SIZE { + } + + /* PSP */ + ARM_LIB_STACK +0 ALIGN 32 EMPTY S_PSP_STACK_SIZE { + } + + ARM_LIB_HEAP +0 ALIGN 8 EMPTY S_HEAP_SIZE { + } + + ER_TFM_DATA +0 { + .ANY (+RW +ZI) + } + + TFM_SECURE_STACK +0 ALIGN 128 EMPTY 0x1000 { + } + + TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x400 { + } + +#else /* TFM_LVL == 1 */ + + /**** Unprivileged Secure code start here */ + TFM_UNPRIV_CODE +0 ALIGN 32 { + tfm_spm_services.o (+RO) + platform_retarget_dev.o (+RO) + *(SFN) + *armlib* + } + + TFM_SP_PLATFORM +0 ALIGN 32 { + *tfm_platform* (+RO) + *(TFM_SP_PLATFORM_ATTR_FN) + } + + /* Shared area between BL2 and runtime to exchange data */ + TFM_SHARED_DATA MBED_RAM_START ALIGN 32 OVERLAY EMPTY BOOT_TFM_SHARED_DATA_SIZE { + } + + /* MSP */ + ARM_LIB_STACK_MSP MBED_RAM_START ALIGN 32 OVERLAY EMPTY S_MSP_STACK_SIZE { + } + + /* PSP */ + ARM_LIB_STACK +0 ALIGN 32 EMPTY S_PSP_STACK_SIZE { + } + + ARM_LIB_HEAP +0 ALIGN 8 EMPTY S_HEAP_SIZE { + } + + ER_TFM_DATA +0 { + .ANY (+RW +ZI) + } + + TFM_UNPRIV_RO_DATA +0 ALIGN 32 { + tfm_spm_services.o (+RW +ZI) + platform_retarget_dev.o (+RW +ZI) + } + + TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x400 { + } + + TFM_SP_PLATFORM_DATA +0 ALIGN 32 { + *tfm_platform* (+RW +ZI) + } + + TFM_SP_PLATFORM_STACK +0 ALIGN 128 EMPTY 0x0400 { + } + +#endif /* TFM_LVL == 1 */ + + /* This empty, zero long execution region is here to mark the limit address + * of the last execution region that is allocated in SRAM. + */ + SRAM_WATERMARK +0 EMPTY 0x0 { + } + + ER_CODE_CMSE_VENEER CMSE_VENEER_REGION_START FIXED PADVALUE 0xFFFFFFFF CMSE_VENEER_REGION_SIZE { + *(Veneer$$CMSE) + } + + /* Make sure that the sections allocated in the SRAM does not exceed the + * size of the SRAM available. + */ + ScatterAssert(ImageLimit(SRAM_WATERMARK) <= MBED_RAM_START + MBED_RAM_SIZE) +} + + +LR_NS_PARTITION NS_PARTITION_START { + /* Reserved place for NS application. + * No code will be placed here, just address of this region is used in the + * secure code to configure certain HW components. + */ + ER_NS_PARTITION NS_PARTITION_START EMPTY NS_PARTITION_SIZE { + } +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_ARMC6/startup_cmsdk_musca_s.S b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_ARMC6/startup_cmsdk_musca_s.S new file mode 100644 index 0000000000..4cce3b059d --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_ARMC6/startup_cmsdk_musca_s.S @@ -0,0 +1,254 @@ +;/* +; * Copyright (c) 2017-2019 ARM Limited +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; */ +; +; This file is derivative of CMSIS V5.01 startup_ARMv8MML.s +; Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75 + +;/* +;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ +;*/ + + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + + IMPORT |Image$$ARM_LIB_STACK_MSP$$ZI$$Limit| + +; Vector Table Mapped to Address 0 at Reset + + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors ;Core Interrupts + DCD |Image$$ARM_LIB_STACK_MSP$$ZI$$Limit| ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD SecureFault_Handler ; Secure Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + ;SSE-200 Interrupts + DCD NS_WATCHDOG_RESET_IRQHandler ; 0: Non-Secure Watchdog Reset Request Interrupt + DCD NS_WATCHDOG_IRQHandler ; 1: Non-Secure Watchdog Interrupt + DCD S32K_TIMER_IRQHandler ; 2: S32K Timer Interrupt + DCD TIMER0_IRQHandler ; 3: CMSDK Timer 0 Interrupt + DCD TIMER1_IRQHandler ; 4: CMSDK Timer 1 Interrupt + DCD DUALTIMER_IRQHandler ; 5: CMSDK Dual Timer Interrupt + DCD MHU0_IRQHandler ; 6: Message Handling Unit 0 Interrupt + DCD MHU1_IRQHandler ; 7: Message Handling Unit 1 Interrupt + DCD CRYPTOCELL_IRQHandler ; 8: CryptoCell-312 Interrupt + DCD MPC_Handler ; 9: Secure Combined MPC Interrupt + DCD PPC_Handler ; 10: Secure Combined PPC Interrupt + DCD S_MSC_COMBINED_IRQHandler ; 11: Secure Combined MSC Interrupt + DCD S_BRIDGE_ERR_IRQHandler ; 12: Secure Bridge Error Combined Interrupt + DCD I_CACHE_INV_ERR_IRQHandler ; 13: Intsruction Cache Invalidation Interrupt + DCD 0 ; 14: Reserved + DCD SYS_PPU_IRQHandler ; 15: System PPU Interrupt + DCD CPU0_PPU_IRQHandler ; 16: CPU0 PPU Interrupt + DCD CPU1_PPU_IRQHandler ; 17: CPU1 PPU Interrupt + DCD CPU0_DGB_PPU_IRQHandler ; 18: CPU0 Debug PPU Interrupt + DCD CPU1_DGB_PPU_IRQHandler ; 19: CPU1 Debug PPU Interrupt + DCD CRYPTOCELL_PPU_IRQHandler ; 20: CryptoCell PPU Interrupt + DCD 0 ; 21: Reserved + DCD RAM0_PPU_IRQHandler ; 22: RAM 0 PPU Interrupt + DCD RAM1_PPU_IRQHandler ; 23: RAM 1 PPU Interrupt + DCD RAM2_PPU_IRQHandler ; 24: RAM 2 PPU Interrupt + DCD RAM3_PPU_IRQHandler ; 25: RAM 3 PPU Interrupt + DCD DEBUG_PPU_IRQHandler ; 26: Debug PPU Interrupt + DCD 0 ; 27: Reserved + DCD CPU0_CTI_IRQHandler ; 28: CPU0 CTI Interrupt + DCD CPU1_CTI_IRQHandler ; 29: CPU1 CTI Interrupt + DCD 0 ; 30: Reserved + DCD 0 ; 31: Reserved + ;Expansion Interrupts + DCD 0 ; 32: Reserved + DCD GpTimer_IRQHandler ; 33: General Purpose Timer + DCD I2C0_IRQHandler ; 34: I2C0 + DCD I2C1_IRQHandler ; 35: I2C1 + DCD I2S_IRQHandler ; 36: I2S + DCD SPI_IRQHandler ; 37: SPI + DCD QSPI_IRQHandler ; 38: QSPI + DCD UARTRX0_Handler ; 39: UART0 receive FIFO interrupt + DCD UARTTX0_Handler ; 40: UART0 transmit FIFO interrupt + DCD UART0_RxTimeout_IRQHandler ; 41: UART0 receive timeout interrupt + DCD UART0_ModemStatus_IRQHandler ; 42: UART0 modem status interrupt + DCD UART0_Error_IRQHandler ; 43: UART0 error interrupt + DCD UART0_IRQHandler ; 44: UART0 interrupt + DCD UARTRX1_Handler ; 45: UART0 receive FIFO interrupt + DCD UARTTX1_Handler ; 46: UART0 transmit FIFO interrupt + DCD UART1_RxTimeout_IRQHandler ; 47: UART0 receive timeout interrupt + DCD UART1_ModemStatus_IRQHandler ; 48: UART0 modem status interrupt + DCD UART1_Error_IRQHandler ; 49: UART0 error interrupt + DCD UART1_IRQHandler ; 50: UART0 interrupt + DCD GPIO_0_IRQHandler ; 51: GPIO 0 interrupt + DCD GPIO_1_IRQHandler ; 52: GPIO 1 interrupt + DCD GPIO_2_IRQHandler ; 53: GPIO 2 interrupt + DCD GPIO_3_IRQHandler ; 54: GPIO 3 interrupt + DCD GPIO_4_IRQHandler ; 55: GPIO 4 interrupt + DCD GPIO_5_IRQHandler ; 56: GPIO 5 interrupt + DCD GPIO_6_IRQHandler ; 57: GPIO 6 interrupt + DCD GPIO_7_IRQHandler ; 58: GPIO 7 interrupt + DCD GPIO_8_IRQHandler ; 59: GPIO 8 interrupt + DCD GPIO_9_IRQHandler ; 60: GPIO 9 interrupt + DCD GPIO_10_IRQHandler ; 61: GPIO 10 interrupt + DCD GPIO_11_IRQHandler ; 62: GPIO 11 interrupt + DCD GPIO_12_IRQHandler ; 63: GPIO 12 interrupt + DCD GPIO_13_IRQHandler ; 64: GPIO 13 interrupt + DCD GPIO_14_IRQHandler ; 65: GPIO 14 interrupt + DCD GPIO_15_IRQHandler ; 66: GPIO 15 interrupt + DCD Combined_IRQHandler ; 67: Combined interrupt + DCD PVT_IRQHandler ; 68: PVT sensor interrupt + DCD 0 ; 69: Reserved + DCD PWM_0_IRQHandler ; 70: PWM0 interrupt + DCD RTC_IRQHandler ; 71: RTC interrupt + DCD GpTimer0_IRQHandler ; 72: General Purpose Timer0 + DCD GpTimer1_IRQHandler ; 73: General Purpose Timer1 + DCD PWM_1_IRQHandler ; 74: PWM1 interrupt + DCD PWM_2_IRQHandler ; 75: PWM2 interrupt + DCD IOMUX_IRQHandler ; 76: IOMUX interrupt + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + +; Reset Handler + AREA |.text|, CODE, READONLY +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + CPSID i ; Disable IRQs + LDR R0, =SystemInit + BLX R0 + MRS R0, control ; Get control value + ORR R0, R0, #2 ; Select switch to PSP + MSR control, R0 + LDR R0, =__main + BX R0 + ENDP +End_Of_Main + B . + + +; Dummy Exception Handlers (infinite loops which can be modified) + MACRO + Default_Handler $handler_name +$handler_name PROC + EXPORT $handler_name [WEAK] + B . + ENDP + MEND + + Default_Handler NMI_Handler + Default_Handler HardFault_Handler + Default_Handler MemManage_Handler + Default_Handler BusFault_Handler + Default_Handler UsageFault_Handler + Default_Handler SecureFault_Handler + Default_Handler SVC_Handler + Default_Handler DebugMon_Handler + Default_Handler PendSV_Handler + Default_Handler SysTick_Handler + + Default_Handler NS_WATCHDOG_RESET_IRQHandler + Default_Handler NS_WATCHDOG_IRQHandler + Default_Handler S32K_TIMER_IRQHandler + Default_Handler TIMER0_IRQHandler + Default_Handler TIMER1_IRQHandler + Default_Handler DUALTIMER_IRQHandler + Default_Handler MHU0_IRQHandler + Default_Handler MHU1_IRQHandler + Default_Handler CRYPTOCELL_IRQHandler + Default_Handler MPC_Handler + Default_Handler PPC_Handler + Default_Handler S_MSC_COMBINED_IRQHandler + Default_Handler S_BRIDGE_ERR_IRQHandler + Default_Handler I_CACHE_INV_ERR_IRQHandler + Default_Handler SYS_PPU_IRQHandler + Default_Handler CPU0_PPU_IRQHandler + Default_Handler CPU1_PPU_IRQHandler + Default_Handler CPU0_DGB_PPU_IRQHandler + Default_Handler CPU1_DGB_PPU_IRQHandler + Default_Handler CRYPTOCELL_PPU_IRQHandler + Default_Handler RAM0_PPU_IRQHandler + Default_Handler RAM1_PPU_IRQHandler + Default_Handler RAM2_PPU_IRQHandler + Default_Handler RAM3_PPU_IRQHandler + Default_Handler DEBUG_PPU_IRQHandler + Default_Handler CPU0_CTI_IRQHandler + Default_Handler CPU1_CTI_IRQHandler + + Default_Handler GpTimer_IRQHandler + Default_Handler I2C0_IRQHandler + Default_Handler I2C1_IRQHandler + Default_Handler I2S_IRQHandler + Default_Handler SPI_IRQHandler + Default_Handler QSPI_IRQHandler + Default_Handler UARTRX0_Handler + Default_Handler UARTTX0_Handler + Default_Handler UART0_RxTimeout_IRQHandler + Default_Handler UART0_ModemStatus_IRQHandler + Default_Handler UART0_Error_IRQHandler + Default_Handler UART0_IRQHandler + Default_Handler UARTRX1_Handler + Default_Handler UARTTX1_Handler + Default_Handler UART1_RxTimeout_IRQHandler + Default_Handler UART1_ModemStatus_IRQHandler + Default_Handler UART1_Error_IRQHandler + Default_Handler UART1_IRQHandler + Default_Handler GPIO_0_IRQHandler + Default_Handler GPIO_1_IRQHandler + Default_Handler GPIO_2_IRQHandler + Default_Handler GPIO_3_IRQHandler + Default_Handler GPIO_4_IRQHandler + Default_Handler GPIO_5_IRQHandler + Default_Handler GPIO_6_IRQHandler + Default_Handler GPIO_7_IRQHandler + Default_Handler GPIO_8_IRQHandler + Default_Handler GPIO_9_IRQHandler + Default_Handler GPIO_10_IRQHandler + Default_Handler GPIO_11_IRQHandler + Default_Handler GPIO_12_IRQHandler + Default_Handler GPIO_13_IRQHandler + Default_Handler GPIO_14_IRQHandler + Default_Handler GPIO_15_IRQHandler + Default_Handler Combined_IRQHandler + Default_Handler PVT_IRQHandler + Default_Handler PWM_0_IRQHandler + Default_Handler RTC_IRQHandler + Default_Handler GpTimer0_IRQHandler + Default_Handler GpTimer1_IRQHandler + Default_Handler PWM_1_IRQHandler + Default_Handler PWM_2_IRQHandler + Default_Handler IOMUX_IRQHandler + + ALIGN + + END diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_GCC_ARM/musca_s.ld b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_GCC_ARM/musca_s.ld new file mode 100644 index 0000000000..ad7f0f0ad1 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_GCC_ARM/musca_s.ld @@ -0,0 +1,364 @@ +;/* +; * Copyright (c) 2018-2019 ARM Limited +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; * +; * +; * This file is derivative of CMSIS V5.00 gcc_arm.ld +; */ + +/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ + +/* Linker script to configure memory regions. */ +/* This file will be run trough the pre-processor. */ + +#include "../../../partition/region_defs.h" + +#if !defined(TFM_LVL) + #define TFM_LVL 1 +#endif + +MEMORY +{ + FLASH (rx) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE + RAM (rwx) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE + VENEERS (rx) : ORIGIN = CMSE_VENEER_REGION_START, LENGTH = CMSE_VENEER_REGION_SIZE +} + +HEAP_SIZE = S_HEAP_SIZE; +__heap_size__ = S_HEAP_SIZE; +__psp_stack_size__ = S_PSP_STACK_SIZE; +__msp_init_stack_size__ = S_MSP_STACK_SIZE; + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a libc_nano.a) + +ENTRY(Reset_Handler) + +SECTIONS +{ + .TFM_VECTORS : ALIGN(4) + { + __vectors_start__ = .; + KEEP(*(.vectors)) + *startup*(.text*) + . = ALIGN(4); + __vectors_end__ = .; + } > FLASH + +#if TFM_LVL == 1 + .copy.table : ALIGN(4) + { + __copy_table_start__ = .; + LONG (LOADADDR(.TFM_DATA)) + LONG (ADDR(.TFM_DATA)) + LONG (SIZEOF(.TFM_DATA)) + __copy_table_end__ = .; + } > FLASH + + .zero.table : ALIGN(4) + { + __zero_table_start__ = .; + LONG (ADDR(.TFM_BSS)) + LONG (SIZEOF(.TFM_BSS)) + LONG (ADDR(.TFM_SECURE_STACK)) + LONG (SIZEOF(.TFM_SECURE_STACK)) + LONG (ADDR(.TFM_UNPRIV_SCRATCH)) + LONG (SIZEOF(.TFM_UNPRIV_SCRATCH)) + __zero_table_end__ = .; + } > FLASH + +#else /* TFM_LVL == 1 */ + .copy.table : ALIGN(4) + { + __copy_table_start__ = .; + LONG (LOADADDR(.TFM_DATA)) + LONG (ADDR(.TFM_DATA)) + LONG (SIZEOF(.TFM_DATA)) + LONG (LOADADDR(.TFM_UNPRIV_RO_DATA)) + LONG (ADDR(.TFM_UNPRIV_RO_DATA)) + LONG (SIZEOF(.TFM_UNPRIV_RO_DATA)) + LONG (LOADADDR(.TFM_SP_PLATFORM_DATA)) + LONG (ADDR(.TFM_SP_PLATFORM_DATA)) + LONG (SIZEOF(.TFM_SP_PLATFORM_DATA)) + __copy_table_end__ = .; + } > FLASH + + .zero.table : ALIGN(4) + { + __zero_table_start__ = .; + LONG (ADDR(.TFM_BSS)) + LONG (SIZEOF(.TFM_BSS)) + LONG (ADDR(.TFM_UNPRIV_RO_BSS)) + LONG (SIZEOF(.TFM_UNPRIV_RO_BSS)) + LONG (ADDR(.TFM_SP_PLATFORM_BSS)) + LONG (SIZEOF(.TFM_SP_PLATFORM_BSS)) + LONG (ADDR(.TFM_SP_PLATFORM_STACK)) + LONG (SIZEOF(.TFM_SP_PLATFORM_STACK)) + LONG (ADDR(.TFM_UNPRIV_SCRATCH)) + LONG (SIZEOF(.TFM_UNPRIV_SCRATCH)) + __zero_table_end__ = .; + } > FLASH + + .TFM_UNPRIV_CODE : ALIGN(32) + { + *libc_nano*:*(.text*) + *libc_nano*:*(.rodata*) + *tfm_spm_services.o(.text*) + *tfm_spm_services.o(.rodata*) + *platform_retarget_dev.o(.text*) + *platform_retarget_dev.o(.rodata*) + *(SFN) + *libgcc*:*(.text*) + *libgcc*:*(.rodata*) + . = ALIGN(32); + } > FLASH + Image$$TFM_UNPRIV_CODE$$RO$$Base = ADDR(.TFM_UNPRIV_CODE); + Image$$TFM_UNPRIV_CODE$$RO$$Limit = ADDR(.TFM_UNPRIV_CODE) + SIZEOF(.TFM_UNPRIV_CODE); + + .TFM_SP_PLATFORM : ALIGN(32) + { + *tfm_platform*:*(.text*) + *tfm_platform*:*(.rodata*) + *(TFM_SP_PLATFORM_ATTR_FN) + . = ALIGN(32); + } > FLASH + Image$$TFM_SP_PLATFORM$$RO$$Base = ADDR(.TFM_SP_PLATFORM); + Image$$TFM_SP_PLATFORM$$RO$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM); + Image$$TFM_SP_PLATFORM$$Base = ADDR(.TFM_SP_PLATFORM); + Image$$TFM_SP_PLATFORM$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM); + + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + +#endif /* TFM_LVL == 1 */ + + .ER_TFM_CODE : + { + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + OVERLAY S_DATA_START : + { + /* shared_data and msp_stack are overlapping on purpose when + * msp_stack is extended until the beginning of RAM, when shared_date + * was read out by partitions + */ + .tfm_bl2_shared_data + { + . = ALIGN(32); + . += BOOT_TFM_SHARED_DATA_SIZE; + } + + .msp_stack + { + . = ALIGN(32); + . += S_MSP_STACK_SIZE; + } + } > RAM + + Image$$ARM_LIB_STACK_MSP$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack); + + .psp_stack : + { + . = ALIGN(32); + . += S_PSP_STACK_SIZE; + } > RAM + Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.psp_stack); + Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.psp_stack) + SIZEOF(.psp_stack); + +#if TFM_LVL == 1 + + .heap : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + __HeapBase = .; + . += S_HEAP_SIZE; + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + } > RAM + Image$$ARM_LIB_HEAP$$ZI$$Base = ADDR(.heap); + Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap); + + .TFM_SECURE_STACK : + { + . = ALIGN(128); + . += 0x1000; + } > RAM + Image$$TFM_SECURE_STACK$$ZI$$Base = ADDR(.TFM_SECURE_STACK); + Image$$TFM_SECURE_STACK$$ZI$$Limit = ADDR(.TFM_SECURE_STACK) + SIZEOF(.TFM_SECURE_STACK); + + .TFM_UNPRIV_SCRATCH : + { + . = ALIGN(32); + . += 0x400; + } > RAM + Image$$TFM_UNPRIV_SCRATCH$$ZI$$Base = ADDR(.TFM_UNPRIV_SCRATCH); + Image$$TFM_UNPRIV_SCRATCH$$ZI$$Limit = ADDR(.TFM_UNPRIV_SCRATCH) + SIZEOF(.TFM_UNPRIV_SCRATCH); +#else /* TFM_LVL == 1 */ + .TFM_UNPRIV_RO_DATA : + { + */tfm_spm_services.o(.data*) + */platform_retarget_dev.o(.data*) + . = ALIGN(32); + } > RAM AT> FLASH + Image$$TFM_UNPRIV_RO_DATA$$RW$$Base = ADDR(.TFM_UNPRIV_RO_DATA); + Image$$TFM_UNPRIV_RO_DATA$$RW$$Limit = ADDR(.TFM_UNPRIV_RO_DATA) + SIZEOF(.TFM_UNPRIV_RO_DATA); + + .TFM_UNPRIV_RO_BSS : ALIGN(32) + { + */tfm_spm_services.o(.bss*) + */platform_retarget_dev.o(.bss*) + */tfm_spm_services.o(COMMON) + */platform_retarget_dev.o(COMMON) + . = ALIGN(32); + } > RAM AT> FLASH + Image$$TFM_UNPRIV_RO_DATA$$ZI$$Base = ADDR(.TFM_UNPRIV_RO_BSS); + Image$$TFM_UNPRIV_RO_DATA$$ZI$$Limit = ADDR(.TFM_UNPRIV_RO_BSS) + SIZEOF(.TFM_UNPRIV_RO_BSS); + + .TFM_UNPRIV_SCRATCH : ALIGN(32) + { + . += 0x400; + } > RAM AT> FLASH + Image$$TFM_UNPRIV_SCRATCH$$ZI$$Base = ADDR(.TFM_UNPRIV_SCRATCH); + Image$$TFM_UNPRIV_SCRATCH$$ZI$$Limit = ADDR(.TFM_UNPRIV_SCRATCH) + SIZEOF(.TFM_UNPRIV_SCRATCH); + + .TFM_SP_PLATFORM_DATA : ALIGN(32) + { + *tfm_platform*:*(.data*) + . = ALIGN(32); + } > RAM AT> FLASH + Image$$TFM_SP_PLATFORM_DATA$$RW$$Base = ADDR(.TFM_SP_PLATFORM_DATA); + Image$$TFM_SP_PLATFORM_DATA$$RW$$Limit = ADDR(.TFM_SP_PLATFORM_DATA) + SIZEOF(.TFM_SP_PLATFORM_DATA); + + .TFM_SP_PLATFORM_BSS : ALIGN(32) + { + *tfm_platform*:*(.bss*) + *tfm_platform*:*(COMMON) + . = ALIGN(32); + } > RAM AT> FLASH + Image$$TFM_SP_PLATFORM_DATA$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_BSS); + Image$$TFM_SP_PLATFORM_DATA$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_BSS) + SIZEOF(.TFM_SP_PLATFORM_BSS); + + .TFM_SP_PLATFORM_STACK : ALIGN(128) + { + . += 0x0400; + } > RAM AT> FLASH + Image$$TFM_SP_PLATFORM_STACK$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_STACK); + Image$$TFM_SP_PLATFORM_STACK$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_STACK) + SIZEOF(.TFM_SP_PLATFORM_STACK); + +#endif /* TFM_LVL == 1 */ + + .TFM_DATA : + { + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + + } > RAM AT> FLASH + Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA); + Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA); + + .TFM_BSS : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS); + Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS); + + Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA); + Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS); + + ASSERT(Image$$ER_TFM_DATA$$Limit <= S_DATA_START + S_DATA_SIZE, "Exceeding secure RAM") + + /* + * Place the CMSE Veneers (containing the SG instruction) after the code, in a + * separate 32 bytes aligned region so that the SAU can programmed to just set + * this region as Non-Secure Callable. + */ + .gnu.sgstubs : ALIGN(32) + { + *(.gnu.sgstubs*) + . = ALIGN(32); + } > VENEERS AT> VENEERS + Image$$ER_CODE_CMSE_VENEER$$Base = ADDR(.gnu.sgstubs); + Image$$ER_CODE_CMSE_VENEER$$Limit = ADDR(.gnu.sgstubs) + SIZEOF(.gnu.sgstubs); + + Load$$LR$$LR_NS_PARTITION$$Base = NS_PARTITION_START; + + Load$$LR$$LR_SECONDARY_PARTITION$$Base = SECONDARY_PARTITION_START; + + PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit); +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_GCC_ARM/startup_cmsdk_musca_s.S b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_GCC_ARM/startup_cmsdk_musca_s.S new file mode 100644 index 0000000000..0c12d4591b --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/TOOLCHAIN_GCC_ARM/startup_cmsdk_musca_s.S @@ -0,0 +1,365 @@ +;/* +; * Copyright (c) 2009-2019 ARM Limited +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; * +; * +; * This file is derivative of CMSIS V5.00 startup_ARMCM33.S +; */ + + .syntax unified + .arch armv8-m.main + + .section .vectors + .align 2 + .globl __Vectors +__Vectors: + .long Image$$ARM_LIB_STACK_MSP$$ZI$$Limit /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long MemManage_Handler /* MPU Fault Handler */ + .long BusFault_Handler /* Bus Fault Handler */ + .long UsageFault_Handler /* Usage Fault Handler */ + .long SecureFault_Handler /* Secure Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long DebugMon_Handler /* Debug Monitor Handler */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long SysTick_Handler /* SysTick Handler */ + + /* Core interrupts */ + .long NS_WATCHDOG_RESET_IRQHandler /* 0: Non-Secure Watchdog Reset Request Interrupt */ + .long NS_WATCHDOG_IRQHandler /* 1: Non-Secure Watchdog Interrupt */ + .long S32K_TIMER_IRQHandler /* 2: S32K Timer Interrupt */ + .long TIMER0_IRQHandler /* 3: CMSDK Timer 0 Interrupt */ + .long TIMER1_IRQHandler /* 4: CMSDK Timer 1 Interrupt */ + .long DUALTIMER_IRQHandler /* 5: CMSDK Dual Timer Interrupt */ + .long MHU0_IRQHandler /* 6: Message Handling Unit 0 Interrupt */ + .long MHU1_IRQHandler /* 7: Message Handling Unit 1 Interrupt */ + .long CRYPTOCELL_IRQHandler /* 8: CryptoCell-312 Interrupt */ + .long MPC_Handler /* 9: Secure Combined MPC Interrupt */ + .long PPC_Handler /* 10: Secure Combined PPC Interrupt */ + .long S_MSC_COMBINED_IRQHandler /* 11: Secure Combined MSC Interrupt */ + .long S_BRIDGE_ERR_IRQHandler /* 12: Secure Bridge Error Combined Interrupt */ + .long I_CACHE_INV_ERR_IRQHandler /* 13: Intsruction Cache Invalidation Interrupt */ + .long 0 /* 14: Reserved */ + .long SYS_PPU_IRQHandler /* 15: System PPU Interrupt */ + .long CPU0_PPU_IRQHandler /* 16: CPU0 PPU Interrupt */ + .long CPU1_PPU_IRQHandler /* 17: CPU1 PPU Interrupt */ + .long CPU0_DGB_PPU_IRQHandler /* 18: CPU0 Debug PPU Interrupt */ + .long CPU1_DGB_PPU_IRQHandler /* 19: CPU1 Debug PPU Interrupt */ + .long CRYPTOCELL_PPU_IRQHandler /* 20: CryptoCell PPU Interrupt */ + .long 0 /* 21: Reserved */ + .long RAM0_PPU_IRQHandler /* 22: RAM 0 PPU Interrupt */ + .long RAM1_PPU_IRQHandler /* 23: RAM 1 PPU Interrupt */ + .long RAM2_PPU_IRQHandler /* 24: RAM 2 PPU Interrupt */ + .long RAM3_PPU_IRQHandler /* 25: RAM 3 PPU Interrupt */ + .long DEBUG_PPU_IRQHandler /* 26: Debug PPU Interrupt */ + .long 0 /* 27: Reserved */ + .long CPU0_CTI_IRQHandler /* 28: CPU0 CTI Interrupt */ + .long CPU1_CTI_IRQHandler /* 29: CPU1 CTI Interrupt */ + .long 0 /* 30: Reserved */ + .long 0 /* 31: Reserved */ + + /* External interrupts */ + .long 0 /* 32: Reserved */ + .long GpTimer_IRQHandler /* 33: General Purpose Timer */ + .long I2C0_IRQHandler /* 34: I2C0 */ + .long I2C1_IRQHandler /* 35: I2C1 */ + .long I2S_IRQHandler /* 36: I2S */ + .long SPI_IRQHandler /* 37: SPI */ + .long QSPI_IRQHandler /* 38: QSPI */ + .long UARTRX0_Handler /* 39: UART0 receive FIFO interrupt */ + .long UARTTX0_Handler /* 40: UART0 transmit FIFO interrupt */ + .long UART0_RxTimeout_IRQHandler /* 41: UART0 receive timeout interrupt */ + .long UART0_ModemStatus_IRQHandler /* 42: UART0 modem status interrupt */ + .long UART0_Error_IRQHandler /* 43: UART0 error interrupt */ + .long UART0_IRQHandler /* 44: UART0 interrupt */ + .long UARTRX1_Handler /* 45: UART0 receive FIFO interrupt */ + .long UARTTX1_Handler /* 46: UART0 transmit FIFO interrupt */ + .long UART1_RxTimeout_IRQHandler /* 47: UART0 receive timeout interrupt */ + .long UART1_ModemStatus_IRQHandler /* 48: UART0 modem status interrupt */ + .long UART1_Error_IRQHandler /* 49: UART0 error interrupt */ + .long UART1_IRQHandler /* 50: UART0 interrupt */ + .long GPIO_0_IRQHandler /* 51: GPIO 0 interrupt */ + .long GPIO_1_IRQHandler /* 52: GPIO 1 interrupt */ + .long GPIO_2_IRQHandler /* 53: GPIO 2 interrupt */ + .long GPIO_3_IRQHandler /* 54: GPIO 3 interrupt */ + .long GPIO_4_IRQHandler /* 55: GPIO 4 interrupt */ + .long GPIO_5_IRQHandler /* 56: GPIO 5 interrupt */ + .long GPIO_6_IRQHandler /* 57: GPIO 6 interrupt */ + .long GPIO_7_IRQHandler /* 58: GPIO 7 interrupt */ + .long GPIO_8_IRQHandler /* 59: GPIO 8 interrupt */ + .long GPIO_9_IRQHandler /* 60: GPIO 9 interrupt */ + .long GPIO_10_IRQHandler /* 61: GPIO 10 interrupt */ + .long GPIO_11_IRQHandler /* 62: GPIO 11 interrupt */ + .long GPIO_12_IRQHandler /* 63: GPIO 12 interrupt */ + .long GPIO_13_IRQHandler /* 64: GPIO 13 interrupt */ + .long GPIO_14_IRQHandler /* 65: GPIO 14 interrupt */ + .long GPIO_15_IRQHandler /* 66: GPIO 15 interrupt */ + .long Combined_IRQHandler /* 67: Combined interrupt */ + .long PVT_IRQHandler /* 68: PVT sensor interrupt */ + .long 0 /* 69: Reserved */ + .long PWM_0_IRQHandler /* 70: PWM0 interrupt */ + .long RTC_IRQHandler /* 71: RTC interrupt */ + .long GpTimer0_IRQHandler /* 72: General Purpose Timer0 */ + .long GpTimer1_IRQHandler /* 73: General Purpose Timer1 */ + .long PWM_1_IRQHandler /* 74: PWM1 interrupt */ + .long PWM_2_IRQHandler /* 75: PWM2 interrupt */ + .long IOMUX_IRQHandler /* 76: IOMUX interrupt */ + + .size __Vectors, . - __Vectors + + .text + .thumb + .thumb_func + .align 2 + .globl Reset_Handler + .type Reset_Handler, %function +Reset_Handler: +/* Firstly it copies data from read only memory to RAM. There are two schemes + * to copy. One can copy more than one sections. Another can only copy + * one section. The former scheme needs more instructions and read-only + * data to implement than the latter. + * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */ + +#ifdef __STARTUP_COPY_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of triplets, each of which specify: + * offset 0: LMA of start of a section to copy from + * offset 4: VMA of start of a section to copy to + * offset 8: size of the section to copy. Must be multiply of 4 + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r4, =__copy_table_start__ + ldr r5, =__copy_table_end__ + +.L_loop0: + cmp r4, r5 + bge .L_loop0_done + ldr r1, [r4] + ldr r2, [r4, #4] + ldr r3, [r4, #8] + +.L_loop0_0: + subs r3, #4 + ittt ge + ldrge r0, [r1, r3] + strge r0, [r2, r3] + bge .L_loop0_0 + + adds r4, #12 + b .L_loop0 + +.L_loop0_done: +#else +/* Single section scheme. + * + * The ranges of copy from/to are specified by following symbols + * __etext: LMA of start of the section to copy from. Usually end of text + * __data_start__: VMA of start of the section to copy to + * __data_end__: VMA of end of the section to copy to + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + +.L_loop1: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .L_loop1 +#endif /*__STARTUP_COPY_MULTIPLE */ + +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * There are two schemes too. One can clear multiple BSS sections. Another + * can only clear one section. The former is more size expensive than the + * latter. + * + * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former. + * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later. + */ +#ifdef __STARTUP_CLEAR_BSS_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of tuples specifying: + * offset 0: Start of a BSS section + * offset 4: Size of this BSS section. Must be multiply of 4 + */ + ldr r3, =__zero_table_start__ + ldr r4, =__zero_table_end__ + +.L_loop2: + cmp r3, r4 + bge .L_loop2_done + ldr r1, [r3] + ldr r2, [r3, #4] + movs r0, 0 + +.L_loop2_0: + subs r2, #4 + itt ge + strge r0, [r1, r2] + bge .L_loop2_0 + + adds r3, #8 + b .L_loop2 +.L_loop2_done: +#elif defined (__STARTUP_CLEAR_BSS) +/* Single BSS section scheme. + * + * The BSS section is specified by following symbols + * __bss_start__: start of the BSS section. + * __bss_end__: end of the BSS section. + * + * Both addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 +.L_loop3: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .L_loop3 +#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */ + + cpsid i /* Disable IRQs */ + bl SystemInit + + mrs r0, control /* Get control value */ + orr r0, r0, #2 /* Select switch to PSP */ + msr control, r0 + ldr r0, =Image$$ARM_LIB_STACK$$ZI$$Limit + msr psp, r0 + +#ifndef __START +#define __START _start +#endif + bl __START + + .pool + .size Reset_Handler, . - Reset_Handler + + +/* Macro to define default handlers. */ + .macro def_irq_handler handler_name + .align 1 + .thumb_func + .weak \handler_name + \handler_name: + b \handler_name + .endm + + def_irq_handler NMI_Handler + def_irq_handler HardFault_Handler + def_irq_handler MemManage_Handler + def_irq_handler BusFault_Handler + def_irq_handler UsageFault_Handler + def_irq_handler SecureFault_Handler + def_irq_handler SVC_Handler + def_irq_handler DebugMon_Handler + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + + /* Core interrupts */ + def_irq_handler NS_WATCHDOG_RESET_IRQHandler /* 0: Non-Secure Watchdog Reset Request Interrupt */ + def_irq_handler NS_WATCHDOG_IRQHandler /* 1: Non-Secure Watchdog Interrupt */ + def_irq_handler S32K_TIMER_IRQHandler /* 2: S32K Timer Interrupt */ + def_irq_handler TIMER0_IRQHandler /* 3: CMSDK Timer 0 Interrupt */ + def_irq_handler TIMER1_IRQHandler /* 4: CMSDK Timer 1 Interrupt */ + def_irq_handler DUALTIMER_IRQHandler /* 5: CMSDK Dual Timer Interrupt */ + def_irq_handler MHU0_IRQHandler /* 6: Message Handling Unit 0 Interrupt */ + def_irq_handler MHU1_IRQHandler /* 7: Message Handling Unit 1 Interrupt */ + def_irq_handler CRYPTOCELL_IRQHandler /* 8: CryptoCell-312 Interrupt */ + def_irq_handler MPC_Handler /* 9: Secure Combined MPC Interrupt */ + def_irq_handler PPC_Handler /* 10: Secure Combined PPC Interrupt */ + def_irq_handler S_MSC_COMBINED_IRQHandler /* 11: Secure Combined MSC Interrupt */ + def_irq_handler S_BRIDGE_ERR_IRQHandler /* 12: Secure Bridge Error Combined Interrupt */ + def_irq_handler I_CACHE_INV_ERR_IRQHandler /* 13: Intsruction Cache Invalidation Interrupt */ + def_irq_handler SYS_PPU_IRQHandler /* 15: System PPU Interrupt */ + def_irq_handler CPU0_PPU_IRQHandler /* 16: CPU0 PPU Interrupt */ + def_irq_handler CPU1_PPU_IRQHandler /* 17: CPU1 PPU Interrupt */ + def_irq_handler CPU0_DGB_PPU_IRQHandler /* 18: CPU0 Debug PPU Interrupt */ + def_irq_handler CPU1_DGB_PPU_IRQHandler /* 19: CPU1 Debug PPU Interrupt */ + def_irq_handler CRYPTOCELL_PPU_IRQHandler /* 20: CryptoCell PPU Interrupt */ + def_irq_handler RAM0_PPU_IRQHandler /* 22: RAM 0 PPU Interrupt */ + def_irq_handler RAM1_PPU_IRQHandler /* 23: RAM 1 PPU Interrupt */ + def_irq_handler RAM2_PPU_IRQHandler /* 24: RAM 2 PPU Interrupt */ + def_irq_handler RAM3_PPU_IRQHandler /* 25: RAM 3 PPU Interrupt */ + def_irq_handler DEBUG_PPU_IRQHandler /* 26: Debug PPU Interrupt */ + def_irq_handler CPU0_CTI_IRQHandler /* 28: CPU0 CTI Interrupt */ + def_irq_handler CPU1_CTI_IRQHandler /* 29: CPU1 CTI Interrupt */ + + /* External interrupts */ + def_irq_handler GpTimer_IRQHandler /* 33: General Purpose Timer */ + def_irq_handler I2C0_IRQHandler /* 34: I2C0 */ + def_irq_handler I2C1_IRQHandler /* 35: I2C1 */ + def_irq_handler I2S_IRQHandler /* 36: I2S */ + def_irq_handler SPI_IRQHandler /* 37: SPI */ + def_irq_handler QSPI_IRQHandler /* 38: QSPI */ + def_irq_handler UARTRX0_Handler /* 39: UART0 receive FIFO interrupt */ + def_irq_handler UARTTX0_Handler /* 40: UART0 transmit FIFO interrupt */ + def_irq_handler UART0_RxTimeout_IRQHandler /* 41: UART0 receive timeout interrupt */ + def_irq_handler UART0_ModemStatus_IRQHandler /* 42: UART0 modem status interrupt */ + def_irq_handler UART0_Error_IRQHandler /* 43: UART0 error interrupt */ + def_irq_handler UART0_IRQHandler /* 44: UART0 interrupt */ + def_irq_handler UARTRX1_Handler /* 45: UART0 receive FIFO interrupt */ + def_irq_handler UARTTX1_Handler /* 46: UART0 transmit FIFO interrupt */ + def_irq_handler UART1_RxTimeout_IRQHandler /* 47: UART0 receive timeout interrupt */ + def_irq_handler UART1_ModemStatus_IRQHandler /* 48: UART0 modem status interrupt */ + def_irq_handler UART1_Error_IRQHandler /* 49: UART0 error interrupt */ + def_irq_handler UART1_IRQHandler /* 50: UART0 interrupt */ + def_irq_handler GPIO_0_IRQHandler /* 51: GPIO 0 interrupt */ + def_irq_handler GPIO_1_IRQHandler /* 52: GPIO 1 interrupt */ + def_irq_handler GPIO_2_IRQHandler /* 53: GPIO 2 interrupt */ + def_irq_handler GPIO_3_IRQHandler /* 54: GPIO 3 interrupt */ + def_irq_handler GPIO_4_IRQHandler /* 55: GPIO 4 interrupt */ + def_irq_handler GPIO_5_IRQHandler /* 56: GPIO 5 interrupt */ + def_irq_handler GPIO_6_IRQHandler /* 57: GPIO 6 interrupt */ + def_irq_handler GPIO_7_IRQHandler /* 58: GPIO 7 interrupt */ + def_irq_handler GPIO_8_IRQHandler /* 59: GPIO 8 interrupt */ + def_irq_handler GPIO_9_IRQHandler /* 60: GPIO 9 interrupt */ + def_irq_handler GPIO_10_IRQHandler /* 61: GPIO 10 interrupt */ + def_irq_handler GPIO_11_IRQHandler /* 62: GPIO 11 interrupt */ + def_irq_handler GPIO_12_IRQHandler /* 63: GPIO 12 interrupt */ + def_irq_handler GPIO_13_IRQHandler /* 64: GPIO 13 interrupt */ + def_irq_handler GPIO_14_IRQHandler /* 65: GPIO 14 interrupt */ + def_irq_handler GPIO_15_IRQHandler /* 66: GPIO 15 interrupt */ + def_irq_handler Combined_IRQHandler /* 67: Combined interrupt */ + def_irq_handler PVT_IRQHandler /* 68: PVT sensor interrupt */ + def_irq_handler PWM_0_IRQHandler /* 70: PWM0 interrupt */ + def_irq_handler RTC_IRQHandler /* 71: RTC interrupt */ + def_irq_handler GpTimer0_IRQHandler /* 72: General Purpose Timer0 */ + def_irq_handler GpTimer1_IRQHandler /* 73: General Purpose Timer1 */ + def_irq_handler PWM_1_IRQHandler /* 74: PWM1 interrupt */ + def_irq_handler PWM_2_IRQHandler /* 75: PWM2 interrupt */ + def_irq_handler IOMUX_IRQHandler /* 76: IOMUX interrupt */ + + .end diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpc_sie200_drv.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpc_sie200_drv.c new file mode 100644 index 0000000000..5bb9e9fd4b --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpc_sie200_drv.c @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mpc_sie200_drv.h" + +#include + +#include "cmsis.h" + +#define MPC_SIE200_BLK_CFG_OFFSET 5U + +#define MPC_SIE200_CTRL_SEC_RESP (1UL << 4UL) /* MPC fault triggers a + * bus error */ +#define MPC_SIE200_CTRL_AUTOINCREMENT (1UL << 8UL) /* BLK_IDX auto increment */ +#define MPC_SIE200_CTRL_SEC_LOCK_DOWN (1UL << 31UL) /* MPC Security lock down */ + +/* ARM MPC interrupt */ +#define MPC_SIE200_INT_EN 1UL +#define MPC_SIE200_INT_STAT 1UL + +/* ARM MPC state definitions */ +#define MPC_SIE200_INITIALIZED (1 << 0) + +/* Error code returned by the internal driver functions */ +enum mpc_sie200_intern_error_t{ + MPC_SIE200_INTERN_ERR_NONE = MPC_SIE200_ERR_NONE, + MPC_SIE200_INTERN_ERR_NOT_IN_RANGE = MPC_SIE200_ERR_NOT_IN_RANGE, + MPC_SIE200_INTERN_ERR_NOT_ALIGNED = MPC_SIE200_ERR_NOT_ALIGNED, + MPC_SIE200_INTERN_ERR_INVALID_RANGE = MPC_SIE200_ERR_INVALID_RANGE, + MPC_INTERN_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE = + MPC_SIE200_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE, + /* Calculated block index + is higher than the maximum allowed by the MPC. It should never + happen unless the controlled ranges of the MPC are misconfigured + in the driver or if the IP has not enough LUTs to cover the + range, due to wrong reported block size for example. + */ + MPC_SIE200_INTERN_ERR_BLK_IDX_TOO_HIGH = -1, + +}; + +/* ARM MPC memory mapped register access structure */ +struct mpc_sie200_reg_map_t { + volatile uint32_t ctrl; /* (R/W) MPC Control */ + volatile uint32_t reserved[3];/* Reserved */ + volatile uint32_t blk_max; /* (R/ ) Maximum value of block based index */ + volatile uint32_t blk_cfg; /* (R/ ) Block configuration */ + volatile uint32_t blk_idx; /* (R/W) Index value for accessing block + * based look up table */ + volatile uint32_t blk_lutn; /* (R/W) Block based gating + * Look Up Table (LUT) */ + volatile uint32_t int_stat; /* (R/ ) Interrupt state */ + volatile uint32_t int_clear; /* ( /W) Interrupt clear */ + volatile uint32_t int_en; /* (R/W) Interrupt enable */ + volatile uint32_t int_info1; /* (R/ ) Interrupt information 1 */ + volatile uint32_t int_info2; /* (R/ ) Interrupt information 2 */ + volatile uint32_t int_set; /* ( /W) Interrupt set. Debug purpose only */ + volatile uint32_t reserved2[997]; /* Reserved */ + volatile uint32_t pidr4; /* (R/ ) Peripheral ID 4 */ + volatile uint32_t pidr5; /* (R/ ) Peripheral ID 5 */ + volatile uint32_t pidr6; /* (R/ ) Peripheral ID 6 */ + volatile uint32_t pidr7; /* (R/ ) Peripheral ID 7 */ + volatile uint32_t pidr0; /* (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* (R/ ) Component ID 3 */ +}; + +/* + * Checks if the address is controlled by the MPC and returns + * the range index in which it is contained. + * + * \param[in] dev MPC device to initalize \ref mpc_sie200_dev_t + * \param[in] addr Address to check if it is controlled by MPC. + * \param[out] addr_range Range index in which it is contained. + * + * \return True if the base is controller by the range list, false otherwise. + */ +static uint32_t is_ctrl_by_range_list(struct mpc_sie200_dev_t* dev, uint32_t addr, + const struct mpc_sie200_memory_range_t** addr_range) +{ + uint32_t i; + const struct mpc_sie200_memory_range_t* range; + + for(i = 0; i < dev->data->nbr_of_ranges; i++) { + range = dev->data->range_list[i]; + if(addr >= range->base && addr <= range->limit) { + *addr_range = range; + return 1; + } + } + return 0; +} + +/* + * Gets the masks selecting the bits in the LUT of the MPC corresponding + * to the base address (included) up to the limit address (included) + * + * \param[in] mpc_dev The MPC device. + * \param[in] base Address in a range controlled by this MPC + * (included), aligned on block size. + * \param[in] limit Address in a range controlled by this MPC + * (included), aligned on block size. + * \param[out] range Memory range in which the base address and + * limit are. + * \param[out] first_word_idx Index of the first touched word in the LUT. + * \param[out] nr_words Number of words used in the LUT. If 1, only + * first_word_mask is valid and limit_word_mask + * must not be used. + * \param[out] first_word_mask First word mask in the LUT will be stored here. + * \param[out] limit_word_mask Limit word mask in the LUT will be stored here. + * + * \return Returns error code as specified in \ref mpc_sie200_intern_error_t + */ +static enum mpc_sie200_intern_error_t get_lut_masks( + struct mpc_sie200_dev_t* dev, + const uint32_t base, const uint32_t limit, + const struct mpc_sie200_memory_range_t** range, + uint32_t *first_word_idx, + uint32_t *nr_words, + uint32_t *first_word_mask, + uint32_t *limit_word_mask) +{ + const struct mpc_sie200_memory_range_t* base_range; + uint32_t block_size; + uint32_t base_block_idx; + uint32_t base_word_idx; + uint32_t blk_max; + const struct mpc_sie200_memory_range_t* limit_range; + uint32_t limit_block_idx; + uint32_t limit_word_idx; + uint32_t mask; + uint32_t norm_base; + uint32_t norm_limit; + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + /* + * Check that the addresses are within the controlled regions + * of this MPC + */ + if(!is_ctrl_by_range_list(dev, base, &base_range) || + !is_ctrl_by_range_list(dev, limit, &limit_range)) { + return MPC_SIE200_INTERN_ERR_NOT_IN_RANGE; + } + + /* Base and limit should be part of the same range */ + if(base_range != limit_range) { + return MPC_SIE200_INTERN_ERR_INVALID_RANGE; + } + *range = base_range; + + block_size = (1 << (p_mpc->blk_cfg + MPC_SIE200_BLK_CFG_OFFSET)); + + /* Base and limit+1 addresses must be aligned on the MPC block size */ + if(base % block_size || (limit+1) % block_size) { + return MPC_SIE200_INTERN_ERR_NOT_ALIGNED; + } + + /* + * Get a normalized address that is an offset from the beginning + * of the lowest range controlled by the MPC + */ + norm_base = (base - base_range->base) + base_range->range_offset; + norm_limit = (limit - base_range->base) + base_range->range_offset; + + /* + * Calculate block index and to which 32 bits word it belongs + */ + limit_block_idx = norm_limit/block_size; + limit_word_idx = limit_block_idx/32; + + base_block_idx = norm_base/block_size; + base_word_idx = base_block_idx/32; + + if(base_block_idx > limit_block_idx) { + return MPC_SIE200_INTERN_ERR_INVALID_RANGE; + } + + /* Transmit the information to the caller */ + *nr_words = limit_word_idx - base_word_idx + 1; + *first_word_idx = base_word_idx; + + /* Limit to the highest block that can be configured */ + blk_max = p_mpc->blk_max; + + if((limit_word_idx > blk_max) || (base_word_idx > blk_max)) { + return MPC_SIE200_INTERN_ERR_BLK_IDX_TOO_HIGH; + } + + /* + * Create the mask for the first word to only select the limit N bits + */ + *first_word_mask = ~((1 << (base_block_idx % 32)) - 1); + + /* + * Create the mask for the limit word to select only the first M bits. + */ + *limit_word_mask = (1 << ((limit_block_idx+1) % 32)) - 1; + /* + * If limit_word_mask is 0, it means that the limit touched block index is + * the limit in its word, so the limit word mask has all its bits selected + */ + if(*limit_word_mask == 0) { + *limit_word_mask = 0xFFFFFFFF; + } + + /* + * If the blocks to configure are all packed in one word, only + * touch this word. + * Code using the computed masks should test if this mask + * is non-zero, and if so, only use this one instead of the limit_word_mask + * and first_word_mask. + * As the only bits that are the same in both masks are the 1 that we want + * to select, just use XOR to extract them. + */ + if(base_word_idx == limit_word_idx) { + mask = ~(*first_word_mask ^ *limit_word_mask); + *first_word_mask = mask; + *limit_word_mask = mask; + } + + return MPC_SIE200_INTERN_ERR_NONE; +} + +enum mpc_sie200_error_t mpc_sie200_init(struct mpc_sie200_dev_t* dev, + const struct mpc_sie200_memory_range_t** range_list, + uint8_t nbr_of_ranges) +{ + if((range_list == NULL) || (nbr_of_ranges == 0)) { + return MPC_SIE200_INVALID_ARG; + } + + dev->data->range_list = range_list; + dev->data->nbr_of_ranges = nbr_of_ranges; + dev->data->state = MPC_SIE200_INITIALIZED; + + return MPC_SIE200_ERR_NONE; +} + +enum mpc_sie200_error_t mpc_sie200_get_block_size(struct mpc_sie200_dev_t* dev, + uint32_t* blk_size) +{ + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & MPC_SIE200_INITIALIZED)) { + return MPC_SIE200_NOT_INIT; + } + + if(blk_size == 0) { + return MPC_SIE200_INVALID_ARG; + } + + /* Calculate the block size in byte according to the manual */ + *blk_size = (1 << (p_mpc->blk_cfg + MPC_SIE200_BLK_CFG_OFFSET)); + + return MPC_SIE200_ERR_NONE; +} + +enum mpc_sie200_error_t mpc_sie200_config_region(struct mpc_sie200_dev_t* dev, + const uint32_t base, + const uint32_t limit, + enum mpc_sie200_sec_attr_t attr) +{ + enum mpc_sie200_intern_error_t error; + uint32_t first_word_idx; + uint32_t first_word_mask; + uint32_t i; + uint32_t limit_word_mask; + uint32_t limit_word_idx; + uint32_t nr_words; + const struct mpc_sie200_memory_range_t* range; + uint32_t word_value; + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & MPC_SIE200_INITIALIZED)) { + return MPC_SIE200_NOT_INIT; + } + + /* Get the bitmasks used to select the bits in the LUT */ + error = get_lut_masks(dev, base, limit, &range, &first_word_idx, &nr_words, + &first_word_mask, &limit_word_mask); + + limit_word_idx = first_word_idx + nr_words - 1; + + if(error != MPC_SIE200_INTERN_ERR_NONE) { + /* Map internal error code lower than 0 to a generic errpr */ + if(error < 0) { + return MPC_SIE200_ERR_INVALID_RANGE; + } + return (enum mpc_sie200_error_t)error; + } + + /* + * The memory range should allow accesses in with the wanted security + * attribute if it requires special attribute for successfull accesses + */ + if(range->attr != attr) { + return MPC_SIE200_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE; + } + + /* + * Starts changing actual configuration so issue DMB to ensure every + * transaction has completed by now + */ + __DMB(); + + /* Set the block index to the first word that will be updated */ + p_mpc->blk_idx = first_word_idx; + + /* If only one word needs to be touched in the LUT */ + if(nr_words == 1) { + word_value = p_mpc->blk_lutn; + if(attr == MPC_SIE200_SEC_ATTR_NONSECURE) { + word_value |= first_word_mask; + } else { + word_value &= ~first_word_mask; + } + + /* + * Set the index again because full word read or write could have + * incremented it + */ + p_mpc->blk_idx = first_word_idx; + p_mpc->blk_lutn = word_value; + + /* Commit the configuration change */ + __DSB(); + __ISB(); + + return MPC_SIE200_ERR_NONE; + } + + /* First word */ + word_value = p_mpc->blk_lutn; + if(attr == MPC_SIE200_SEC_ATTR_NONSECURE) { + word_value |= first_word_mask; + } else { + word_value &= ~first_word_mask; + } + /* + * Set the index again because full word read or write could have + * incremented it + */ + p_mpc->blk_idx = first_word_idx; + /* Partially configure the first word */ + p_mpc->blk_lutn = word_value; + + /* Fully configure the intermediate words if there are any */ + for(i=first_word_idx+1; iblk_idx = i; + if(attr == MPC_SIE200_SEC_ATTR_NONSECURE) { + p_mpc->blk_lutn = 0xFFFFFFFF; + } else { + p_mpc->blk_lutn = 0x00000000; + } + } + + /* Partially configure the limit word */ + p_mpc->blk_idx = limit_word_idx; + word_value = p_mpc->blk_lutn; + if(attr == MPC_SIE200_SEC_ATTR_NONSECURE) { + word_value |= limit_word_mask; + } else { + word_value &= ~limit_word_mask; + } + p_mpc->blk_idx = limit_word_idx; + p_mpc->blk_lutn = word_value; + + /* Commit the configuration change */ + __DSB(); + __ISB(); + + return MPC_SIE200_ERR_NONE; +} + +enum mpc_sie200_error_t mpc_sie200_get_region_config( + struct mpc_sie200_dev_t* dev, + uint32_t base, uint32_t limit, + enum mpc_sie200_sec_attr_t* attr) +{ + enum mpc_sie200_sec_attr_t attr_prev; + uint32_t block_size; + uint32_t block_size_mask; + enum mpc_sie200_intern_error_t error; + uint32_t first_word_idx; + uint32_t first_word_mask; + uint32_t i; + uint32_t limit_word_idx; + uint32_t limit_word_mask; + uint32_t nr_words; + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + const struct mpc_sie200_memory_range_t* range; + uint32_t word_value; + + if(!(dev->data->state & MPC_SIE200_INITIALIZED)) { + return MPC_SIE200_NOT_INIT; + } + + if(attr == 0) { + return MPC_SIE200_INVALID_ARG; + } + + /* + * Initialize the security attribute to mixed in case of early + * termination of this function. A caller that does not check the + * returned error will act as if it does not know anything about the + * region queried, which is the safest bet + */ + *attr = MPC_SIE200_SEC_ATTR_MIXED; + + /* + * If the base and limit are not aligned, align them and make sure + * that the resulting region fully includes the original region + */ + block_size = (1 << (p_mpc->blk_cfg + MPC_SIE200_BLK_CFG_OFFSET)); + + block_size_mask = block_size - 1; + base &= ~(block_size_mask); + limit &= ~(block_size_mask); + limit += block_size - 1; /* Round to the upper block address, + * and then remove one to get the preceding + * address. + */ + + /* Get the bitmasks used to select the bits in the LUT */ + error = get_lut_masks(dev, base, limit, &range, &first_word_idx, &nr_words, + &first_word_mask, &limit_word_mask); + + limit_word_idx = first_word_idx+nr_words - 1; + + if(error != MPC_SIE200_INTERN_ERR_NONE) { + /* Map internal error code lower than 0 to generic error */ + if(error < 0) { + return MPC_SIE200_ERR_INVALID_RANGE; + } + return (enum mpc_sie200_error_t)error; + } + + /* Set the block index to the first word that will be updated */ + p_mpc->blk_idx = first_word_idx; + + /* If only one word needs to be touched in the LUT */ + if(nr_words == 1) { + word_value = p_mpc->blk_lutn; + word_value &= first_word_mask; + if(word_value == 0) { + *attr = MPC_SIE200_SEC_ATTR_SECURE; + /* + * If there are differences between the mask and the word value, + * it means that the security attributes of blocks are mixed + */ + } else if(word_value ^ first_word_mask) { + *attr = MPC_SIE200_SEC_ATTR_MIXED; + } else { + *attr = MPC_SIE200_SEC_ATTR_NONSECURE; + } + return MPC_SIE200_ERR_NONE; + } + + /* Get the partial configuration of the first word */ + word_value = p_mpc->blk_lutn & first_word_mask; + if(word_value == 0x00000000) { + *attr = MPC_SIE200_SEC_ATTR_SECURE; + } else if(word_value ^ first_word_mask) { + *attr = MPC_SIE200_SEC_ATTR_MIXED; + /* + * Bail out as the security attribute will be the same regardless + * of the configuration of other blocks + */ + return MPC_SIE200_ERR_NONE; + } else { + *attr = MPC_SIE200_SEC_ATTR_NONSECURE; + } + /* + * Store the current found attribute, to check that all the blocks indeed + * have the same security attribute. + */ + attr_prev = *attr; + + /* Get the configuration of the intermediate words if there are any */ + for(i=first_word_idx+1; iblk_idx = i; + word_value = p_mpc->blk_lutn; + if(word_value == 0x00000000) { + *attr = MPC_SIE200_SEC_ATTR_SECURE; + } else if(word_value == 0xFFFFFFFF) { + *attr = MPC_SIE200_SEC_ATTR_NONSECURE; + } else { + *attr = MPC_SIE200_SEC_ATTR_MIXED; + return MPC_SIE200_ERR_NONE; + } + + /* If the attribute is different than the one found before, bail out */ + if(*attr != attr_prev) { + *attr = MPC_SIE200_SEC_ATTR_MIXED; + return MPC_SIE200_ERR_NONE; + } + attr_prev = *attr; + } + + /* Get the partial configuration of the limit word */ + p_mpc->blk_idx = limit_word_idx; + word_value = p_mpc->blk_lutn & limit_word_mask; + if(word_value == 0x00000000) { + *attr = MPC_SIE200_SEC_ATTR_SECURE; + } else if(word_value ^ first_word_mask) { + *attr = MPC_SIE200_SEC_ATTR_MIXED; + return MPC_SIE200_ERR_NONE; + } else { + *attr = MPC_SIE200_SEC_ATTR_NONSECURE; + } + + if(*attr != attr_prev) { + *attr = MPC_SIE200_SEC_ATTR_MIXED; + return MPC_SIE200_ERR_NONE; + } + + return MPC_SIE200_ERR_NONE; +} + +enum mpc_sie200_error_t mpc_sie200_get_ctrl(struct mpc_sie200_dev_t* dev, + uint32_t* ctrl_val) +{ + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & MPC_SIE200_INITIALIZED)) { + return MPC_SIE200_NOT_INIT; + } + + if(ctrl_val == 0) { + return MPC_SIE200_INVALID_ARG; + } + + *ctrl_val = p_mpc->ctrl; + + return MPC_SIE200_ERR_NONE; +} + +enum mpc_sie200_error_t mpc_sie200_set_ctrl(struct mpc_sie200_dev_t* dev, + uint32_t mpc_ctrl) +{ + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & MPC_SIE200_INITIALIZED)) { + return MPC_SIE200_NOT_INIT; + } + + p_mpc->ctrl = mpc_ctrl; + + return MPC_SIE200_ERR_NONE; +} + +enum mpc_sie200_error_t mpc_sie200_get_sec_resp(struct mpc_sie200_dev_t* dev, + enum mpc_sie200_sec_resp_t* sec_rep) +{ + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & MPC_SIE200_INITIALIZED)) { + return MPC_SIE200_NOT_INIT; + } + + if(sec_rep == 0) { + return MPC_SIE200_INVALID_ARG; + } + + if(p_mpc->ctrl & MPC_SIE200_CTRL_SEC_RESP) { + *sec_rep = MPC_SIE200_RESP_BUS_ERROR; + return MPC_SIE200_ERR_NONE; + } + + *sec_rep = MPC_SIE200_RESP_RAZ_WI; + + return MPC_SIE200_ERR_NONE; +} + +enum mpc_sie200_error_t mpc_sie200_irq_enable(struct mpc_sie200_dev_t* dev) +{ + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & MPC_SIE200_INITIALIZED)) { + return MPC_SIE200_NOT_INIT; + } + + p_mpc->int_en |= MPC_SIE200_INT_EN; + + return MPC_SIE200_ERR_NONE; +} + +void mpc_sie200_irq_disable(struct mpc_sie200_dev_t* dev) +{ + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + p_mpc->int_en &= ~MPC_SIE200_INT_EN; +} + +void mpc_sie200_clear_irq(struct mpc_sie200_dev_t* dev) +{ + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + p_mpc->int_clear = MPC_SIE200_INT_EN; +} + +uint32_t mpc_sie200_irq_state(struct mpc_sie200_dev_t* dev) +{ + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + return (p_mpc->int_stat & MPC_SIE200_INT_STAT); +} + +enum mpc_sie200_error_t mpc_sie200_lock_down(struct mpc_sie200_dev_t* dev) +{ + struct mpc_sie200_reg_map_t* p_mpc = + (struct mpc_sie200_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & MPC_SIE200_INITIALIZED)) { + return MPC_SIE200_NOT_INIT; + } + + p_mpc->ctrl |= (MPC_SIE200_CTRL_AUTOINCREMENT + | MPC_SIE200_CTRL_SEC_LOCK_DOWN); + + return MPC_SIE200_ERR_NONE; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpc_sie200_drv.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpc_sie200_drv.h new file mode 100644 index 0000000000..27a1c79290 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpc_sie200_drv.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file mpc_sie200_drv.h + * \brief Generic driver for ARM SIE 200 Memory Protection + * Controllers (MPC). + */ + +#ifndef __MPC_SIE_200_DRV_H__ +#define __MPC_SIE_200_DRV_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Error code returned by the driver functions */ +enum mpc_sie200_error_t { + MPC_SIE200_ERR_NONE, /*!< No error */ + MPC_SIE200_INVALID_ARG, /*!< MPC invalid input arguments */ + MPC_SIE200_NOT_INIT, /*!< MPC not initialized */ + MPC_SIE200_ERR_NOT_IN_RANGE, /*!< Address does not belong to a range + * controlled by the MPC */ + MPC_SIE200_ERR_NOT_ALIGNED, /*!< Address is not aligned on the block size + * of this MPC */ + MPC_SIE200_ERR_INVALID_RANGE, /*!< The given address range to configure + * is invalid. This could be because: + * - The base and limit swapped + * - The base and limit addresses + * are in different ranges */ + MPC_SIE200_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE, /*!< The given range cannot be + * accessed with the wanted + * security attributes */ +}; + +/* Security attribute used in various place of the API */ +enum mpc_sie200_sec_attr_t { + MPC_SIE200_SEC_ATTR_SECURE, /*!< Secure attribute */ + MPC_SIE200_SEC_ATTR_NONSECURE, /*!< Non-secure attribute */ + /*!< Used when getting the configuration of a memory range and some blocks + * are secure whereas some other are non secure */ + MPC_SIE200_SEC_ATTR_MIXED, +}; + +/* What can happen when trying to do an illegal memory access */ +enum mpc_sie200_sec_resp_t { + MPC_SIE200_RESP_RAZ_WI, /*!< Read As Zero, Write Ignored */ + MPC_SIE200_RESP_BUS_ERROR /*!< Bus error */ +}; + +/* Description of a memory range controlled by the MPC */ +struct mpc_sie200_memory_range_t { + const uint32_t base; /*!< Base address (included in the range) */ + const uint32_t limit; /*!< Limit address (included in the range) */ + const uint32_t range_offset; /*!< Offset of current range area to the 0 + point of the whole area (the sum of the + sizes of the previous memory ranges + covered by the same MPC) */ + const enum mpc_sie200_sec_attr_t attr; /*!< Optional security attribute + needed to be matched when + accessing this range. + For example, the non-secure + alias of a memory region can not + be accessed using secure access, + and configuring the MPC to + secure using that range will not + be permitted by the driver. */ +}; + +/* ARM MPC SIE 200 device configuration structure */ +struct mpc_sie200_dev_cfg_t { + const uint32_t base; /*!< MPC base address */ +}; + +/* ARM MPC SIE 200 device data structure */ +struct mpc_sie200_dev_data_t { + const struct mpc_sie200_memory_range_t** range_list; /*!< Array of pointers + to memory ranges + controlled by + the MPC */ + uint8_t nbr_of_ranges; /*!< Number of memory ranges in the list */ + uint8_t state; /*!< Indicates if the MPC driver + is initialized and enabled */ + uint16_t reserved; /*!< 32 bits alignment */ +}; + +/* ARM MPC SIE 200 device structure */ +struct mpc_sie200_dev_t { + const struct mpc_sie200_dev_cfg_t* const cfg; /*!< MPC configuration */ + struct mpc_sie200_dev_data_t* const data; /*!< MPC data */ +}; + +/** + * \brief Initializes a MPC device. + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * \param[in] range_list List of memory ranges controller by the MPC + * (\ref mpc_sie200_memory_range_t). This list can not + * freed after the initializations. + * \param[in] nbr_of_ranges Number of memory ranges + * + * \return Returns error code as specified in \ref mpc_sie200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie200_error_t mpc_sie200_init(struct mpc_sie200_dev_t* dev, + const struct mpc_sie200_memory_range_t** range_list, + uint8_t nbr_of_ranges); + +/** + * \brief Gets MPC block size. All regions must be aligned on this block + * size (base address and limit+1 address). + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * \param[out] blk_size MPC block size + * + * \return Returns error code as specified in \ref mpc_sie200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie200_error_t mpc_sie200_get_block_size(struct mpc_sie200_dev_t* dev, + uint32_t* blk_size); + +/** + * \brief Configures a memory region (base and limit included). + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * \param[in] base Base address of the region to poll. This bound is + * included. It does not need to be aligned in any way. + * + * \param[in] limit Limit address of the region to poll. This bound is + * included. (limit+1) does not need to be aligned + * in any way. + * \param[in] attr Security attribute of the region. If the region has mixed + * secure/non-secure, a special value is returned + * (\ref mpc_sie200_sec_attr_t). + * + * In case base and limit+1 addresses are not aligned on + * the block size, the enclosing region with base and + * limit+1 aligned on block size will be queried. + * In case of early termination of the function (error), the + * security attribute will be set to MPC_SIE200_ATTR_MIXED. + * + * \return Returns error code as specified in \ref mpc_sie200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie200_error_t mpc_sie200_config_region(struct mpc_sie200_dev_t* dev, + const uint32_t base, + const uint32_t limit, + enum mpc_sie200_sec_attr_t attr); + +/** + * \brief Gets a memory region configuration(base and limit included). + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * \param[in] base Base address of the region to get the configuration. + * \param[in] limit Limit address of the region to get the configuration. + * \param[out] attr Security attribute of the region + * \ref mpc_sie200_sec_attr_t + * + * \return Returns error code as specified in \ref mpc_sie200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie200_error_t mpc_sie200_get_region_config( + struct mpc_sie200_dev_t* dev, + uint32_t base, + uint32_t limit, + enum mpc_sie200_sec_attr_t* attr); + +/** + * \brief Gets the MPC control value. + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * \param[out] ctrl_val Current MPC control value. + * + * \return Returns error code as specified in \ref mpc_sie200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie200_error_t mpc_sie200_get_ctrl(struct mpc_sie200_dev_t* dev, + uint32_t* ctrl_val); + +/** + * \brief Sets the MPC control value. + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * \param[in] mpc_ctrl New MPC control value + * + * \return Returns error code as specified in \ref mpc_sie200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie200_error_t mpc_sie200_set_ctrl(struct mpc_sie200_dev_t* dev, + uint32_t mpc_ctrl); + +/** + * \brief Gets the configured secure response. + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * \param[out] sec_rep Configured secure response (\ref mpc_sie200_sec_resp_t). + * + * \return Returns error code as specified in \ref mpc_sie200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie200_error_t mpc_sie200_get_sec_resp(struct mpc_sie200_dev_t* dev, + enum mpc_sie200_sec_resp_t* sec_rep); + +/** + * \brief Enables MPC interrupt. + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * + * \return Returns error code as specified in \ref mpc_sie200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie200_error_t mpc_sie200_irq_enable(struct mpc_sie200_dev_t* dev); + +/** + * \brief Disables MPC interrupt + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void mpc_sie200_irq_disable(struct mpc_sie200_dev_t* dev); + +/** + * \brief Clears MPC interrupt. + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void mpc_sie200_clear_irq(struct mpc_sie200_dev_t* dev); + +/** + * \brief Returns the MPC interrupt state. + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * + * \return Returns 1 if the interrupt is active, 0 otherwise. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t mpc_sie200_irq_state(struct mpc_sie200_dev_t* dev); + +/** + * \brief Locks down the MPC configuration. + * + * \param[in] dev MPC device \ref mpc_sie200_dev_t + * + * \return Returns error code as specified in \ref mpc_sie200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie200_error_t mpc_sie200_lock_down(struct mpc_sie200_dev_t* dev); + +#ifdef __cplusplus +} +#endif +#endif /* __MPC_SIE_200_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpu_armv8m_drv.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpu_armv8m_drv.c new file mode 100644 index 0000000000..4aa70c7f16 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpu_armv8m_drv.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2017-2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "mpu_armv8m_drv.h" +#include "cmsis_cpu.h" + +/* + * FixMe: + * This is a beta quality driver for MPU in v8M. To be finalized. + */ + +enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev, + uint32_t privdef_en, + uint32_t hfnmi_en) +{ + /*No error checking*/ + + MPU_Type *mpu = (MPU_Type *)dev->base; + + mpu->CTRL = + (privdef_en ? MPU_CTRL_PRIVDEFENA_Msk : 0) | + (hfnmi_en ? MPU_CTRL_HFNMIENA_Msk : 0); + + /*Ensure all configuration is written before enable*/ + + mpu->CTRL |= MPU_CTRL_ENABLE_Msk; + + /* Enable MPU before next instruction */ + __asm("DSB"); + __asm("ISB"); + return MPU_ARMV8M_OK; +} + +enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev) +{ + MPU_Type *mpu = (MPU_Type *)dev->base; + + /* Reset all fields as enable does full setup */ + mpu->CTRL = 0; + + return MPU_ARMV8M_OK; +} + + +enum mpu_armv8m_error_t mpu_armv8m_region_enable( + struct mpu_armv8m_dev_t *dev, + struct mpu_armv8m_region_cfg_t *region_cfg) +{ + MPU_Type *mpu = (MPU_Type *)dev->base; + + enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK; + uint32_t ctrl_before; + uint32_t base_cfg; + uint32_t limit_cfg; + + /*FIXME : Add complete error checking*/ + if ((region_cfg->region_base & ~MPU_RBAR_BASE_Msk) != 0) { + return MPU_ARMV8M_ERROR; + } + /* region_limit doesn't need to be aligned but the scatter + * file needs to be setup to ensure that partitions do not overlap. + */ + + ctrl_before = mpu->CTRL; + mpu->CTRL = 0; + + mpu->RNR = region_cfg->region_nr & MPU_RNR_REGION_Msk; + + /* This 0s the lower bits of the base address */ + base_cfg = region_cfg->region_base & MPU_RBAR_BASE_Msk; + base_cfg |= (region_cfg->attr_sh << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk; + base_cfg |= (region_cfg->attr_access << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk; + base_cfg |= (region_cfg->attr_exec << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk; + + mpu->RBAR = base_cfg; + + /*This 0s the lower bits of base address but they are treated as 1 */ + limit_cfg = (region_cfg->region_limit-1) & MPU_RLAR_LIMIT_Msk; + + /*FIXME: Enable the memory attr setting */ + limit_cfg |= MPU_RLAR_EN_Msk; + + mpu->RLAR = limit_cfg; + + /*Restore main MPU control*/ + mpu->CTRL = ctrl_before; + + /* Enable MPU before the next instruction */ + __asm("DSB"); + __asm("ISB"); + + return ret_val; +} + + +enum mpu_armv8m_error_t mpu_armv8m_region_disable( + struct mpu_armv8m_dev_t *dev, + uint32_t region_nr) +{ + + MPU_Type *mpu = (MPU_Type *)dev->base; + + enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK; + uint32_t ctrl_before; + + /*FIXME : Add complete error checking*/ + + ctrl_before = mpu->CTRL; + mpu->CTRL = 0; + + mpu->RNR = region_nr & MPU_RNR_REGION_Msk; + + mpu->RBAR = 0; + mpu->RLAR = 0; + + /*Restore main MPU control*/ + mpu->CTRL = ctrl_before; + + return ret_val; +} + +enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev) +{ + MPU_Type *mpu = (MPU_Type *)dev->base; + uint32_t i = (mpu->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; + + while (i > 0) { + mpu_armv8m_region_disable(dev, i-1); + i--; + } + + return MPU_ARMV8M_OK; + +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpu_armv8m_drv.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpu_armv8m_drv.h new file mode 100644 index 0000000000..0abf7fd33f --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/mpu_armv8m_drv.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __MPU_ARMV8M_DRV_H__ +#define __MPU_ARMV8M_DRV_H__ + +#include + +#include "cmsis.h" + +#define PRIVILEGED_DEFAULT_ENABLE 1 +#define HARDFAULT_NMI_ENABLE 1 + +struct mpu_armv8m_dev_t { + const uint32_t base; +}; + +enum mpu_armv8m_error_t { + MPU_ARMV8M_OK, + MPU_ARMV8M_ERROR +}; + +enum mpu_armv8m_attr_exec_t { + MPU_ARMV8M_XN_EXEC_OK, + MPU_ARMV8M_XN_EXEC_NEVER +}; + +enum mpu_armv8m_attr_access_t { + MPU_ARMV8M_AP_RW_PRIV_ONLY, + MPU_ARMV8M_AP_RW_PRIV_UNPRIV, + MPU_ARMV8M_AP_RO_PRIV_ONLY, + MPU_ARMV8M_AP_RO_PRIV_UNPRIV +}; + +enum mpu_armv8m_attr_shared_t { + MPU_ARMV8M_SH_NONE, + MPU_ARMV8M_SH_UNUSED, + MPU_ARMV8M_SH_OUTER, + MPU_ARMV8M_SH_INNER +}; + +struct mpu_armv8m_region_cfg_t { + uint32_t region_nr; + uint32_t region_base; + uint32_t region_limit; + enum mpu_armv8m_attr_exec_t attr_exec; + enum mpu_armv8m_attr_access_t attr_access; + enum mpu_armv8m_attr_shared_t attr_sh; +}; + +struct mpu_armv8m_region_cfg_raw_t { + uint32_t region_nr; + uint32_t region_base; + uint32_t region_limit; +}; + + +/** + * \brief Enable MPU + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * \param[in] privdef_en privilege default region 1:enable 0:disable + * \param[in] hfnmi_en mpu for hard fault & nmi 1:enable 0:disable + * + * \return Error code \ref mpu_armv8m_error_t + * + * \note This function doesn't check if dev is NULL. + */ + +enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev, + uint32_t privdef_en, + uint32_t hfnmi_en); + +/** + * \brief Disable MPU + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * + * \return Error code \ref arm_mpu_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev); + +/** + * \brief Disable MPU and clean all regions + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * + * \return Error code \ref arm_mpu_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev); + +/** + * \brief Enable MPU Region + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * \param[in] region_cfg MPU region config \ref mpu_armv8m_region_cfg_t + * + * \return Error code \ref arm_mpu_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpu_armv8m_error_t mpu_armv8m_region_enable( + struct mpu_armv8m_dev_t *dev, + struct mpu_armv8m_region_cfg_t *region_cfg); + +/** + * \brief Disable MPU Region + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * \param[in] region_nr Region number + * + * \return Error code \ref arm_mpu_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpu_armv8m_error_t mpu_armv8m_region_disable( + struct mpu_armv8m_dev_t *dev, + uint32_t region_nr); + +#endif /* __MPU_ARMV8M_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/ppc_sse200_drv.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/ppc_sse200_drv.c new file mode 100644 index 0000000000..2ea46b8043 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/ppc_sse200_drv.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ppc_sse200_drv.h" + +/* SPCTRL PPCs control memory mapped registers access structure */ +struct arm_spctrl_ppc_sse200_t { + volatile uint32_t reserved[8]; + volatile uint32_t secppcintstat; /* Secure PPC Interrupt Status */ + volatile uint32_t secppcintclr; /* Secure PPC Interrupt Clear */ + volatile uint32_t secppcinten; /* Secure PPC Interrupt Enable */ + volatile uint32_t reserved1[9]; + volatile uint32_t ahbnsppc0; /* Non-Secure Access AHB slave Peripheral + Protection Control #0 */ + volatile uint32_t reserved2[3]; /* Reserved for Future Non-secure Access + AHB Slave Peripheral Protection + Control */ + volatile uint32_t ahbnsppcexp0; /* Expansion 0 Non_Secure Access AHB + slave Peripheral Protection Control */ + volatile uint32_t ahbnsppcexp1; /* Expansion 1 Non_Secure Access AHB + slave Peripheral Protection Control */ + volatile uint32_t ahbnsppcexp2; /* Expansion 2 Non_Secure Access AHB + slave Peripheral Protection Control */ + volatile uint32_t ahbnsppcexp3; /* Expansion 3 Non_Secure Access AHB + slave Peripheral Protection Control */ + volatile uint32_t apbnsppc0; /* Non-Secure Access APB slave Peripheral + Protection Control 0 */ + volatile uint32_t apbnsppc1; /* Non-Secure Access APB slave Peripheral + Protection Control 1 */ + volatile uint32_t reserved3[2]; /* Non-Secure Access APB slave Peripheral + Protection Control [3:1] */ + volatile uint32_t apbnsppcexp0; /* Expansion 0 Non_Secure Access APB + slave Peripheral Protection Control */ + volatile uint32_t apbnsppcexp1; /* Expansion 1 Non_Secure Access APB + slave Peripheral Protection Control */ + volatile uint32_t apbnsppcexp2; /* Expansion 2 Non_Secure Access APB + slave Peripheral Protection Control */ + volatile uint32_t apbnsppcexp3; /* Expansion 3 Non_Secure Access APB + slave Peripheral Protection Control */ + volatile uint32_t ahbspppc0; /* Secure Unprivileged Access AHB slave + Peripheral Protection Control 0 */ + volatile uint32_t reserved4[3]; /* Reserved for Future Secure Unprivileged + Access AHB slave Peripheral Protection + Control */ + volatile uint32_t ahbspppcexp0; /* Expansion 0 Secure Unprivileged Access + AHB slave Peripheral Protection + Control */ + volatile uint32_t ahbspppcexp1; /* Expansion 1 Secure Unprivileged Access + AHB slave Peripheral Protection + Control */ + volatile uint32_t ahbspppcexp2; /* Expansion 2 Secure Unprivileged Access + AHB slave Peripheral Protection + Control */ + volatile uint32_t ahbspppcexp3; /* Expansion 3 Secure Unprivileged Access + AHB slave Peripheral Protection + Control */ + volatile uint32_t apbspppc0; /* Secure Unprivileged Access APB slave + Peripheral 0 */ + volatile uint32_t apbspppc1; /* Secure Unprivileged Access APB slave + Peripheral 1 */ + volatile uint32_t reserved5[2]; /* Reserved for Future Secure Unprivileged + Access APB slave Peripheral Protection + Control */ + volatile uint32_t apbspppcexp0; /* Expansion 0 Secure Unprivileged Access + APB slave Peripheral Protection + Control */ + volatile uint32_t apbspppcexp1; /* Expansion 1 Secure Unprivileged Access + APB slave Peripheral Protection + Control */ + volatile uint32_t apbspppcexp2; /* Expansion 2 Secure Unprivileged Access + APB slave Peripheral Protection + Control */ + volatile uint32_t apbspppcexp3; /* Expansion 3 Secure Unprivileged Access + APB slave Peripheral Protection + Control */ +}; + +/* NSPCTRL PPCs memory mapped register access structure */ +struct arm_nspctrl_ppc_sse200_t { + volatile uint32_t reserved[36]; + volatile uint32_t ahbnspppc0; + volatile uint32_t reserved1[3]; + volatile uint32_t ahbnspppcexp0; + volatile uint32_t ahbnspppcexp1; + volatile uint32_t ahbnspppcexp2; + volatile uint32_t ahbnspppcexp3; + volatile uint32_t apbnspppc0; + volatile uint32_t apbnspppc1; + volatile uint32_t reserved2[2]; + volatile uint32_t apbnspppcexp0; + volatile uint32_t apbnspppcexp1; + volatile uint32_t apbnspppcexp2; + volatile uint32_t apbnspppcexp3; +}; + +/* PPC interrupt position mask */ +#define APB_PPC0_INT_POS_MASK (1UL << 0) +#define APB_PPC1_INT_POS_MASK (1UL << 1) +/* Reseved bits 2:3 */ +#define APB_PPCEXP0_INT_POS_MASK (1UL << 4) +#define APB_PPCEXP1_INT_POS_MASK (1UL << 5) +#define APB_PPCEXP2_INT_POS_MASK (1UL << 6) +#define APB_PPCEXP3_INT_POS_MASK (1UL << 7) +/* Reseved bits 8:15 */ +#define AHB_PPC0_INT_POS_MASK (1UL << 16) +/* Reseved bits 17:19 */ +#define AHB_PPCEXP0_INT_POS_MASK (1UL << 20) +#define AHB_PPCEXP1_INT_POS_MASK (1UL << 21) +#define AHB_PPCEXP2_INT_POS_MASK (1UL << 22) +#define AHB_PPCEXP3_INT_POS_MASK (1UL << 23) +/* Reseved bits 24:31 */ + +/* ARM PPC state definitions */ +#define PPC_SSE200_INITIALIZED (1 << 0) + +/* Default peripheral states */ +#define SECURE_AS_DEFAULT_PERIPHERAL_STATE 1 +#define PRIVILEGE_ONLY_AS_DEFAULT_PERIPHERAL_STATE 1 + +void ppc_sse200_init(struct ppc_sse200_dev_t* dev, + enum ppc_sse200_name_t ppc_name) +{ + struct arm_spctrl_ppc_sse200_t* p_spctrl = + (struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base; + struct arm_nspctrl_ppc_sse200_t* p_nspctrl = + (struct arm_nspctrl_ppc_sse200_t*)dev->cfg->nspctrl_base; + + switch(ppc_name) { + case AHB_PPC0: + dev->data->p_ns_ppc = &p_spctrl->ahbnsppc0; + dev->data->p_sp_ppc = &p_spctrl->ahbspppc0; + dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppc0; + dev->data->int_bit_mask = AHB_PPC0_INT_POS_MASK; + break; + case AHB_PPC_EXP0: + dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp0; + dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp0; + dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp0; + dev->data->int_bit_mask = AHB_PPCEXP0_INT_POS_MASK; + break; + case AHB_PPC_EXP1: + dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp1; + dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp1; + dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp1; + dev->data->int_bit_mask = AHB_PPCEXP1_INT_POS_MASK; + break; + case AHB_PPC_EXP2: + dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp2; + dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp2; + dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp2; + dev->data->int_bit_mask = AHB_PPCEXP2_INT_POS_MASK; + break; + case AHB_PPC_EXP3: + dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp3; + dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp3; + dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp3; + dev->data->int_bit_mask = AHB_PPCEXP3_INT_POS_MASK; + break; + case APB_PPC0: + dev->data->p_ns_ppc = &p_spctrl->apbnsppc0; + dev->data->p_sp_ppc = &p_spctrl->apbspppc0; + dev->data->p_nsp_ppc = &p_nspctrl->apbnspppc0; + dev->data->int_bit_mask = APB_PPC0_INT_POS_MASK; + break; + case APB_PPC1: + dev->data->p_ns_ppc = &p_spctrl->apbnsppc1; + dev->data->p_sp_ppc = &p_spctrl->apbspppc1; + dev->data->p_nsp_ppc = &p_nspctrl->apbnspppc1; + dev->data->int_bit_mask = APB_PPC1_INT_POS_MASK; + break; + case APB_PPC_EXP0: + dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp0; + dev->data->p_sp_ppc = &p_spctrl->apbspppcexp0; + dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp0; + dev->data->int_bit_mask = APB_PPCEXP0_INT_POS_MASK; + break; + case APB_PPC_EXP1: + dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp1; + dev->data->p_sp_ppc = &p_spctrl->apbspppcexp1; + dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp1; + dev->data->int_bit_mask = APB_PPCEXP1_INT_POS_MASK; + break; + case APB_PPC_EXP2: + dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp2; + dev->data->p_sp_ppc = &p_spctrl->apbspppcexp2; + dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp2; + dev->data->int_bit_mask = APB_PPCEXP2_INT_POS_MASK; + break; + case APB_PPC_EXP3: + dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp3; + dev->data->p_sp_ppc = &p_spctrl->apbspppcexp3; + dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp3; + dev->data->int_bit_mask = APB_PPCEXP3_INT_POS_MASK; + break; + /* default: The default is not defined intentionally to force the + * compiler to check that all enumeration values are + * covered in the switch.*/ + } + + dev->data->state = PPC_SSE200_INITIALIZED; +} + +enum ppc_sse200_error_t ppc_sse200_config_peripheral( + struct ppc_sse200_dev_t* dev, + uint8_t periph, + enum ppc_sse200_sec_attr_t sec_attr, + enum ppc_sse200_priv_attr_t priv_attr) +{ + if(dev->data->state != PPC_SSE200_INITIALIZED) { + return PPC_SSE200_NOT_INIT; + } + + if(sec_attr == PPC_SSE200_SECURE_ONLY) { + /* Sets secure attribute */ + *(dev->data->p_ns_ppc) &= ~(1U << periph); + + /* Uses secure unprivileged access address (SPCTRL) to set privilege + * attribute */ + if(priv_attr == PPC_SSE200_PRIV_ONLY) { + *(dev->data->p_sp_ppc) &= ~(1U << periph); + } else { + *(dev->data->p_sp_ppc) |= (1U << periph); + } + } else { + /* Sets secure attribute */ + *(dev->data->p_ns_ppc) |= (1U << periph); + + /* Uses non-secure unprivileged access address (NSPCTRL) to set + * privilege attribute */ + if(priv_attr == PPC_SSE200_PRIV_ONLY) { + *(dev->data->p_nsp_ppc) &= ~(1U << periph); + } else { + *(dev->data->p_nsp_ppc) |= (1U << periph); + } + } + + return PPC_SSE200_ERR_NONE; +} + +uint32_t ppc_sse200_is_periph_secure(struct ppc_sse200_dev_t* dev, + uint8_t periph) +{ + if(dev->data->state != PPC_SSE200_INITIALIZED) { + return SECURE_AS_DEFAULT_PERIPHERAL_STATE; + } + + return ((*(dev->data->p_ns_ppc) & (1U << periph)) == 0); +} + +uint32_t ppc_sse200_is_periph_priv_only(struct ppc_sse200_dev_t* dev, + uint8_t periph) +{ + if(dev->data->state != PPC_SSE200_INITIALIZED) { + return PRIVILEGE_ONLY_AS_DEFAULT_PERIPHERAL_STATE; + } + + if ((*(dev->data->p_ns_ppc) & (1U << periph)) == 0) { + /* Returns secure unprivileged access address (SPCTRL) */ + return ((*(dev->data->p_sp_ppc) & (1U << periph)) == 0); + } else { + /* Returns non-secure unprivileged access address (NSPCTRL) */ + return ((*(dev->data->p_nsp_ppc) & (1U << periph)) == 0); + } +} + +enum ppc_sse200_error_t ppc_sse200_irq_enable(struct ppc_sse200_dev_t* dev) +{ + struct arm_spctrl_ppc_sse200_t* p_spctrl = + (struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base; + + if(dev->data->state != PPC_SSE200_INITIALIZED) { + return PPC_SSE200_NOT_INIT; + } + + p_spctrl->secppcinten |= dev->data->int_bit_mask; + + return PPC_SSE200_ERR_NONE; +} + +void ppc_sse200_irq_disable(struct ppc_sse200_dev_t* dev) +{ + struct arm_spctrl_ppc_sse200_t* p_spctrl = + (struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base; + + if(dev->data->state == PPC_SSE200_INITIALIZED) { + p_spctrl->secppcinten &= ~(dev->data->int_bit_mask); + } +} + +void ppc_sse200_clear_irq(struct ppc_sse200_dev_t* dev) +{ + struct arm_spctrl_ppc_sse200_t* p_spctrl = + (struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base; + + if(dev->data->state == PPC_SSE200_INITIALIZED) { + p_spctrl->secppcintclr = dev->data->int_bit_mask; + } +} + +uint32_t ppc_sse200_irq_state(struct ppc_sse200_dev_t* dev) +{ + struct arm_spctrl_ppc_sse200_t* p_spctrl = + (struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base; + + if(dev->data->state != PPC_SSE200_INITIALIZED) { + return 0; + } + + return ((p_spctrl->secppcintstat & dev->data->int_bit_mask) != 0); +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/ppc_sse200_drv.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/ppc_sse200_drv.h new file mode 100644 index 0000000000..de567d427b --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/ppc_sse200_drv.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file ppc_sse200_drv.h + * \brief Generic driver for ARM SEE 200 Peripheral Protection + * Controllers (PPC). + */ + +#ifndef __PPC_SSE_200_DRV_H__ +#define __PPC_SSE_200_DRV_H__ + +#include + +/* Secure Privilege Control Block aka SPCTRL */ +/* Non-Secure Privilege Control Block aka NSPCTRL */ + +/* ARM TrustZone PPC device configuration structure */ +struct ppc_sse200_dev_cfg_t { + uint32_t const spctrl_base; /*!< SPCTRL base address */ + uint32_t const nspctrl_base; /*!< NSPCTRL base address */ +}; + +/* ARM TrustZone PPC device data structure */ +struct ppc_sse200_dev_data_t { + volatile uint32_t* p_ns_ppc; /*!< Pointer to non-secure register */ + volatile uint32_t* p_sp_ppc; /*!< Pointer to secure unprivileged + register */ + volatile uint32_t* p_nsp_ppc; /*!< Pointer to non-secure unprivileged + register */ + uint32_t int_bit_mask; /*!< Interrupt bit mask */ + uint8_t state; /*!< Indicates if the PPC driver + is initialized */ + uint8_t reserved[3]; /*!< 32 bits alignment */ +}; + +/* ARM PPC device structure */ +struct ppc_sse200_dev_t { + const struct ppc_sse200_dev_cfg_t* const cfg; /*!< PPC configuration */ + struct ppc_sse200_dev_data_t* const data; /*!< PPC data */ +}; + +/* Security attribute used to configure the peripheral */ +enum ppc_sse200_sec_attr_t { + PPC_SSE200_SECURE_ONLY, /*! Secure access */ + PPC_SSE200_NONSECURE_ONLY, /*! Non-secure access */ +}; + +/* Privilege attribute used to configure the peripheral */ +enum ppc_sse200_priv_attr_t { + PPC_SSE200_PRIV_AND_NONPRIV, /*! Privilege and non-Privilege access */ + PPC_SSE200_PRIV_ONLY, /*! Privilege only access */ +}; + +/* ARM PPC error codes */ +enum ppc_sse200_error_t { + PPC_SSE200_ERR_NONE = 0, /*!< No error */ + PPC_SSE200_NOT_INIT, /*!< PPC not initialized */ +}; + +/* ARM PPC names */ +enum ppc_sse200_name_t { + AHB_PPC0 = 0, /*!< AHB PPC0 */ + AHB_PPC_EXP0, /*!< Expansion 0 AHB PPC */ + AHB_PPC_EXP1, /*!< Expansion 1 AHB PPC */ + AHB_PPC_EXP2, /*!< Expansion 2 AHB PPC */ + AHB_PPC_EXP3, /*!< Expansion 3 AHB PPC */ + APB_PPC0, /*!< APB PPC0 */ + APB_PPC1, /*!< APB PPC1 */ + APB_PPC_EXP0, /*!< Expansion 0 APB PPC */ + APB_PPC_EXP1, /*!< Expansion 1 APB PPC */ + APB_PPC_EXP2, /*!< Expansion 2 APB PPC */ + APB_PPC_EXP3 /*!< Expansion 3 APB PPC */ +}; + +/** + * \brief Initialize the PPC device. + * + * \param[in] dev PPC device \ref ppc_sse200_dev_t + * \param[in] ppc_name PPC name \ref ppc_sse200_name_t + * + * \note This function doesn't check if dev is NULL. + */ +void ppc_sse200_init(struct ppc_sse200_dev_t* dev, + enum ppc_sse200_name_t ppc_name); + +/** + * \brief Configures the PPC device. + * + * \param[in] dev PPC device \ref ppc_sse200_dev_t + * \param[in] periph Peripheral position in the PPC. + * \param[in] sec_attr Secure attribute value. + * \param[in] priv_attr Privilege attribute value. + * + * \return Returns error code as specified in \ref ppc_sse200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum ppc_sse200_error_t ppc_sse200_config_peripheral( + struct ppc_sse200_dev_t* dev, + uint8_t periph, + enum ppc_sse200_sec_attr_t sec_attr, + enum ppc_sse200_priv_attr_t priv_attr); +/** + * \brief Checks if the peripheral is configured as secure or non-secure. + * + * \param[in] dev PPC device \ref ppc_sse200_dev_t + * \param[in] periph Peripheral position in the PPC. + * + * \return Returns 1 for secure and 0 for non-secure. + * If the driver is not initalized the return value is 1 (secure) as + * it is the default system configuration. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t ppc_sse200_is_periph_secure(struct ppc_sse200_dev_t* dev, + uint8_t periph); + +/** + * \brief Checks if the peripheral is configured as Privilege only or + * Privilege and non-Privilege access mode. + * + * \param[in] dev PPC device \ref ppc_sse200_dev_t + * \param[in] periph Peripheral position in the PPC. + * + * \return Returns 1 for Privilege only configuration and 0 for Privilege and + * non-Privilege access. + * If the driver is not initalized the return of this function is + * 1 (Privilege only) as it is the default system configuration. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t ppc_sse200_is_periph_priv_only(struct ppc_sse200_dev_t* dev, + uint8_t periph); +/** + * \brief Enables PPC interrupt. + * + * \param[in] dev PPC device \ref ppc_sse200_dev_t + * + * \return Returns error code as specified in \ref ppc_sse200_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum ppc_sse200_error_t ppc_sse200_irq_enable(struct ppc_sse200_dev_t* dev); + +/** + * \brief Disables PPC interrupt. + * + * \param[in] dev PPC device \ref ppc_sse200_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void ppc_sse200_irq_disable(struct ppc_sse200_dev_t* dev); + +/** + * \brief Clears PPC interrupt. + * + * \param[in] dev PPC device \ref ppc_sse200_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void ppc_sse200_clear_irq(struct ppc_sse200_dev_t* dev); + +/** + * \brief Returns the PPC interrupt state. + * + * \param[in] dev PPC device \ref ppc_sse200_dev_t + * + * \return Returns 1 if the interrupt is active and otherwise 0. + * If the driver is not initalized the return of this function is + * 0 (not active) as it is the default system configuration. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t ppc_sse200_irq_state(struct ppc_sse200_dev_t* dev); + +#endif /* __PPC_SSE_200_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/qspi_ip6514e_drv.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/qspi_ip6514e_drv.c new file mode 100644 index 0000000000..c213d700ea --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/qspi_ip6514e_drv.c @@ -0,0 +1,757 @@ +/* + * Copyright (c) 2018-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +/* Use memcpy */ +#include + +#include "qspi_ip6514e_drv.h" + +/** Setter bit manipulation macro */ +#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX))) +/** Clearing bit manipulation macro */ +#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX))) +/** Getter bit manipulation macro */ +#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX)))) + +#define WORD_ALIGN_4B_MASK 0x3U /* Mask the first 2 bits */ +#define IS_ADDR_ALIGNED(ADDR) (((uint32_t)(ADDR) & (WORD_ALIGN_4B_MASK)) == 0U) + +#define BITS_PER_BYTE 8U +#define BITS_PER_WORD 32U + +#define CFG_READS true +#define CFG_WRITES false + +#define ARG_NOT_USED 0 +#define ARG_PTR_NOT_USED NULL + +#define DATA_REG_NUMBER 2U +#define DATA_REG_LOWER 0U +#define DATA_REG_UPPER 1U + +#define ERROR_VALUE 0xFFFFFFFFU + +/** + * \brief QSPI IP6514E register map structure + */ +struct _qspi_ip6514e_reg_map_t { + volatile uint32_t qspi_cfg; /*!< 0x00 (R/W) */ + volatile uint32_t device_read_inst; /*!< 0x04 (R/W) */ + volatile uint32_t device_write_inst; /*!< 0x08 (R/W) */ + volatile uint32_t hidden1[2]; + volatile uint32_t device_size; /*!< 0x14 (R/W) */ + volatile uint32_t hidden2[3]; + volatile uint32_t remap_addr; /*!< 0x24 (R/W) */ + volatile uint32_t hidden3[26]; + volatile uint32_t flash_cmd_ctrl; /*!< 0x90 (R/W) */ + volatile uint32_t flash_cmd_addr; /*!< 0x94 (R/W) */ + volatile uint32_t hidden4[2]; + volatile uint32_t flash_cmd_read_data_lower; /*!< 0xA0 (R/ ) */ + volatile uint32_t flash_cmd_read_data_upper; /*!< 0xA4 (R/ ) */ + volatile uint32_t flash_cmd_write_data_lower; /*!< 0xA8 (R/W) */ + volatile uint32_t flash_cmd_write_data_upper; /*!< 0xAC (R/W) */ + volatile uint32_t hidden5[2]; +}; + +/** QSPI Configuration register description (offset 0x00) */ +#define QSPI_CFG_ENABLE_POS 0U +#define QSPI_CFG_ENABLE_ADDR_REMAP_POS 16U +#define QSPI_CFG_BAUD_DIV_POS 19U + #define QSPI_CFG_BAUD_DIV_MIN 2U + #define QSPI_CFG_BAUD_DIV_MAX 32U + #define QSPI_CFG_BAUD_DIV_BITS 4U +#define QSPI_CFG_IDLE_POS 31U + +/** + * Device Read/Write Instruction registers description (offset 0x04 and 0x08). + * These values are the same for the Device Read Instruction register at offset + * 0x04 and the Device Write Instruction register at offset 0x08. + */ +#define DEVICE_READ_WRITE_INST_OPCODE_POS 0U +#define DEVICE_READ_INST_INST_TYPE_POS 8U /* Only applies to the Read + * register. */ +#define DEVICE_READ_WRITE_INST_ADDR_TYPE_POS 12U +#define DEVICE_READ_WRITE_INST_DATA_TYPE_POS 16U + #define DEVICE_READ_WRITE_INST_MODE_QSPI 2U + #define DEVICE_READ_WRITE_INST_MODE_DSPI 1U + #define DEVICE_READ_WRITE_INST_MODE_SPI 0U + #define DEVICE_READ_WRITE_INST_MODE_BITS 2U +#define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_POS 24U + #define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_BITS 5U + #define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_MAX 31U + +/** Device Size Configuration register description (offset 0x14) */ +#define DEVICE_SIZE_ADDR_BYTES_POS 0U + #define DEVICE_SIZE_ADDR_BYTES_MIN 1U + #define DEVICE_SIZE_ADDR_BYTES_MAX 16U + #define DEVICE_SIZE_ADDR_BYTES_BITS 4U +#define DEVICE_SIZE_PAGE_BYTES_POS 4U + #define DEVICE_SIZE_PAGE_BYTES_MAX 4095U + #define DEVICE_SIZE_PAGE_BYTES_BITS 12U + +/** Flash Command Control register description (offset 0x90) */ +#define FLASH_CMD_CTRL_EXECUTE_POS 0U +#define FLASH_CMD_CTRL_BUSY_POS 1U +#define FLASH_CMD_CTRL_DUMMY_CYCLES_POS 7U + #define FLASH_CMD_CTRL_DUMMY_CYCLES_MAX 31U + #define FLASH_CMD_CTRL_DUMMY_CYCLES_BITS 5U +#define FLASH_CMD_CTRL_WRITE_BYTES_POS 12U + #define FLASH_CMD_CTRL_WRITE_BYTES_MAX 8U + #define FLASH_CMD_CTRL_WRITE_BYTES_BITS 3U +#define FLASH_CMD_CTRL_WRITE_ENABLE_POS 15U +#define FLASH_CMD_CTRL_ADDR_BYTES_POS 16U + #define FLASH_CMD_CTRL_ADDR_BYTES_MAX 4U + #define FLASH_CMD_CTRL_ADDR_BYTES_BITS 2U +#define FLASH_CMD_CTRL_ADDR_ENABLE_POS 19U +#define FLASH_CMD_CTRL_READ_BYTES_POS 20U + #define FLASH_CMD_CTRL_READ_BYTES_MAX 8U + #define FLASH_CMD_CTRL_READ_BYTES_BITS 3U +#define FLASH_CMD_CTRL_READ_ENABLE_POS 23U +#define FLASH_CMD_CTRL_OPCODE_POS 24U + +/** Default register values of the QSPI Flash controller */ +#define QSPI_CFG_REG_RESET_VALUE (0x80780081U) +#define DEVICE_READ_INSTR_REG_RESET_VALUE (0x00000003U) +#define DEVICE_WRITE_INSTR_REG_RESET_VALUE (0x00000002U) +#define DEVICE_SIZE_CFG_REG_RESET_VALUE (0x00101002U) +#define REMAP_ADDR_REG_RESET_VALUE (0x00000000U) +#define FLASH_CMD_CONTROL_REG_RESET_VALUE (0x00000000U) +#define FLASH_CMD_ADDRESS_REG_RESET_VALUE (0x00000000U) +#define FLASH_CMD_WRITE_DATA_REG_RESET_VALUE (0x00000000U) + +/** + * \brief Change specific bits in a 32 bits word. + * + * \param[in,out] word Pointer of the word to change + * \param[in] bits bits_length bits to put at bits_pos in the word + * pointed + * \param[in] bits_length Number of bits to change + * \param[in] bits_pos Position of the bits to change + * + * \note This function will do nothing if the parameters given are incorret: + * * word is NULL + * * bits_length + bits_pos > 32 + * * bits_length is 0 + */ +static void change_bits_in_word(volatile uint32_t *word, + uint32_t bits, + uint32_t bits_length, + uint32_t bits_pos) +{ + uint32_t mask; + + if ((word == NULL) || + ((bits_length + bits_pos) > BITS_PER_WORD) || + (bits_length == 0U)) { + /* Silently fail */ + return; + } + + /* Change all the bits */ + if (bits_length == BITS_PER_WORD) { + *word = bits; + return; + } + + mask = ((1U << bits_length) - 1); + /* + * We change the bits in three steps: + * - clear bits_length bits with zeroes at bits_pos in the word + * - mask bits in case it contains more than bits_length bits + * - set the new bits in the cleared word + * Because the data pointed by word is only read once, the data will still + * be coherent after an interruption that changes it. + */ + *word = ((*word & ~(mask << bits_pos)) | ((bits & mask) << bits_pos)); +} + +/** + * \brief Configure reads or writes commands for direct operations. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * \param[in] opcode Read/write opcode that will be used for every + * direct read/write + * \param[in] dummy_cycles Number of dummy cycles to wait before triggering + * the command, this value must be between 0 and 31 + * (both included) + * \param[in] is_reads_cfg true to configure direct reads, false to configure + * direct writes + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note The QSPI controller should be idle before calling this function. + */ +static enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads_writes( + struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + uint32_t dummy_cycles, + bool is_reads_cfg) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + /* + * Select the good register address if we want to configure reads or writes. + */ + volatile uint32_t *device_read_write_inst_reg = is_reads_cfg ? + &(reg_map->device_read_inst) : + &(reg_map->device_write_inst); + uint32_t device_read_write_inst_reg_copy = *device_read_write_inst_reg; + + /* + * Wait for the Serial Interface and QSPI pipeline to be IDLE when + * all low level synchronization has been done. + */ + while(!qspi_ip6514e_is_idle(dev)); + + if (dummy_cycles > DEVICE_READ_WRITE_INST_DUMMY_CYCLES_MAX) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + change_bits_in_word(&device_read_write_inst_reg_copy, + (uint32_t)opcode, + BITS_PER_BYTE, + DEVICE_READ_WRITE_INST_OPCODE_POS); + change_bits_in_word(&device_read_write_inst_reg_copy, + dummy_cycles, + DEVICE_READ_WRITE_INST_DUMMY_CYCLES_BITS, + DEVICE_READ_WRITE_INST_DUMMY_CYCLES_POS); + + *device_read_write_inst_reg = device_read_write_inst_reg_copy; + + return QSPI_IP6514E_ERR_NONE; +} + +/** + * \brief Given the public SPI mode enumeration, returns the private value it + * maps to in the register field. + * + * \param[in] spi_mode Read/write opcode that will be used for every direct + * read/write + * + * \return Return the correct DEVICE_READ_WRITE_INST_MODE value. + */ +static uint32_t spi_mode_field_value(enum qspi_ip6514e_spi_mode_t spi_mode) +{ + switch (spi_mode) { + case QSPI_IP6514E_SPI_MODE: + return DEVICE_READ_WRITE_INST_MODE_SPI; + case QSPI_IP6514E_DSPI_MODE: + return DEVICE_READ_WRITE_INST_MODE_DSPI; + case QSPI_IP6514E_QSPI_MODE: + return DEVICE_READ_WRITE_INST_MODE_QSPI; + default: + return ERROR_VALUE; + } +} + +bool qspi_ip6514e_is_idle(struct qspi_ip6514e_dev_t* dev) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + + return GET_BIT(reg_map->qspi_cfg, QSPI_CFG_IDLE_POS); +} + +bool qspi_ip6514e_is_enabled(struct qspi_ip6514e_dev_t* dev) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + + return GET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS); +} + +void qspi_ip6514e_disable(struct qspi_ip6514e_dev_t* dev) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + + CLR_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS); +} + +void qspi_ip6514e_enable(struct qspi_ip6514e_dev_t* dev) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + + SET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS); +} + +enum qspi_ip6514e_error_t qspi_ip6514e_set_baud_rate_div( + struct qspi_ip6514e_dev_t* dev, + uint32_t div) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + + /* + * Wait for the Serial Interface and QSPI pipeline to be IDLE when + * all low level synchronization has been done. + */ + while(!qspi_ip6514e_is_idle(dev)); + + /* div should be an even number. */ + if (((div & 1U) == 1) || + (div < QSPI_CFG_BAUD_DIV_MIN) || + (div > QSPI_CFG_BAUD_DIV_MAX)) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + /* + * The div value (between 2 and 32) needs to be stored in the register on a + * 4 bits field. + */ + change_bits_in_word(&(reg_map->qspi_cfg), + (div / 2) - 1, + QSPI_CFG_BAUD_DIV_BITS, + QSPI_CFG_BAUD_DIV_POS); + + return QSPI_IP6514E_ERR_NONE; +} + +enum qspi_ip6514e_error_t qspi_ip6514e_set_spi_mode( + struct qspi_ip6514e_dev_t* dev, + enum qspi_ip6514e_spi_mode_t inst_type, + enum qspi_ip6514e_spi_mode_t addr_type, + enum qspi_ip6514e_spi_mode_t data_type) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + uint32_t inst_spi_mode, addr_spi_mode, data_spi_mode; + /* + * A local copy of the Device Read Instruction and Device Write Instruction + * registers is used to limit APB accesses. + */ + uint32_t device_read_inst_cpy = reg_map->device_read_inst; + uint32_t device_write_inst_cpy = reg_map->device_write_inst; + + /* + * Wait for the Serial Interface and QSPI pipeline to be IDLE when + * all low level synchronization has been done. + */ + while(!qspi_ip6514e_is_idle(dev)); + + /* + * First check that the instruction mode is not SPI. If that is the case, + * the address and data mode register fields become DO NOT CARE. + */ + inst_spi_mode = spi_mode_field_value(inst_type); + if (inst_spi_mode == ERROR_VALUE) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + if (inst_type != QSPI_IP6514E_SPI_MODE) { + change_bits_in_word(&(reg_map->device_read_inst), + inst_spi_mode, + DEVICE_READ_WRITE_INST_MODE_BITS, + DEVICE_READ_INST_INST_TYPE_POS); + return QSPI_IP6514E_ERR_NONE; + } + + /* Now check and set address and data modes. */ + addr_spi_mode = spi_mode_field_value(addr_type); + data_spi_mode = spi_mode_field_value(data_type); + if ((addr_spi_mode == ERROR_VALUE) || (data_spi_mode == ERROR_VALUE)) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + /* Change the Device Read Instruction register. */ + change_bits_in_word(&device_read_inst_cpy, + inst_spi_mode, + DEVICE_READ_WRITE_INST_MODE_BITS, + DEVICE_READ_INST_INST_TYPE_POS); + change_bits_in_word(&device_read_inst_cpy, + addr_spi_mode, + DEVICE_READ_WRITE_INST_MODE_BITS, + DEVICE_READ_WRITE_INST_ADDR_TYPE_POS); + change_bits_in_word(&device_read_inst_cpy, + data_spi_mode, + DEVICE_READ_WRITE_INST_MODE_BITS, + DEVICE_READ_WRITE_INST_DATA_TYPE_POS); + + /* Change the Device Write Instruction register. */ + change_bits_in_word(&device_write_inst_cpy, + addr_spi_mode, + DEVICE_READ_WRITE_INST_MODE_BITS, + DEVICE_READ_WRITE_INST_ADDR_TYPE_POS); + change_bits_in_word(&device_write_inst_cpy, + data_spi_mode, + DEVICE_READ_WRITE_INST_MODE_BITS, + DEVICE_READ_WRITE_INST_DATA_TYPE_POS); + + /* Save the changes. */ + reg_map->device_read_inst = device_read_inst_cpy; + reg_map->device_write_inst = device_write_inst_cpy; + + return QSPI_IP6514E_ERR_NONE; +} + +enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads(struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + uint32_t dummy_cycles) +{ + return qspi_ip6514e_cfg_reads_writes(dev, opcode, dummy_cycles, CFG_READS); +} + +enum qspi_ip6514e_error_t qspi_ip6514e_cfg_writes( + struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + uint32_t dummy_cycles) +{ + return qspi_ip6514e_cfg_reads_writes(dev, opcode, dummy_cycles, CFG_WRITES); +} + +enum qspi_ip6514e_error_t qspi_ip6514e_cfg_page_size( + struct qspi_ip6514e_dev_t* dev, + uint32_t page_size) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + + /* + * Wait for the Serial Interface and QSPI pipeline to be IDLE when + * all low level synchronization has been done. + */ + while(!qspi_ip6514e_is_idle(dev)); + + if (page_size > DEVICE_SIZE_PAGE_BYTES_MAX) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + change_bits_in_word(&(reg_map->device_size), + page_size, + DEVICE_SIZE_PAGE_BYTES_BITS, + DEVICE_SIZE_PAGE_BYTES_POS); + + return QSPI_IP6514E_ERR_NONE; +} + +enum qspi_ip6514e_error_t qspi_ip6514e_cfg_addr_bytes( + struct qspi_ip6514e_dev_t* dev, + uint32_t bytes_number) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + + /* + * Wait for the Serial Interface and QSPI pipeline to be IDLE when + * all low level synchronization has been done. + */ + while(!qspi_ip6514e_is_idle(dev)); + + if (bytes_number < DEVICE_SIZE_ADDR_BYTES_MIN || + bytes_number > DEVICE_SIZE_ADDR_BYTES_MAX) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + change_bits_in_word(&(reg_map->device_size), + bytes_number - 1, + DEVICE_SIZE_ADDR_BYTES_BITS, + DEVICE_SIZE_ADDR_BYTES_POS); + + + return QSPI_IP6514E_ERR_NONE; +} + +void qspi_ip6514e_remap_addr(struct qspi_ip6514e_dev_t* dev, uint32_t offset) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + /* Save the enable state to restore it after. */ + bool is_enabled = qspi_ip6514e_is_enabled(dev); + + if (is_enabled) { + qspi_ip6514e_disable(dev); + } + + reg_map->remap_addr = offset; + SET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_ADDR_REMAP_POS); + + if (is_enabled) { + qspi_ip6514e_enable(dev); + } +} + +void qspi_ip6514e_disable_remap(struct qspi_ip6514e_dev_t* dev) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + /* Save the enable state to restore it after. */ + bool is_enabled = qspi_ip6514e_is_enabled(dev); + + if (is_enabled) { + qspi_ip6514e_disable(dev); + } + + CLR_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_ADDR_REMAP_POS); + + if (is_enabled) { + qspi_ip6514e_enable(dev); + } +} + +void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + + /* Restore the default value of the QSPI Configuration register. */ + reg_map->qspi_cfg = QSPI_CFG_REG_RESET_VALUE; + + /* Restore the default value of the Device R/W Instruction registers. */ + reg_map->device_read_inst = DEVICE_READ_INSTR_REG_RESET_VALUE; + reg_map->device_write_inst = DEVICE_WRITE_INSTR_REG_RESET_VALUE; + + /* Restore the default value of the Device Size Configuration register. */ + reg_map->device_size = DEVICE_SIZE_CFG_REG_RESET_VALUE; + + /* Restore the default value of the Remap Address register. */ + reg_map->remap_addr = REMAP_ADDR_REG_RESET_VALUE; + + /* Restore the default value of the Flash Command Control register. */ + reg_map->flash_cmd_ctrl = FLASH_CMD_CONTROL_REG_RESET_VALUE; + /* Restore the default value of the Flash Command Address register. */ + reg_map->flash_cmd_addr = FLASH_CMD_ADDRESS_REG_RESET_VALUE; + + /* Restore the default value of the Flash Command Write Data registers. */ + reg_map->flash_cmd_write_data_lower = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE; + reg_map->flash_cmd_write_data_upper = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE; + + /* + * This function does not affect the Flash Command Read Data registers + * which are completely Read-Only. + */ +} + +enum qspi_ip6514e_error_t qspi_ip6514e_send_cmd(struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + void *read_data, + uint32_t read_len, + const void *write_data, + uint32_t write_len, + uint32_t addr, + uint32_t addr_bytes_number, + uint32_t dummy_cycles) +{ + struct _qspi_ip6514e_reg_map_t *reg_map = + (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base; + /* To limit APB accesses, we set this reg up locally before */ + uint32_t flash_cmd_ctrl = 0U; + bool read_requested = ((read_data != NULL) && (read_len != 0)); + bool write_requested = ((write_data != NULL) && (write_len != 0)); + bool addr_requested = (addr_bytes_number != 0); + /* + * To prevent unaligned and byte or halfbyte accesses to the APB registers, + * a word aligned buffer is used to temporary transfer the data before doing + * word accesses on these registers from that buffer. + */ + uint32_t data_regs[DATA_REG_NUMBER] = {0}; + + if (read_len > FLASH_CMD_CTRL_READ_BYTES_MAX) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + if (write_len > FLASH_CMD_CTRL_WRITE_BYTES_MAX) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + if (addr_bytes_number > FLASH_CMD_CTRL_ADDR_BYTES_MAX) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + if (dummy_cycles > FLASH_CMD_CTRL_DUMMY_CYCLES_MAX) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + if (read_requested && write_requested) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + change_bits_in_word(&flash_cmd_ctrl, + (uint32_t)opcode, + BITS_PER_BYTE, + FLASH_CMD_CTRL_OPCODE_POS); + + /* Enable read if requested */ + if (read_requested) { + SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_READ_ENABLE_POS); + change_bits_in_word(&flash_cmd_ctrl, + read_len - 1, + FLASH_CMD_CTRL_READ_BYTES_BITS, + FLASH_CMD_CTRL_READ_BYTES_POS); + } + + /* Enable write if requested */ + if (write_requested) { + SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_WRITE_ENABLE_POS); + change_bits_in_word(&flash_cmd_ctrl, + write_len - 1, + FLASH_CMD_CTRL_WRITE_BYTES_BITS, + FLASH_CMD_CTRL_WRITE_BYTES_POS); + + if (IS_ADDR_ALIGNED(write_data) && IS_ADDR_ALIGNED(write_len)) { + /* + * Optimised case when write_data is word aligned and write_len is + * 4 or 8. + */ + reg_map->flash_cmd_write_data_lower = *(uint32_t *)write_data; + if (write_len == FLASH_CMD_CTRL_WRITE_BYTES_MAX) { + reg_map->flash_cmd_write_data_upper = + *((uint32_t *)write_data + 1); + } + } else { + /* + * data_regs is used as a buffer to only do unaligned access on the + * AHB bus and word aligned accesses to the APB registers. + */ + memcpy((void *)data_regs, write_data, write_len); + /* + * Only write_len bytes will be written even if both data registers + * are written. + */ + reg_map->flash_cmd_write_data_lower = data_regs[DATA_REG_LOWER]; + reg_map->flash_cmd_write_data_upper = data_regs[DATA_REG_UPPER]; + } + } + + /* Enable the address if requested */ + if (addr_requested) { + SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_ADDR_ENABLE_POS); + reg_map->flash_cmd_addr = addr; + change_bits_in_word(&flash_cmd_ctrl, + addr_bytes_number - 1, + FLASH_CMD_CTRL_ADDR_BYTES_BITS, + FLASH_CMD_CTRL_ADDR_BYTES_POS); + } + + /* Put dummy cycles number */ + change_bits_in_word(&flash_cmd_ctrl, + dummy_cycles, + FLASH_CMD_CTRL_DUMMY_CYCLES_BITS, + FLASH_CMD_CTRL_DUMMY_CYCLES_POS); + + /* Copy the Flash Command Control register and execute the command */ + reg_map->flash_cmd_ctrl = flash_cmd_ctrl; + SET_BIT(reg_map->flash_cmd_ctrl, FLASH_CMD_CTRL_EXECUTE_POS); + + /* Wait for termination */ + while (GET_BIT(reg_map->flash_cmd_ctrl, FLASH_CMD_CTRL_BUSY_POS)); + + /* + * Recolt the read data if it was requested. read_len validity has already + * been verified at this point. + */ + if (read_requested) { + if (IS_ADDR_ALIGNED(read_data) && IS_ADDR_ALIGNED(read_len)) { + /* + * Optimised case when read_data is word aligned and read_len is + * 4 or 8. + */ + *(uint32_t *)read_data = reg_map->flash_cmd_read_data_lower; + if (read_len == FLASH_CMD_CTRL_READ_BYTES_MAX) { + *((uint32_t *)read_data + 1) = + reg_map->flash_cmd_read_data_upper; + } + } else { + /* + * Only read_len bytes have been written even if both data registers + * are written. + */ + data_regs[DATA_REG_LOWER] = reg_map->flash_cmd_read_data_lower; + data_regs[DATA_REG_UPPER] = reg_map->flash_cmd_read_data_upper; + /* + * data_regs is used as a buffer to only do unaligned access on the + * AHB bus and word aligned accesses to the APB registers. + */ + memcpy(read_data, (void *)data_regs, read_len); + } + } + + return QSPI_IP6514E_ERR_NONE; +} + +void qspi_ip6514e_send_simple_cmd(struct qspi_ip6514e_dev_t* dev, + uint8_t opcode) +{ + /* + * No read/write data, no address, no dummy cycles. + * Given the arguments, this function can not fail. + */ + (void)qspi_ip6514e_send_cmd(dev, + opcode, + ARG_PTR_NOT_USED, + ARG_NOT_USED, + ARG_PTR_NOT_USED, + ARG_NOT_USED, + ARG_NOT_USED, + ARG_NOT_USED, + 0); +} + +enum qspi_ip6514e_error_t qspi_ip6514e_send_read_cmd( + struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + void *read_data, + uint32_t read_len, + uint32_t addr, + uint32_t addr_bytes_number, + uint32_t dummy_cycles) +{ + /* Read arguments are expected */ + if (read_data == ARG_PTR_NOT_USED || read_len == ARG_NOT_USED) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + /* No write data */ + return qspi_ip6514e_send_cmd(dev, + opcode, + read_data, + read_len, + ARG_PTR_NOT_USED, + ARG_NOT_USED, + addr, + addr_bytes_number, + dummy_cycles); +} + +enum qspi_ip6514e_error_t qspi_ip6514e_send_write_cmd( + struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + const void *write_data, + uint32_t write_len, + uint32_t addr, + uint32_t addr_bytes_number, + uint32_t dummy_cycles) +{ + /* Write arguments are expected */ + if (write_data == ARG_PTR_NOT_USED || write_len == ARG_NOT_USED) { + return QSPI_IP6514E_ERR_WRONG_ARGUMENT; + } + + /* No read data, no dummy cycles */ + return qspi_ip6514e_send_cmd(dev, + opcode, + ARG_PTR_NOT_USED, + ARG_NOT_USED, + write_data, + write_len, + addr, + addr_bytes_number, + dummy_cycles); +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/qspi_ip6514e_drv.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/qspi_ip6514e_drv.h new file mode 100644 index 0000000000..e5d4adeb7e --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/device/drivers/qspi_ip6514e_drv.h @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2018-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file qspi_ip6514e_drv.h + * \brief Driver for Cadence QSPI Flash Controller IP. + * There are two ways to communicate with the flash memory device: + * - issue AHB requests for direct read and writes in the Flash memory + * mapped address zone. The commands used for those can be configured + * by the driver + * - send a command to the device to access his internal registers and + * do other operations like erasing a sector + * At reset, the QSPI controller will work in a default mode which will + * allow to do basic commands. It should be configured with the + * flash memory device specifications for optimal use for commands and + * direct reads/writes. Here is an example of configuration: + * - send command to activate QSPI mode on the flash memory device + * - send command to change dummy cycles on the flash memory device + * - check if any operation is ungoing + * - disable the QSPI controller + * - change the baud rate divisor + * - activate the QSPI mode on the controller + * - change the dummy cycles number and opcode for reads/writes + * - change the number of bytes per page + * - change the number of address bytes + * - activate the QSPI controller + * + * Warning: none of the functions declared here check if the dev + * argument points to NULL. + */ + +#ifndef __QSPI_IP6514E_DRV_H__ +#define __QSPI_IP6514E_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Cadence QSPI IP6514E error enumeration types + */ +enum qspi_ip6514e_error_t { + QSPI_IP6514E_ERR_NONE, + QSPI_IP6514E_ERR_WRONG_ARGUMENT, + QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED, + QSPI_IP6514E_ERR_READ_IN_PROGRESS, + QSPI_IP6514E_ERR_WRITE_IN_PROGRESS, + /* Any new error should be added to the enumeration type error of + * the corresponding Flash device library as well. + */ +}; + +/** + * \brief Cadence QSPI IP6514E SPI modes + */ +enum qspi_ip6514e_spi_mode_t { + QSPI_IP6514E_SPI_MODE, + /*!< Use 1 line for Instruction, Address and Data */ + QSPI_IP6514E_DSPI_MODE, + /*!< Use 2 lines for Instruction, Address and Data */ + QSPI_IP6514E_QSPI_MODE, + /*!< Use 4 lines for Instruction, Address and Data */ +}; + +/** + * \brief Cadence QSPI IP6514E device configuration structure + */ +struct qspi_ip6514e_dev_cfg_t { + const uint32_t base; /*!< QSPI IP6514E base address */ + /* + * If not all the AHB wires are connected to the QSPI Flash Controller the + * driver can still access all of the Flash memory. The bits of this value + * should be put to 1 for every wire that is connected. Set it to + * 0xFFFFFFFFU if all AHB address wires are connected to the + * QSPI Flash Controller. + */ + uint32_t addr_mask; +}; + +/** + * \brief Cadence QSPI IP6514E device structure + */ +struct qspi_ip6514e_dev_t { + const struct qspi_ip6514e_dev_cfg_t* const cfg; + /*!< QSPI IP6514E configuration */ +}; + +/** + * \brief Check if the controller is idle. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * + * \return true if the controller is idle, false otherwise. + */ +bool qspi_ip6514e_is_idle(struct qspi_ip6514e_dev_t* dev); + +/** + * \brief Check if the controller is enabled. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * + * \return true if the controller is enabled, false otherwise. + */ +bool qspi_ip6514e_is_enabled(struct qspi_ip6514e_dev_t* dev); + +/** + * \brief Disable the QSPI controller. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + */ +void qspi_ip6514e_disable(struct qspi_ip6514e_dev_t* dev); + +/** + * \brief Enable the QSPI controller. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + */ +void qspi_ip6514e_enable(struct qspi_ip6514e_dev_t* dev); + +/** + * \brief Change the baud rate divisor. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * \param[in] div Baud rate divisor value. It can only be an even number + * between 2 and 32 (both included). + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note The QSPI frequency is calculated dividing the QSPI controller clock by + * this divisor. Please check Flash memory device specifications to know + * the maximal frequency that can be used. + * \note The QSPI controller should be disabled before calling this function. + */ +enum qspi_ip6514e_error_t qspi_ip6514e_set_baud_rate_div( + struct qspi_ip6514e_dev_t* dev, + uint32_t div); + +/** + * \brief Set SPI mode for instruction, address and data. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * \param[in] inst_type SPI mode to use for the instruction part of the command + * \param[in] addr_type SPI mode to use for the address part of the command + * \param[in] data_type SPI mode to use for the data part of the command + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note The QSPI controller should be idle before calling this function. + * \note Changing this setting will affect commands and direct operations. + */ +enum qspi_ip6514e_error_t qspi_ip6514e_set_spi_mode( + struct qspi_ip6514e_dev_t* dev, + enum qspi_ip6514e_spi_mode_t inst_type, + enum qspi_ip6514e_spi_mode_t addr_type, + enum qspi_ip6514e_spi_mode_t data_type); + +/** + * \brief Configure read commands for direct reads. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * \param[in] opcode Read opcode that will be used for every direct read + * \param[in] dummy_cycles Number of dummy cycles to wait before triggering the + * command, this value must be between 0 and 31 + * (both included) + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note The QSPI controller should be idle before calling this function. + */ +enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads(struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + uint32_t dummy_cycles); + +/** + * \brief Configure write commands for direct writes. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * \param[in] opcode Write opcode that will be used for every direct write + * \param[in] dummy_cycles Number of dummy cycles to wait before triggering the + * command, this value must be between 0 and 31 + * (both included) + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note The QSPI controller should be idle before calling this function. + */ +enum qspi_ip6514e_error_t qspi_ip6514e_cfg_writes( + struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + uint32_t dummy_cycles); + +/** + * \brief Change the number of bytes per device page. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * \param[in] page_size Number of bytes per device page, must be between 0 + * and 4095 (both included) + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note The QSPI controller should be idle before calling this function. + * \note This function will affect direct reads/writes. + */ +enum qspi_ip6514e_error_t qspi_ip6514e_cfg_page_size( + struct qspi_ip6514e_dev_t* dev, + uint32_t page_size); + +/** + * \brief Change the number of device address bytes. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * \param[in] bytes_number Number of device address bytes, must be between 1 + * and 16 (both included) + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note The QSPI controller should be idle before calling this function. + * \note This function will affect direct reads/writes. + */ +enum qspi_ip6514e_error_t qspi_ip6514e_cfg_addr_bytes( + struct qspi_ip6514e_dev_t* dev, + uint32_t bytes_number); + +/** + * \brief Remap the incoming AHB address with an offset for direct accesses. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * \param[in] offset Offset that will be added to the incoming AHB address to + * access the Flash memory + * + * \note This function will only affect direct reads/writes. + * \note This function does not check if the resulting address is out of memory + * bounds. + */ +void qspi_ip6514e_remap_addr(struct qspi_ip6514e_dev_t* dev, uint32_t offset); + +/** + * \brief Disable AHB address remapping for direct accesses. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * + * \note This function will disable the controller if it is not already + * disabled and enable it again (if it was). + * \note This function will only affect direct reads/writes. + */ +void qspi_ip6514e_disable_remap(struct qspi_ip6514e_dev_t* dev); + +/** + * \brief Restore the default value of the QSPI controller registers. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * + * \note The QSPI controller should be disabled before calling this function. + */ +void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev); + +/** + * \brief Send a command to the flash memory device using the Software Triggered + * Instruction Generator (STIG). + * + * \param[in] dev QSPI IP6514E device struct + * \ref qspi_ip6514e_dev_t + * \param[in] opcode Opcode for the command. + * \param[out] read_data Pointer to a memory zone where the read_len + * bytes read will be written to. If no data is to + * be read for the command, + * this argument should be NULL. + * \param[in] read_len Number of bytes to read for the command. If + * no bytes are to be read, use 0 for argument + * otherwise between 1 and 8 bytes (both + * included) can be read. + * \param[in] write_data Pointer to a memory zone where are + * located the write_len bytes to write for + * this command. If no bytes are to be written, + * use NULL as argument. + * \param[in] write_len Number of bytes to write for the command. If + * no bytes are to be written, use 0 for + * argument otherwise between 1 and 8 bytes + * (both included) can be written. + * \param[in] addr Address used for the command + * \param[in] addr_bytes_number Number of address bytes for this command. + * If an address is not needed for the command, + * use 0 for argument, otherwise between 1 and + * 4 bytes (both included) can be used. + * \param[in] dummy_cycles Number of dummy cycles required for the + * command, between 0 and 31 (both included). + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note Check the flash memory device specifications for the possible opcodes + * that can be used and the other informations needed for this function. + * \note The SPI mode used for this command is the one set with the + * \ref qspi_ip6514e_activate_qspi_mode function or the default one. + */ +enum qspi_ip6514e_error_t qspi_ip6514e_send_cmd(struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + void *read_data, + uint32_t read_len, + const void *write_data, + uint32_t write_len, + uint32_t addr, + uint32_t addr_bytes_number, + uint32_t dummy_cycles); + +/** + * \brief Send a simple command to the flash memory device using the Software + * Triggered Instruction Generator (STIG) with no data arguments. + * This command can be used for example to send the WRITE ENABLE command. + * + * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t + * \param[in] opcode Opcode for the command. + * + * \note Check the flash memory device specifications for the possible opcodes + * that can be used and the other informations needed for this function. + * \note The SPI mode used for this command is the one set with the + * \ref qspi_ip6514e_activate_qspi_mode function or the default one. + */ +void qspi_ip6514e_send_simple_cmd(struct qspi_ip6514e_dev_t* dev, + uint8_t opcode); + +/** + * \brief Send a read command to the flash memory device using the Software + * Triggered Instruction Generator (STIG). This command can be used to + * read Flash memory data or registers. + * + * \param[in] dev QSPI IP6514E device struct + * \ref qspi_ip6514e_dev_t + * \param[in] opcode Opcode for the command. + * \param[out] read_data Pointer to a memory zone where the + * read_len bytes read will be written to. + * \param[in] read_len Number of bytes to read for the command. + * Between 1 and 8 bytes (both included) can be + * read. + * \param[in] addr Address used for the command + * \param[in] addr_bytes_number Number of address bytes for this command. + * If an address is not needed for the command, + * use 0 for argument, otherwise between 1 and + * 4 bytes (both included) can be used. + * \param[in] dummy_cycles Number of dummy cycles required for the + * command, between 0 and 31 (both included). + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note Check the flash memory device specifications for the possible opcodes + * that can be used and the other informations needed for this function. + * \note The SPI mode used for this command is the one set with the + * \ref qspi_ip6514e_activate_qspi_mode function or the default one. + */ +enum qspi_ip6514e_error_t qspi_ip6514e_send_read_cmd( + struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + void *read_data, + uint32_t read_len, + uint32_t addr, + uint32_t addr_bytes_number, + uint32_t dummy_cycles); + +/** + * \brief Send a write command to the flash memory device using the Software + * Triggered Instruction Generator (STIG). This command can be used to + * write Flash memory or registers. + * + * \param[in] dev QSPI IP6514E device struct + * \ref qspi_ip6514e_dev_t + * \param[in] opcode Opcode for the command. + * \param[in] write_data Pointer to a memory zone where are + * located the write_len bytes to write for + * this command. + * \param[in] write_len Number of bytes to write for the command. + * Between 1 and 8 bytes (both included) can be + * written. + * \param[in] addr Address used for the command + * \param[in] addr_bytes_number Number of address bytes for this command. + * If an address is not needed for the command, + * use 0 for argument, otherwise between 1 and + * 4 bytes (both included) can be used. + * \param[in] dummy_cycles Number of dummy cycles required for the + * command, between 0 and 31 (both included). + * + * \return Returns error code as specified in \ref qspi_ip6514e_error_t + * + * \note Check the flash memory device specifications for the possible opcodes + * that can be used and the other informations needed for this function. + * \note The SPI mode used for this command is the one set with the + * \ref qspi_ip6514e_activate_qspi_mode function or the default one. + */ +enum qspi_ip6514e_error_t qspi_ip6514e_send_write_cmd( + struct qspi_ip6514e_dev_t* dev, + uint8_t opcode, + const void *write_data, + uint32_t write_len, + uint32_t addr, + uint32_t addr_bytes_number, + uint32_t dummy_cycles); + +#ifdef __cplusplus +} +#endif + +#endif /* __QSPI_IP6514E_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/flash_api.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/flash_api.c new file mode 100644 index 0000000000..3293db6523 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/flash_api.c @@ -0,0 +1,132 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device.h" +#include "flash_layout.h" +#include "flash_api.h" + +#if DEVICE_FLASH + +#define FLASH_DEV MT25QL_DEV_NS + +int32_t flash_init(flash_t *obj) +{ + (void)(obj); + enum mt25ql_error_t err = MT25QL_ERR_NONE; + + qspi_ip6514e_enable(FLASH_DEV.controller); + + /* Configure QSPI Flash controller to operate in single SPI mode and + * to use fast Flash commands */ + err = mt25ql_config_mode(&FLASH_DEV, MT25QL_FUNC_STATE_FAST); + if (err != MT25QL_ERR_NONE) { + return -1; + } + + return 0; +} + +int32_t flash_free(flash_t *obj) +{ + (void)(obj); + enum mt25ql_error_t err = MT25QL_ERR_NONE; + + /* Restores the QSPI Flash controller and MT25QL to default state */ + err = mt25ql_restore_default_state(&FLASH_DEV); + if (err != MT25QL_ERR_NONE) { + return -1; + } + + return 0; +} + +int32_t flash_erase_sector(flash_t *obj, uint32_t address) +{ + (void)(obj); + enum mt25ql_error_t err = MT25QL_ERR_NONE; + + err = mt25ql_erase(&FLASH_DEV, address, MT25QL_ERASE_SUBSECTOR_4K); + if (err != MT25QL_ERR_NONE) { + return -1; + } + + return 0; +} + +int32_t flash_read(flash_t *obj, uint32_t address, + uint8_t *data, uint32_t size) +{ + (void)obj; + enum mt25ql_error_t err = MT25QL_ERR_NONE; + + err = mt25ql_command_read(&FLASH_DEV, address, data, size); + if (err != MT25QL_ERR_NONE) { + return -1; + } + + return 0; +} + +int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) +{ + (void)(obj); + enum mt25ql_error_t err = MT25QL_ERR_NONE; + + err = mt25ql_command_write(&FLASH_DEV, address, data, size); + if (err != MT25QL_ERR_NONE) { + return -1; + } + + return 0; +} + +uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) +{ + (void)(obj); + if ((address >= NS_QSPI_ALIAS_BASE) && (address < NS_QSPI_ALIAS_BASE + FLASH_TOTAL_SIZE)) { + return SUBSECTOR_4KB; + } + + return MBED_FLASH_INVALID_SIZE; +} + +uint32_t flash_get_page_size(const flash_t *obj) +{ + (void)(obj); + return FLASH_PAGE_SIZE; +} + +uint32_t flash_get_start_address(const flash_t *obj) +{ + (void)(obj); + return NS_QSPI_ALIAS_BASE; +} + +uint32_t flash_get_size(const flash_t *obj) +{ + (void)(obj); + return FLASH_TOTAL_SIZE; +} + +uint8_t flash_get_erase_value(const flash_t *obj) +{ + (void)obj; + return 0xFF; +} + +#endif // DEVICE_FLASH diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/spm_hal.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/spm_hal.c new file mode 100644 index 0000000000..a3fef1f553 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/spm_hal.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "platform/include/tfm_spm_hal.h" +#include "spm_api.h" +#include "spm_db.h" +#include "tfm_platform_core_api.h" +#include "target_cfg.h" +#include "Driver_MPC.h" +#include "mpu_armv8m_drv.h" +#include "region_defs.h" +#include "secure_utilities.h" + +/* Import MPC driver */ +extern ARM_DRIVER_MPC Driver_CODE_SRAM_MPC; + +/* Get address of memory regions to configure MPU */ +extern const struct memory_region_limits memory_regions; + +struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE }; + +void tfm_spm_hal_init_isolation_hw(void) +{ + /* Configures non-secure memory spaces in the target */ + sau_and_idau_cfg(); + mpc_init_cfg(); + ppc_init_cfg(); +} + +void tfm_spm_hal_configure_default_isolation( + const struct tfm_spm_partition_platform_data_t *platform_data) +{ + if (platform_data) { + if (platform_data->periph_ppc_bank != PPC_SP_DO_NOT_CONFIGURE) { + ppc_configure_to_secure(platform_data->periph_ppc_bank, + platform_data->periph_ppc_loc); + } + } +} + +#if TFM_LVL != 1 + +#define MPU_REGION_VENEERS 0 +#define MPU_REGION_TFM_UNPRIV_CODE 1 +#define MPU_REGION_TFM_UNPRIV_DATA 2 +#define MPU_REGION_NS_DATA 3 +#define PARTITION_REGION_RO 4 +#define PARTITION_REGION_RW_STACK 5 +#define PARTITION_REGION_PERIPH 6 +#define PARTITION_REGION_SHARE 7 + +REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base); +REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit); +REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base); +REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit); +REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); +REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit); + +static enum spm_err_t tfm_spm_mpu_init(void) +{ + struct mpu_armv8m_region_cfg_t region_cfg; + + mpu_armv8m_clean(&dev_mpu_s); + + /* Veneer region */ + region_cfg.region_nr = MPU_REGION_VENEERS; + region_cfg.region_base = memory_regions.veneer_base; + region_cfg.region_limit = memory_regions.veneer_limit; + region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV; + region_cfg.attr_sh = MPU_ARMV8M_SH_NONE; + region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK; + if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) { + return SPM_ERR_INVALID_CONFIG; + } + + /* TFM Core unprivileged code region */ + region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_CODE; + region_cfg.region_base = + (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base); + region_cfg.region_limit = + (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit); + region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV; + region_cfg.attr_sh = MPU_ARMV8M_SH_NONE; + region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK; + if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) { + return SPM_ERR_INVALID_CONFIG; + } + + /* TFM Core unprivileged data region */ + region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_DATA; + region_cfg.region_base = + (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base); + region_cfg.region_limit = + (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit); + region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV; + region_cfg.attr_sh = MPU_ARMV8M_SH_NONE; + region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER; + if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) { + return SPM_ERR_INVALID_CONFIG; + } + + /* TFM Core unprivileged non-secure data region */ + region_cfg.region_nr = MPU_REGION_NS_DATA; + region_cfg.region_base = NS_DATA_START; + region_cfg.region_limit = NS_DATA_LIMIT; + region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV; + region_cfg.attr_sh = MPU_ARMV8M_SH_NONE; + region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER; + if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) { + return SPM_ERR_INVALID_CONFIG; + } + + mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE, + HARDFAULT_NMI_ENABLE); + + return SPM_ERR_OK; +} + +enum spm_err_t tfm_spm_hal_partition_sandbox_config( + const struct tfm_spm_partition_memory_data_t *memory_data, + const struct tfm_spm_partition_platform_data_t *platform_data) +{ + /* This function takes a partition id and enables the + * SPM partition for that partition + */ + + struct mpu_armv8m_region_cfg_t region_cfg; + + mpu_armv8m_disable(&dev_mpu_s); + + /* Configure Regions */ + if (memory_data->ro_start) { + /* RO region */ + region_cfg.region_nr = PARTITION_REGION_RO; + region_cfg.region_base = memory_data->ro_start; + region_cfg.region_limit = memory_data->ro_limit; + region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV; + region_cfg.attr_sh = MPU_ARMV8M_SH_NONE; + region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK; + + if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) + != MPU_ARMV8M_OK) { + return SPM_ERR_INVALID_CONFIG; + } + } + + /* RW, ZI and stack as one region */ + region_cfg.region_nr = PARTITION_REGION_RW_STACK; + region_cfg.region_base = memory_data->rw_start; + region_cfg.region_limit = memory_data->stack_top; + region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV; + region_cfg.attr_sh = MPU_ARMV8M_SH_NONE; + region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER; + + if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) { + return SPM_ERR_INVALID_CONFIG; + } + + if (platform_data) { + /* Peripheral */ + region_cfg.region_nr = PARTITION_REGION_PERIPH; + region_cfg.region_base = platform_data->periph_start; + region_cfg.region_limit = platform_data->periph_limit; + region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV; + region_cfg.attr_sh = MPU_ARMV8M_SH_NONE; + region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER; + if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) + != MPU_ARMV8M_OK) { + return SPM_ERR_INVALID_CONFIG; + } + + ppc_en_secure_unpriv(platform_data->periph_ppc_bank, + platform_data->periph_ppc_loc); + } + + mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE, + HARDFAULT_NMI_ENABLE); + + return SPM_ERR_OK; +} + +enum spm_err_t tfm_spm_hal_partition_sandbox_deconfig( + const struct tfm_spm_partition_memory_data_t *memory_data, + const struct tfm_spm_partition_platform_data_t *platform_data) +{ + /* This function takes a partition id and disables the + * SPM partition for that partition + */ + + if (platform_data) { + /* Peripheral */ + ppc_clr_secure_unpriv(platform_data->periph_ppc_bank, + platform_data->periph_ppc_loc); + } + + mpu_armv8m_disable(&dev_mpu_s); + mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RO); + mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RW_STACK); + mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_PERIPH); + mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE); + mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE, + HARDFAULT_NMI_ENABLE); + + return SPM_ERR_OK; +} + +/** + * Set share region to which the partition needs access + */ +enum spm_err_t tfm_spm_hal_set_share_region( + enum tfm_buffer_share_region_e share) +{ + struct mpu_armv8m_region_cfg_t region_cfg; + enum spm_err_t res = SPM_ERR_INVALID_CONFIG; + uint32_t scratch_base = + (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); + uint32_t scratch_limit = + (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit); + + mpu_armv8m_disable(&dev_mpu_s); + + if (share == TFM_BUFFER_SHARE_DISABLE) { + mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE); + } else { + + region_cfg.region_nr = PARTITION_REGION_SHARE; + region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV; + region_cfg.attr_sh = MPU_ARMV8M_SH_NONE; + region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER; + switch (share) { + case TFM_BUFFER_SHARE_SCRATCH: + /* Use scratch area for SP-to-SP data sharing */ + region_cfg.region_base = scratch_base; + region_cfg.region_limit = scratch_limit; + res = SPM_ERR_OK; + break; + case TFM_BUFFER_SHARE_NS_CODE: + region_cfg.region_base = memory_regions.non_secure_partition_base; + region_cfg.region_limit = memory_regions.non_secure_partition_limit; + /* Only allow read access to NS code region and keep + * exec.never attribute + */ + region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV; + res = SPM_ERR_OK; + break; + default: + /* Leave res to be set to SPM_ERR_INVALID_CONFIG */ + break; + } + if (res == SPM_ERR_OK) { + mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg); + } + } + mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE, + HARDFAULT_NMI_ENABLE); + + return res; +} + +#endif /* TFM_LVL != 1 */ + +void tfm_spm_hal_setup_isolation_hw(void) +{ +#if TFM_LVL != 1 + if (tfm_spm_mpu_init() != SPM_ERR_OK) { + ERROR_MSG("Failed to set up initial MPU configuration! Halting."); + while (1) { + ; + } + } +#endif +} + +void MPC_Handler(void) +{ + /* Clear MPC interrupt flag and pending MPC IRQ */ + Driver_CODE_SRAM_MPC.ClearInterrupt(); + NVIC_ClearPendingIRQ(S_MPC_COMBINED_IRQn); + + /* Print fault message and block execution */ + LOG_MSG("Oops... MPC fault!!!"); + + /* Inform TF-M core that isolation boundary has been violated */ + tfm_access_violation_handler(); +} + +void PPC_Handler(void) +{ + /* + * Due to an issue on the FVP, the PPC fault doesn't trigger a + * PPC IRQ which is handled by the PPC_handler. + * In the FVP execution, this code is not execute. + */ + + /* Clear PPC interrupt flag and pending PPC IRQ */ + ppc_clear_irq(); + NVIC_ClearPendingIRQ(S_PPC_COMBINED_IRQn); + + /* Print fault message*/ + LOG_MSG("Oops... PPC fault!!!"); + + /* Inform TF-M core that isolation boundary has been violated */ + tfm_access_violation_handler(); +} + +uint32_t tfm_spm_hal_get_ns_VTOR(void) +{ + return memory_regions.non_secure_code_start; +} + +uint32_t tfm_spm_hal_get_ns_MSP(void) +{ + return *((uint32_t *)memory_regions.non_secure_code_start); +} + +uint32_t tfm_spm_hal_get_ns_entry_point(void) +{ + return *((uint32_t *)(memory_regions.non_secure_code_start+ 4)); +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/target_cfg.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/target_cfg.c new file mode 100644 index 0000000000..b2a1ed60b4 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/target_cfg.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2018-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cmsis.h" +#include "target_cfg.h" +#include "Driver_MPC.h" +#include "platform_retarget_dev.h" +#include "region_defs.h" +#include "tfm_secure_api.h" + +/* Macros to pick linker symbols */ +#define REGION(a, b, c) a##b##c +#define REGION_NAME(a, b, c) REGION(a, b, c) +#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c) + +/* The section names come from the scatter file */ +REGION_DECLARE(Load$$LR$$, LR_NS_PARTITION, $$Base); +REGION_DECLARE(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base); + +REGION_DECLARE(Image$$, ER_CODE_CMSE_VENEER, $$Base); +REGION_DECLARE(Image$$, ER_CODE_CMSE_VENEER, $$Limit); + +const struct memory_region_limits memory_regions = { + .non_secure_code_start = + (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) + + BL2_HEADER_SIZE, + + .non_secure_partition_base = + (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base), + + .non_secure_partition_limit = + (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) + + NS_PARTITION_SIZE - 1, + + .veneer_base = + (uint32_t)®ION_NAME(Image$$, ER_CODE_CMSE_VENEER, $$Base), + + .veneer_limit = + (uint32_t)®ION_NAME(Image$$, ER_CODE_CMSE_VENEER, $$Limit), +}; + +/* Allows software, via SAU, to define the code region as a NSC */ +#define NSCCFG_CODENSC 1 + +/* Import MPC driver */ +extern ARM_DRIVER_MPC Driver_CODE_SRAM_MPC, Driver_QSPI_MPC; +extern ARM_DRIVER_MPC Driver_ISRAM0_MPC, Driver_ISRAM1_MPC; +extern ARM_DRIVER_MPC Driver_ISRAM2_MPC, Driver_ISRAM3_MPC; + +/* Define Peripherals NS address range for the platform */ +#define PERIPHERALS_BASE_NS_START (0x40000000) +#define PERIPHERALS_BASE_NS_END (0x4FFFFFFF) + +/* Enable system reset request for CPU 0 */ +#define ENABLE_CPU0_SYSTEM_RESET_REQUEST (1U << 4U) + +/* To write into AIRCR register, 0x5FA value must be write to the VECTKEY field, + * otherwise the processor ignores the write. + */ +#define SCB_AIRCR_WRITE_MASK ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)) + +/* Debug configuration flags */ +#define SPNIDEN_SEL_STATUS (0x01u << 7) +#define SPNIDEN_STATUS (0x01u << 6) +#define SPIDEN_SEL_STATUS (0x01u << 5) +#define SPIDEN_STATUS (0x01u << 4) +#define NIDEN_SEL_STATUS (0x01u << 3) +#define NIDEN_STATUS (0x01u << 2) +#define DBGEN_SEL_STATUS (0x01u << 1) +#define DBGEN_STATUS (0x01u << 0) + +#define All_SEL_STATUS (SPNIDEN_SEL_STATUS | SPIDEN_SEL_STATUS | \ + NIDEN_SEL_STATUS | DBGEN_SEL_STATUS) + +struct tfm_spm_partition_platform_data_t tfm_peripheral_std_uart = { + MUSCA_UART1_NS_BASE, + MUSCA_UART1_NS_BASE + 0xFFF, + PPC_SP_DO_NOT_CONFIGURE, + -1 +}; + +void enable_fault_handlers(void) +{ + /* Enables BUS, MEM, USG and Secure faults */ + SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk + | SCB_SHCSR_BUSFAULTENA_Msk + | SCB_SHCSR_MEMFAULTENA_Msk + | SCB_SHCSR_SECUREFAULTENA_Msk; +} + +void system_reset_cfg(void) +{ + struct sysctrl_t *sysctrl = (struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S; + uint32_t reg_value = SCB->AIRCR; + + /* Enable system reset request for CPU 0, to be triggered via + * NVIC_SystemReset function. + */ + sysctrl->resetmask |= ENABLE_CPU0_SYSTEM_RESET_REQUEST; + + /* Clear SCB_AIRCR_VECTKEY value */ + reg_value &= ~(uint32_t)(SCB_AIRCR_VECTKEY_Msk); + + /* Enable system reset request only to the secure world */ + reg_value |= (uint32_t)(SCB_AIRCR_WRITE_MASK | SCB_AIRCR_SYSRESETREQS_Msk); + + SCB->AIRCR = reg_value; +} + +void tfm_spm_hal_init_debug(void) +{ + volatile struct sysctrl_t *sys_ctrl = + (struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S; + +#if defined(DAUTH_NONE) + /* Set all the debug enable selector bits to 1 */ + sys_ctrl->secdbgset = All_SEL_STATUS; + /* Set all the debug enable bits to 0 */ + sys_ctrl->secdbgclr = + DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS; +#elif defined(DAUTH_NS_ONLY) + /* Set all the debug enable selector bits to 1 */ + sys_ctrl->secdbgset = All_SEL_STATUS; + /* Set the debug enable bits to 1 for NS, and 0 for S mode */ + sys_ctrl->secdbgset = DBGEN_STATUS | NIDEN_STATUS; + sys_ctrl->secdbgclr = SPIDEN_STATUS | SPNIDEN_STATUS; +#elif defined(DAUTH_FULL) + /* Set all the debug enable selector bits to 1 */ + sys_ctrl->secdbgset = All_SEL_STATUS; + /* Set all the debug enable bits to 1 */ + sys_ctrl->secdbgset = + DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS; +#else + +#if !defined(DAUTH_CHIP_DEFAULT) +#error "No debug authentication setting is provided." +#endif + + /* Set all the debug enable selector bits to 0 */ + sys_ctrl->secdbgclr = All_SEL_STATUS; + + /* No need to set any enable bits because the value depends on + * input signals. + */ +#endif +} + +/*----------------- NVIC interrupt target state to NS configuration ----------*/ +void nvic_interrupt_target_state_cfg() +{ + /* Target every interrupt to NS; unimplemented interrupts will be WI */ + for (uint8_t i=0; iITNS)/sizeof(NVIC->ITNS[0]); i++) { + NVIC->ITNS[i] = 0xFFFFFFFF; + } + + /* Make sure that MPC and PPC are targeted to S state */ + NVIC_ClearTargetState(S_MPC_COMBINED_IRQn); + NVIC_ClearTargetState(S_PPC_COMBINED_IRQn); +} + +/*----------------- NVIC interrupt enabling for S peripherals ----------------*/ +void nvic_interrupt_enable() +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + + /* MPC interrupt enabling */ + Driver_QSPI_MPC.EnableInterrupt(); + Driver_CODE_SRAM_MPC.EnableInterrupt(); + NVIC_EnableIRQ(S_MPC_COMBINED_IRQn); + + /* PPC interrupt enabling */ + /* Clear pending PPC interrupts */ + /* In the PPC configuration function, we have used the Non-Secure + * Privilege Control Block to grant unprivilged NS access to some + * peripherals used by NS. That triggers a PPC0 exception as that + * register is meant for NS privileged access only. Clear it here + */ + spctrl->secppcintclr = CMSDK_APB_PPC0_INT_POS_MASK; + + /* Enable PPC interrupts for APB PPC */ + spctrl->secppcinten |= CMSDK_APB_PPC0_INT_POS_MASK; + spctrl->secppcinten |= CMSDK_APB_PPC1_INT_POS_MASK; + spctrl->secppcinten |= CMSDK_APB_PPCEXP0_INT_POS_MASK; + spctrl->secppcinten |= CMSDK_APB_PPCEXP1_INT_POS_MASK; + spctrl->secppcinten |= CMSDK_APB_PPCEXP2_INT_POS_MASK; + spctrl->secppcinten |= CMSDK_APB_PPCEXP3_INT_POS_MASK; + NVIC_EnableIRQ(S_PPC_COMBINED_IRQn); +} + +/*------------------- SAU/IDAU configuration functions -----------------------*/ + +void sau_and_idau_cfg(void) +{ + /* Enables SAU */ + TZ_SAU_Enable(); + + /* Configures SAU regions to be non-secure */ + SAU->RNR = TFM_NS_REGION_CODE; + SAU->RBAR = (memory_regions.non_secure_partition_base + & SAU_RBAR_BADDR_Msk); + SAU->RLAR = (memory_regions.non_secure_partition_limit + & SAU_RLAR_LADDR_Msk) + | SAU_RLAR_ENABLE_Msk; + + SAU->RNR = TFM_NS_REGION_DATA; + SAU->RBAR = (NS_DATA_START & SAU_RBAR_BADDR_Msk); + SAU->RLAR = (NS_DATA_LIMIT & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk; + + /* Configures veneers region to be non-secure callable */ + SAU->RNR = TFM_NS_REGION_VENEER; + SAU->RBAR = (memory_regions.veneer_base & SAU_RBAR_BADDR_Msk); + SAU->RLAR = (memory_regions.veneer_limit & SAU_RLAR_LADDR_Msk) + | SAU_RLAR_ENABLE_Msk + | SAU_RLAR_NSC_Msk; + + /* Configure the peripherals space */ + SAU->RNR = TFM_NS_REGION_PERIPH_1; + SAU->RBAR = (PERIPHERALS_BASE_NS_START & SAU_RBAR_BADDR_Msk); + SAU->RLAR = (PERIPHERALS_BASE_NS_END & SAU_RLAR_LADDR_Msk) + | SAU_RLAR_ENABLE_Msk; + + /* FIXME: Secondary image partition info comes from BL2. Configure SAU + * based on those limits. + */ + + /* Allows SAU to define the code region as a NSC */ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + spctrl->nsccfg |= NSCCFG_CODENSC; +} + +/*------------------- Memory configuration functions -------------------------*/ + +void mpc_init_cfg(void) +{ + ARM_DRIVER_MPC* mpc_data_region0 = &Driver_ISRAM0_MPC; + ARM_DRIVER_MPC* mpc_data_region1 = &Driver_ISRAM1_MPC; + ARM_DRIVER_MPC* mpc_data_region2 = &Driver_ISRAM2_MPC; + ARM_DRIVER_MPC* mpc_data_region3 = &Driver_ISRAM3_MPC; + + Driver_CODE_SRAM_MPC.Initialize(); + Driver_CODE_SRAM_MPC.ConfigRegion(memory_regions.non_secure_partition_base, + memory_regions.non_secure_partition_limit, + ARM_MPC_ATTR_NONSECURE); + + mpc_data_region0->Initialize(); + mpc_data_region0->ConfigRegion(MPC_ISRAM0_RANGE_BASE_S, + MPC_ISRAM0_RANGE_LIMIT_S, + ARM_MPC_ATTR_SECURE); + + mpc_data_region1->Initialize(); + mpc_data_region1->ConfigRegion(MPC_ISRAM1_RANGE_BASE_S, + MPC_ISRAM1_RANGE_LIMIT_S, + ARM_MPC_ATTR_SECURE); + + mpc_data_region2->Initialize(); + +#if defined(TEST_FRAMEWORK_S) || defined(TEST_FRAMEWORK_NS) + /* To run the regression tests on Musca A1, it is required to assign more + * RAM memory in the secure execution environment. + * So, the secure RAM memory size is 96KB and the non-secure one is 32 KB. + * When it is not required to run the regression tests, the RAM memory + * partition is the original one which is 64KB of the RAM memory for each + * execution environment. + */ + mpc_data_region2->ConfigRegion(MPC_ISRAM2_RANGE_BASE_S, + MPC_ISRAM2_RANGE_LIMIT_S, + ARM_MPC_ATTR_SECURE); +#else + mpc_data_region2->ConfigRegion(MPC_ISRAM2_RANGE_BASE_NS, + MPC_ISRAM2_RANGE_LIMIT_NS, + ARM_MPC_ATTR_NONSECURE); +#endif + + mpc_data_region3->Initialize(); + mpc_data_region3->ConfigRegion(MPC_ISRAM3_RANGE_BASE_NS, + MPC_ISRAM3_RANGE_LIMIT_NS, + ARM_MPC_ATTR_NONSECURE); + + /* Lock down the MPC configuration */ + Driver_CODE_SRAM_MPC.LockDown(); + mpc_data_region0->LockDown(); + mpc_data_region1->LockDown(); + mpc_data_region2->LockDown(); + mpc_data_region3->LockDown(); + + /* Add barriers to assure the MPC configuration is done before continue + * the execution. + */ + __DSB(); + __ISB(); +} + +/*---------------------- PPC configuration functions -------------------------*/ + +void ppc_init_cfg(void) +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + struct nspctrl_def* nspctrl = CMSDK_NSPCTRL; + + /* Grant non-secure access to peripherals in the PPC0 + * (timer0 and 1, dualtimer, watchdog, mhu 0 and 1) + */ + spctrl->apbnsppc0 |= (1U << CMSDK_TIMER0_APB_PPC_POS); + spctrl->apbnsppc0 |= (1U << CMSDK_TIMER1_APB_PPC_POS); + spctrl->apbnsppc0 |= (1U << CMSDK_DTIMER_APB_PPC_POS); + spctrl->apbnsppc0 |= (1U << CMSDK_MHU0_APB_PPC_POS); + spctrl->apbnsppc0 |= (1U << CMSDK_MHU1_APB_PPC_POS); + + /* Grant non-secure access to S32K Timer in PPC1*/ + spctrl->apbnsppc1 |= (1U << CMSDK_S32K_TIMER_PPC_POS); + + /* Grant non-secure access for AHB peripherals on EXP0 */ + spctrl->ahbnsppcexp0 = (1U << MUSCA_PERIPHS_AHB_PPC_POS); + + /* in NS, grant un-privileged for AHB peripherals on EXP0 */ + nspctrl->ahbnspppcexp0 = (1U << MUSCA_PERIPHS_AHB_PPC_POS); + + /* Configure the response to a security violation as a + * bus error instead of RAZ/WI + */ + spctrl->secrespcfg |= 1U; +} + +void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t pos) +{ + /* Setting NS flag for peripheral to enable NS access */ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + ((uint32_t*)&(spctrl->ahbnsppc0))[bank] |= (1U << pos); +} + +void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t pos) +{ + /* Clear NS flag for peripheral to prevent NS access */ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + ((uint32_t*)&(spctrl->ahbnsppc0))[bank] &= ~(1U << pos); +} + +void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos) +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + ((uint32_t*)&(spctrl->ahbspppc0))[bank] |= (1U << pos); +} + +void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos) +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + ((uint32_t*)&(spctrl->ahbspppc0))[bank] &= ~(1U << pos); +} + +void ppc_clear_irq(void) +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + /* Clear APB PPC EXP2 IRQ */ + spctrl->secppcintclr = CMSDK_APB_PPCEXP2_INT_POS_MASK; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/target_cfg.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/target_cfg.h new file mode 100644 index 0000000000..a98f2f39b0 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/target_cfg.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TARGET_CFG_H__ +#define __TARGET_CFG_H__ + +#include "tfm_peripherals_def.h" + +/** + * \brief Defines the word offsets of Slave Peripheral Protection Controller + * Registers + */ +enum ppc_bank_e +{ + PPC_SP_DO_NOT_CONFIGURE = -1, + PPC_SP_AHB_PPC0 = 0, + PPC_SP_RES0, + PPC_SP_RES1, + PPC_SP_RES2, + PPC_SP_AHB_PPC_EXP0, + PPC_SP_AHB_PPC_EXP1, + PPC_SP_AHB_PPC_EXP2, + PPC_SP_AHB_PPC_EXP3, + PPC_SP_APB_PPC0, + PPC_SP_APB_PPC1, + PPC_SP_RES3, + PPC_SP_RES4, + PPC_SP_APB_PPC_EXP0, + PPC_SP_APB_PPC_EXP1, + PPC_SP_APB_PPC_EXP2, + PPC_SP_APB_PPC_EXP3, +}; + +/** + * \brief Store the addresses of memory regions + */ +struct memory_region_limits { + uint32_t non_secure_code_start; + uint32_t non_secure_partition_base; + uint32_t non_secure_partition_limit; + uint32_t veneer_base; + uint32_t veneer_limit; +}; + +/** + * \brief Holds the data necessary to do isolation for a specific peripheral. + */ +struct tfm_spm_partition_platform_data_t +{ + uint32_t periph_start; + uint32_t periph_limit; + int16_t periph_ppc_bank; + int16_t periph_ppc_loc; +}; + +/** + * \brief Configures the Memory Protection Controller. + */ +void mpc_init_cfg(void); + +/** + * \brief Configures the Peripheral Protection Controller. + */ +void ppc_init_cfg(void); + +/** + * \brief Restict access to peripheral to secure + */ +void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t loc); + +/** + * \brief Allow non-secure access to peripheral + */ +void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t loc); + +/** + * \brief Enable secure unprivileged access to peripheral + */ +void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos); + +/** + * \brief Clear secure unprivileged access to peripheral + */ +void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos); + +/** + * \brief Clears PPC interrupt. + */ +void ppc_clear_irq(void); + +/** + * \brief Configures SAU and IDAU. + */ +void sau_and_idau_cfg(void); + + +#endif /* __TARGET_CFG_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/tfm_peripherals_def.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/tfm_peripherals_def.h new file mode 100644 index 0000000000..ab5f174fdd --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_S/tfm_peripherals_def.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PERIPHERALS_DEF_H__ +#define __TFM_PERIPHERALS_DEF_H__ + +struct tfm_spm_partition_platform_data_t; + +extern struct tfm_spm_partition_platform_data_t tfm_peripheral_std_uart; + +#define TFM_PERIPHERAL_STD_UART (&tfm_peripheral_std_uart) + +#endif /* __TFM_PERIPHERALS_DEF_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device.h new file mode 100644 index 0000000000..dce9696f4f --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device.h @@ -0,0 +1,24 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_DEVICE_H +#define MBED_DEVICE_H + +#include "objects.h" + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/cmsis.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/cmsis.h new file mode 100644 index 0000000000..775cc598b4 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/cmsis.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MUSCA_CMSIS_H__ +#define __MUSCA_CMSIS_H__ + +/* CMSIS wrapper for Musca board */ + +#include "system_cmsdk_musca.h" +#include "platform_regs.h" /* Platform registers */ +#include "platform_retarget.h" /* Peripherals base addresses */ + +#if defined(TARGET_MUSCA_A1_NS) +#include "cmsis_nvic.h" +#endif + +#endif /*__MUSCA_CMSIS_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/cmsis_cpu.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/cmsis_cpu.h new file mode 100644 index 0000000000..03c43cff68 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/cmsis_cpu.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_CPU_H__ +#define __CMSIS_CPU_H__ + +#include "system_core_musca.h" +#include "core_cm33.h" + +#endif /* __CMSIS_CPU_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/device_cfg.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/device_cfg.h new file mode 100644 index 0000000000..333b0a25b4 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/device_cfg.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ARM_LTD_DEVICE_CFG_H__ +#define __ARM_LTD_DEVICE_CFG_H__ + +/** + * \file device_cfg.h + * \brief Configuration file native driver re-targeting + * + * \details This file can be used to add native driver specific macro + * definitions to select which peripherals are available in the build. + * + * This is a default device configuration file with all peripherals enabled. + */ + +/* ARM SCC */ +#if defined(TARGET_MUSCA_A1_S) +#define MUSCA_A1_SCC_S +#endif + +#if defined(TARGET_MUSCA_A1_NS) +#define MUSCA_A1_SCC_NS +#define MUSCA_A1_SCC_DEV MUSCA_A1_SCC_DEV_NS +#endif + +#if defined(TARGET_MUSCA_A1_S) + +/* ARM Memory Protection Controller (MPC) SIE 200 */ +#define MPC_ISRAM0_S +#define MPC_ISRAM1_S +#define MPC_ISRAM2_S +#define MPC_ISRAM3_S +#define MPC_CODE_SRAM_S +#define MPC_CODE_SRAM_NS +#define MPC_QSPI_S +#define MPC_QSPI_NS + +/* ARM Peripheral Protection Controllers (PPC) */ +#define AHB_PPC0_S +#define AHB_PPCEXP0_S +#define AHB_PPCEXP1_S +#define AHB_PPCEXP2_S +#define AHB_PPCEXP3_S + +#define APB_PPC0_S +#define APB_PPC1_S +#define APB_PPCEXP0_S +#define APB_PPCEXP1_S +#define APB_PPCEXP2_S +#define APB_PPCEXP3_S + +#endif // defined(TARGET_MUSCA_A1_S) + +/*ARM UART Controller PL011*/ +#if defined(TARGET_MUSCA_A1_NS) +#define UART0_PL011_NS +#define UART0_PL011_DEV UART0_PL011_DEV_NS +#define uart0_tx_irq_handler UARTTX0_Handler +#define uart0_rx_irq_handler UARTRX0_Handler +#define uart0_rx_timeout_irq_handler UART0_RxTimeout_IRQHandler +#endif + +#if defined(TARGET_MUSCA_A1_NS) +#define UART1_PL011_NS +#define UART1_PL011_DEV UART1_PL011_DEV_NS +#define uart1_tx_irq_handler UARTTX1_Handler +#define uart1_rx_irq_handler UARTRX1_Handler +#define uart1_rx_timeout_irq_handler UART1_RxTimeout_IRQHandler +#endif + +/* CMSDK Timers */ +#if defined(TARGET_MUSCA_A1_S) +#define CMSDK_TIMER0_S +#endif + +#if defined(TARGET_MUSCA_A1_NS) +#define CMSDK_TIMER0_NS +#define CMSDK_TIMER0_DEV CMSDK_TIMER0_DEV_NS +#endif + +#if defined(TARGET_MUSCA_A1_S) +#define CMSDK_TIMER1_S +#endif + +#if defined(TARGET_MUSCA_A1_NS) +#define CMSDK_TIMER1_NS +#endif + +#if defined(TARGET_MUSCA_A1_S) + +/* Cadence QSPI Flash Controller */ +#define QSPI_IP6514E_S +#define QSPI_IP6514E_NS + +/* MT25QL Flash memory library */ +#define MT25QL_S +#define MT25QL_NS + +#endif // defined(TARGET_MUSCA_A1_S) + +#if defined(TARGET_MUSCA_A1_NS) +/* GP Timer */ +#define GP_TIMER_NS +#define GP_TIMER_DEV GP_TIMER_DEV_NS + +#define GP_TIMER_ALARM0_IRQ GpTimer0_IRQn +#define GP_TIMER_IRQ0_HANDLER GpTimer0_IRQHandler +#define GP_TIMER_ALARM_NR TIMER_GP_READ_ALARM_0 +#define GP_TIMER_FREQ_HZ 32768UL /* System Ref Clock */ +#define GP_TIMER_BIT_WIDTH 32U + +/** + * mbed usec high-resolution ticker configuration + */ +#define USEC_TIMER_DEV CMSDK_TIMER0_DEV_NS +#define usec_interval_irq_handler TIMER0_IRQHandler +#define USEC_INTERVAL_IRQ TIMER0_IRQn +/** Timer frequency is equal to SYSTEM_CLOCK, defined in system_cmsdk_musca.c */ +#define TIMER_FREQ_HZ 50000000U +/** The us Ticker uses CMSDK Timer, that does not have HW prescaler. + * The reported shift define is necessary for the software emulated + * prescaler behavior, so the ticker works as if it was ticking on a + * virtually slower frequency. The value 5 sets up the ticker to work + * properly in the specified frequency interval. + */ +#define USEC_REPORTED_SHIFT 6 +#define USEC_REPORTED_FREQ_HZ (TIMER_FREQ_HZ >> USEC_REPORTED_SHIFT) +#define USEC_REPORTED_BITS (32 - USEC_REPORTED_SHIFT) + +#define UART_DEFAULT_BAUD_RATE 9600U +#endif // TARGET_MUSCA_A1_NS + +#endif /* __ARM_LTD_DEVICE_CFG_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/musca_a1_scc_drv.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/musca_a1_scc_drv.c new file mode 100644 index 0000000000..191d1f61f7 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/musca_a1_scc_drv.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "musca_a1_scc_drv.h" + +struct musca_a1_scc_reg_map_t { + volatile uint32_t reset_ctrl; /* 0x00 RW Reset Control Register */ + volatile uint32_t clk_ctrl; /* 0x04 RW Clock Control Register*/ + volatile uint32_t pwr_ctrl; /* 0x08 RW Power Control Register*/ + volatile uint32_t pll_ctrl; /* 0x0C RW Power Control Register */ + volatile uint32_t dbg_ctrl; /* 0x10 RW Debug Control Register */ + volatile uint32_t sram_ctrl; /* 0x14 RW SRAM Control Register */ + volatile uint32_t intr_ctrl; /* 0x18 RW Interupt Control Register */ + volatile uint32_t reserved1; /* 0x1C RW reserved */ + volatile uint32_t cpu0_vtor_sram; /* 0x20 RW Reset vector for CPU0 Secure Mode */ + volatile uint32_t cpu0_vtor_flash; /* 0x24 RW Reset vector for CPU0 Secure Mode */ + volatile uint32_t cpu1_vtor_sram; /* 0x28 RW Reset vector for CPU1 Secure Mode */ + volatile uint32_t cpu1_vtor_flash; /* 0x2C RW Reset vector for CPU0 Secure Mode */ + volatile uint32_t iomux_main_insel; /* 0x30 RW Main function in data select */ + volatile uint32_t iomux_main_outsel; /* 0x34 RW Main function out data select */ + volatile uint32_t iomux_main_oensel; /* 0x38 RW Main function out enable select */ + volatile uint32_t iomux_main_default_in; /* 0x3C RW Main function default in select */ + volatile uint32_t iomux_altf1_insel; /* 0x40 RW Alt function 1 in data select */ + volatile uint32_t iomux_altf1_outsel; /* 0x44 RW Alt function 1 out data select */ + volatile uint32_t iomux_altf1_oensel; /* 0x48 RW Alt function 1 out enable select */ + volatile uint32_t iomux_altf1_default_in; /* 0x4C RW Alt function 1 default in select */ + volatile uint32_t iomux_altf2_insel; /* 0x50 RW Alt function 2 in data select */ + volatile uint32_t iomux_altf2_outsel; /* 0x54 RW Alt function 2 out data select */ + volatile uint32_t iomux_altf2_oensel; /* 0x58 RW Alt function 2 out enable select */ + volatile uint32_t iomux_altf2_default_in; /* 0x5C RW Alt function 2 default in select */ + volatile uint32_t pvt_ctrl; /* 0x60 RW PVT control register */ + volatile uint32_t spare0; /* 0x64 RW reserved */ + volatile uint32_t iopad_ds0; /* 0x68 RW Drive Select 0 */ + volatile uint32_t iopad_ds1; /* 0x6C RW Drive Select 1 */ + volatile uint32_t iopad_pe; /* 0x70 RW Pull Enable */ + volatile uint32_t iopad_ps; /* 0x74 RW Pull Select */ + volatile uint32_t iopad_sr; /* 0x78 RW Slew Select */ + volatile uint32_t iopad_is; /* 0x7C RW Input Select */ + volatile uint32_t sram_rw_margine; /* 0x80 RW reserved */ + volatile uint32_t static_conf_sig0; /* 0x84 RW Static configuration */ + volatile uint32_t static_conf_sig1; /* 0x88 RW Static configuration */ + volatile uint32_t req_set; /* 0x8C RW External Event Enable */ + volatile uint32_t req_clear; /* 0x90 RW External Event Clear */ + volatile uint32_t iomux_altf3_insel; /* 0x94 RW Alt function 3 in data select */ + volatile uint32_t iomux_altf3_outsel; /* 0x98 RW Alt function 3 out data select */ + volatile uint32_t iomux_altf3_oensel; /* 0x9C RW Alt function 3 out enable select */ + volatile uint32_t iomux_altf3_default_in; /* 0xA0 RW Alt function 3 default in select */ + volatile uint32_t pcsm_ctrl_override; /* 0xA4 RW Q-Channels QACTIVE Override */ + volatile uint32_t pd_cpu0_iso_override; /* 0xA8 RW CPU0 Isolation Override */ + volatile uint32_t pd_cpu1_iso_override; /* 0xAC RW CPU1 Isolation Override */ + volatile uint32_t sys_sram_rw_assist0; /* 0xB0 RW CPU0 icache sram ldata */ + volatile uint32_t sys_sram_rw_assist1; /* 0xB4 RW CPU0 icache sram tag */ + volatile uint32_t sys_sram_rw_assist2; /* 0xB8 RW CPU1 icache sram ldata */ + volatile uint32_t sys_sram_rw_assist3; /* 0xBC RW CPU1 icache sram tag */ + volatile uint32_t sys_sram_rw_assist4; /* 0xC0 RW System sram */ + volatile uint32_t sys_sram_rw_assist5; /* 0xC4 RW System sram */ + volatile uint32_t reserved2[3]; /* reserved */ + volatile uint32_t crypto_sram_rw_assist0; /* 0xD4 RW Crypto ram */ + volatile uint32_t crypto_sram_rw_assist1; /* 0xD8 RW Crypto sec sram */ + volatile uint32_t crypto_sram_rw_assist2; /* 0xDC RW Reserved */ + volatile uint32_t req_edge_sel; /* 0xC0 RW Power clock request edge select */ + volatile uint32_t req_enable; /* 0xC4 RW Power clock request enable */ + volatile uint32_t reserved3[28]; /* reserved */ + volatile uint32_t chip_id; /* 0x100 RO Chip ID 0x0797_0477 */ + volatile uint32_t clock_status; /* 0x104 RO Clock status */ + volatile uint32_t io_in_status; /* 0x108 RO I/O in status */ +}; + +/** + * \brief Clears selected alternate functions for selected pins + * + * \param[in] dev SCC registers base address \ref musca_a1_scc_reg_map_t + * \param[in] func_mask Bitmask of alternate functions to clear + * \ref gpio_altfunc_mask_t + * \param[in] pin_mask Pin mask for the alternate functions + */ +static void scc_clear_alt_func(struct musca_a1_scc_reg_map_t* scc_regs, + enum gpio_altfunc_mask_t func_mask, + uint32_t pin_mask) +{ + if (func_mask & GPIO_MAIN_FUNC_MASK) { + scc_regs->iomux_main_insel &= ~pin_mask; + scc_regs->iomux_main_outsel &= ~pin_mask; + scc_regs->iomux_main_oensel &= ~pin_mask; + } + if (func_mask & GPIO_ALTFUNC_1_MASK) { + scc_regs->iomux_altf1_insel &= ~pin_mask; + scc_regs->iomux_altf1_outsel &= ~pin_mask; + scc_regs->iomux_altf1_oensel &= ~pin_mask; + } + if (func_mask & GPIO_ALTFUNC_2_MASK) { + scc_regs->iomux_altf2_insel &= ~pin_mask; + scc_regs->iomux_altf2_outsel &= ~pin_mask; + scc_regs->iomux_altf2_oensel &= ~pin_mask; + } + if (func_mask & GPIO_ALTFUNC_3_MASK) { + scc_regs->iomux_altf3_insel &= ~pin_mask; + scc_regs->iomux_altf3_outsel &= ~pin_mask; + scc_regs->iomux_altf3_oensel &= ~pin_mask; + } +} + +void musca_a1_scc_set_alt_func(struct musca_a1_scc_dev_t* dev, + enum gpio_altfunc_t altfunc, uint32_t pin_mask) +{ + struct musca_a1_scc_reg_map_t* scc_regs = + (struct musca_a1_scc_reg_map_t*) dev->cfg->base; + enum gpio_altfunc_mask_t altfunc_to_clear = GPIO_ALTFUNC_NONE; + volatile uint32_t *insel = NULL; + volatile uint32_t *outsel = NULL; + volatile uint32_t *oensel = NULL; + + if (altfunc >= GPIO_ALTFUNC_MAX) { + /* If no altfunction is selected, then nothing to do. + * This is possible during init and we do not + * want to change the reset values set by the HW + */ + return; + } + + switch (altfunc) { + case GPIO_MAIN_FUNC: + insel = &scc_regs->iomux_main_insel; + outsel = &scc_regs->iomux_main_outsel; + oensel = &scc_regs->iomux_main_oensel; + altfunc_to_clear = GPIO_MAIN_FUNC_NEG_MASK; + break; + + case GPIO_ALTFUNC_1: + insel = &scc_regs->iomux_altf1_insel; + outsel = &scc_regs->iomux_altf1_outsel; + oensel = &scc_regs->iomux_altf1_oensel; + altfunc_to_clear = GPIO_ALTFUNC_1_NEG_MASK; + break; + + case GPIO_ALTFUNC_2: + insel = &scc_regs->iomux_altf2_insel; + outsel = &scc_regs->iomux_altf2_outsel; + oensel = &scc_regs->iomux_altf2_oensel; + altfunc_to_clear = GPIO_ALTFUNC_2_NEG_MASK; + break; + + case GPIO_ALTFUNC_3: + insel = &scc_regs->iomux_altf3_insel; + outsel = &scc_regs->iomux_altf3_outsel; + oensel = &scc_regs->iomux_altf3_oensel; + altfunc_to_clear = GPIO_ALTFUNC_3_NEG_MASK; + break; + default: + break; + } + + /* Select the wanted function's output enable bit first. + * This way the output won't be disabled which is desired + * if we switch from output to output function + */ + *oensel |= pin_mask; + + /* Clear all alternate function registers which are not selected */ + scc_clear_alt_func(scc_regs, altfunc_to_clear, pin_mask); + + /* Enable input and output data line */ + *insel |= pin_mask; + *outsel |= pin_mask; +} + +void musca_a1_scc_set_pinmode(struct musca_a1_scc_dev_t* dev, uint32_t pin_mask, + enum pinmode_select_t mode) +{ + struct musca_a1_scc_reg_map_t* scc_regs = + (struct musca_a1_scc_reg_map_t*) dev->cfg->base; + + switch (mode) { + case PINMODE_NONE: + scc_regs->iopad_pe &= ~pin_mask; + break; + case PINMODE_PULL_DOWN: + /* If the pull select bit is set to 0 it means pull down */ + scc_regs->iopad_ps &= ~pin_mask; + scc_regs->iopad_pe |= pin_mask; + break; + case PINMODE_PULL_UP: + /* If the pull select bit is set to 1 it means pull up */ + scc_regs->iopad_ps |= pin_mask; + scc_regs->iopad_pe |= pin_mask; + break; + default: + break; + } +} + +void musca_a1_scc_set_default_in(struct musca_a1_scc_dev_t* dev, + enum gpio_altfunc_t altfunc, + uint32_t default_in_mask, + uint32_t default_in_value) +{ + struct musca_a1_scc_reg_map_t* scc_regs = + (struct musca_a1_scc_reg_map_t*) dev->cfg->base; + uint32_t iomux_value = 0; + + if (altfunc >= GPIO_ALTFUNC_MAX) { + /* If no altfunction is selected, then nothing to do */ + return; + } + + switch (altfunc) { + case GPIO_MAIN_FUNC: + iomux_value = scc_regs->iomux_main_default_in & ~default_in_mask; + iomux_value |= (default_in_value & default_in_mask); + scc_regs->iomux_main_default_in = iomux_value; + scc_regs->iomux_main_insel = (scc_regs->iomux_main_insel & ~default_in_mask); + break; + + case GPIO_ALTFUNC_1: + iomux_value = scc_regs->iomux_altf1_default_in & ~default_in_mask; + iomux_value |= (default_in_value & default_in_mask); + scc_regs->iomux_altf1_default_in = iomux_value; + scc_regs->iomux_altf1_insel = (scc_regs->iomux_altf1_insel & ~default_in_mask); + break; + + case GPIO_ALTFUNC_2: + iomux_value = scc_regs->iomux_altf2_default_in & ~default_in_mask; + iomux_value |= (default_in_value & default_in_mask); + scc_regs->iomux_altf2_default_in = iomux_value; + scc_regs->iomux_altf2_insel = (scc_regs->iomux_altf2_insel & ~default_in_mask); + break; + + case GPIO_ALTFUNC_3: + iomux_value = scc_regs->iomux_altf3_default_in & ~default_in_mask; + iomux_value |= (default_in_value & default_in_mask); + scc_regs->iomux_altf3_default_in = iomux_value; + scc_regs->iomux_altf3_insel = (scc_regs->iomux_altf3_insel & ~default_in_mask); + break; + default: + break; + } +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/musca_a1_scc_drv.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/musca_a1_scc_drv.h new file mode 100644 index 0000000000..91ecb12284 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/musca_a1_scc_drv.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __MUSCA_A1_SCC_DRV_H__ +#define __MUSCA_A1_SCC_DRV_H__ + +#include +#include + +/** + * \brief Enum to store alternate function values. + * They are used as shift operand, must be unsigned. + */ +enum gpio_altfunc_t { + GPIO_MAIN_FUNC = 0UL, + GPIO_ALTFUNC_1, + GPIO_ALTFUNC_2, + GPIO_ALTFUNC_3, + GPIO_ALTFUNC_MAX +}; + +#define GPIO_ALTFUNC_ALL_MASK ((1U << GPIO_ALTFUNC_MAX) - 1) + +/** +* \brief Enum to store alternate function mask values. +*/ +enum gpio_altfunc_mask_t { + GPIO_ALTFUNC_NONE = 0, + GPIO_MAIN_FUNC_MASK = (1UL << GPIO_MAIN_FUNC), + GPIO_ALTFUNC_1_MASK = (1UL << GPIO_ALTFUNC_1), + GPIO_ALTFUNC_2_MASK = (1UL << GPIO_ALTFUNC_2), + GPIO_ALTFUNC_3_MASK = (1UL << GPIO_ALTFUNC_3), + GPIO_MAIN_FUNC_NEG_MASK = (~GPIO_MAIN_FUNC_MASK & GPIO_ALTFUNC_ALL_MASK), + GPIO_ALTFUNC_1_NEG_MASK = (~GPIO_ALTFUNC_1_MASK & GPIO_ALTFUNC_ALL_MASK), + GPIO_ALTFUNC_2_NEG_MASK = (~GPIO_ALTFUNC_2_MASK & GPIO_ALTFUNC_ALL_MASK), + GPIO_ALTFUNC_3_NEG_MASK = (~GPIO_ALTFUNC_3_MASK & GPIO_ALTFUNC_ALL_MASK) +}; + +enum pinmode_select_t { + PINMODE_NONE, + PINMODE_PULL_DOWN, + PINMODE_PULL_UP +}; + +/* MUSCA SCC device configuration structure */ +struct musca_a1_scc_dev_cfg_t { + const uint32_t base; /*!< SCC base address */ +}; + +/* MUSCA SCC device structure */ +struct musca_a1_scc_dev_t { + const struct musca_a1_scc_dev_cfg_t* const cfg; /*!< SCC configuration */ +}; + +/** + * \brief Sets selected alternate functions for selected pins + * + * \param[in] dev SCC device pointer \ref musca_a1_scc_dev_t + * \param[in] altfunc Alternate function to set \ref gpio_altfunc_t + * \param[in] pin_mask Pin mask for the alternate functions + * + * \note This function doesn't check if scc dev is NULL. + * \note If no alternate function is selected then the function won't do anything + */ +void musca_a1_scc_set_alt_func(struct musca_a1_scc_dev_t* dev, + enum gpio_altfunc_t altfunc, uint32_t pin_mask); + +/** + * \brief Sets pinmode for the given pins + * + * \param[in] dev SCC device pointer \ref musca_a1_scc_dev_t + * \param[in] pin_mask Pin mask for the alternate functions + * \param[in] mode Pin mode to set \ref pinmode_select_t + * + * \note This function doesn't check if scc dev is NULL. + */ +void musca_a1_scc_set_pinmode(struct musca_a1_scc_dev_t* dev, uint32_t pin_mask, + enum pinmode_select_t mode); + +/** + * \brief Sets default input values for the selected pins + * + * \param[in] dev SCC device pointer \ref musca_a1_scc_dev_t + * \param[in] altfunc The selected alternate function that is set the + * specified default in value \ref gpio_altfunc_t + * \param[in] default_in_mask Pin mask for selecting pins + * \param[in] default_in_value Pin values for the selected pins + * + * \note This function doesn't check if scc_base is NULL. + * \note If no alternate function is selected, the function won't do anything + */ +void musca_a1_scc_set_default_in(struct musca_a1_scc_dev_t* dev, + enum gpio_altfunc_t altfunc, + uint32_t default_in_mask, + uint32_t default_in_value); + +#endif /* __MUSCA_A1_SCC_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/timer_cmsdk_drv.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/timer_cmsdk_drv.c new file mode 100644 index 0000000000..4272e1d968 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/timer_cmsdk_drv.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file timer_cmsdk_drv.c + * \brief Generic driver for CMSDK APB Timers. + * The timer is a 32-bit down-counter with the following features: + * - optional programmable external clock source + * - programmable interrupt source, triggered if counter reaches 0 + * - automatic reload if counter reaches 0 + */ + +#include "timer_cmsdk_drv.h" + +/** Setter bit manipulation macro */ +#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX))) +/** Clearing bit manipulation macro */ +#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX))) +/** Getter bit manipulation macro */ +#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX)))) + +/** + * \brief Timer register map structure + * + */ +struct timer_cmsdk_reg_map_t { + volatile uint32_t ctrl; /* Offset: 0x000 (R/W) control register */ + volatile uint32_t value; /* Offset: 0x004 (R/W) current value register */ + volatile uint32_t reload; /* Offset: 0x008 (R/W) reload value register */ + union { + volatile uint32_t intstatus; /* Offset: 0x00C (R/ ) interrupt + * status register */ + volatile uint32_t intclear; /* Offset: 0x00C ( /W) interrupt + * clear register */ + }intreg; +}; + +/** + * \brief CTRL register bit definitions + * + */ +enum ctrl_reg_bits_t{ + CTRL_REG_ENUM_ENABLE_INDEX = 0, + CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX = 1, + CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX = 2, + CTRL_REG_ENUM_IRQ_ENABLE_INDEX = 3 +}; + +/** + * \brief INTSTATUS/INTCLEAR register bit definitions + * + */ +enum interrupt_reg_bits_t{ + INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX = 0 +}; + +void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + + if (dev->data->is_initialized == 0) { + register_map->ctrl = 0; + register_map->reload = TIMER_CMSDK_DEFAULT_RELOAD; + dev->data->is_initialized = 1; + } +} + +bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev) +{ + return dev->data->is_initialized; +} + +void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX); +} + +void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX); +} + +bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->ctrl, + CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX); +} + +void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX); +} + +void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX); +} + +bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->ctrl, + CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX); +} + +void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX); +} + +void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX); +} + +bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX); +} + +void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX); +} + +void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX); +} + +bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX); +} + +bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->intreg.intstatus, + INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX); +} + +void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->intreg.intclear, + INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX); +} + +uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return register_map->value; +} + +void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev, + uint32_t reload) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + register_map->reload = reload; +} + +void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + register_map->value = register_map->reload; +} + +uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return register_map->reload; +} + +uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return register_map->reload - register_map->value; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/timer_cmsdk_drv.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/timer_cmsdk_drv.h new file mode 100644 index 0000000000..6f5108b860 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/drivers/timer_cmsdk_drv.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file timer_cmsdk_drv.h + * \brief Generic driver for CMSDK APB Timers. + * The timer is a 32-bit down-counter with the following features: + * - optional programmable external clock source + * - programmable interrupt source, triggered if counter reaches 0 + * - automatic reload if counter reaches 0 + */ + +#ifndef __TIMER_CMSDK_DRV_H__ +#define __TIMER_CMSDK_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Maximum reload value */ +#define TIMER_CMSDK_MAX_RELOAD UINT32_MAX /* max of 32-bit */ +#define TIMER_CMSDK_DEFAULT_RELOAD TIMER_CMSDK_MAX_RELOAD + +/** CMSDK timer device configuration structure */ +struct timer_cmsdk_dev_cfg_t { + const uintptr_t base; /*!< Timer base address */ +}; + +/** CMSDK timer device data structure */ +struct timer_cmsdk_dev_data_t { + bool is_initialized; /*!< Indicates if the timer is initialized */ +}; + +/* CMSDK timer device structure */ +struct timer_cmsdk_dev_t { + const struct timer_cmsdk_dev_cfg_t* const cfg; /*!< Timer configuration */ + struct timer_cmsdk_dev_data_t* const data; /*!< Timer data */ +}; + +/** + * \brief Initializes timer to a known default state, which is: + * - timer disabled + * - timer interrupt disabled + * - clock source set to internal + * - external input disabled + * - reload value maxed out + * Init should be called prior to any other process and + * it's the caller's responsibility to follow proper call order. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if a timer is initialized. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if initialized, false otherwise + */ +bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Enables external input, which could be used as clock source + * by calling \ref timer_cmsdk_set_clock_to_external. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Disables external input. + * Make sure if the timer is explicitly wanted to be stopped or set + * the clock source to internal by \ref timer_cmsdk_set_clock_to_internal. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if external input is enabled. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if enabled, false otherwise + */ +bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Sets the clock source to internal. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Sets the clock source to external. + * Make sure external input is enabled correspondingly + * by \ref timer_cmsdk_enable_external_input. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if clock source is external input. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if external, false if internal + */ +bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Enables timer operation. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Disables the given hardware timer. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if a timer is enabled. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if enabled, false otherwise + */ +bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Enables timer interrupt. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Disables timer interrupt. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if a timer interrupt is enabled. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if enabled, false otherwise + */ +bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Gets timer interrupt status + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * * \return true if active, false otherwise + */ +bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Clears timer interrupt + * The interrupt request is held until it is cleared. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Reads timer current value. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return Timer value + */ +uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Sets the reload value of the selected timer. + * + * New reload value takes effect when: + * - timer is restarted + * - on timer underflow + * - when timer_cmsdk_reset is called + * + * \note In r1p0 technical reference manual it's incorrectly stated + * writing the reload value automatically sets the current value also. + * r1p1 technical reference manual includes the fix. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * \param[in] reload Timer reload value to set. + * This is the start value of the 32-bit down counter, + * which automatically reloaded if 0 is reached. + */ +void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev, + uint32_t reload); + +/** + * \brief Resets the timer counter to the reload value instantly + * (i.e. without waiting for underflow). + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Gets the reload value of the selected timer. + * This is the start value of the 32-bit down counter, + * which is automatically reloaded if 0 is reached by the counter. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return Reload value of the selected timer. + */ +uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Reads the number of ticks elapsed in the current cycle. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return Get elapsed number of ticks since last reload was set. + * Elapsed = (Reload value - Current value) + */ +uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev); + +#ifdef __cplusplus +} +#endif +#endif /* __TIMER_CMSDK_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_regs.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_regs.h new file mode 100644 index 0000000000..e2cd1ac602 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_regs.h @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ARM_LTD_MUSCA_REGS_H__ +#define __ARM_LTD_MUSCA_REGS_H__ + +#include +#include "platform_retarget.h" + +/* sysinfo memory mapped register access structure */ +struct sysinfo_t { + volatile uint32_t sysversion; /* (R/ ) System version */ + volatile uint32_t sysconfig; /* (R/ ) System configuration */ + volatile uint32_t reserved0[1008]; + volatile uint32_t pidr4; /* (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved1[3]; + volatile uint32_t pidr0; /* (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* (R/ ) Component ID 3 */ +}; + +/* Secure System Control (SYSCTRL) Alias */ +#define CMSDK_SYSCTRL_BASE_S MUSCA_SYSTEM_CTRL_S_BASE + +/* sysctrl memory mapped register access structure */ +struct sysctrl_t { + volatile uint32_t secdbgstat; /* (R/ ) Secure Debug Configuration + * Status Register*/ + volatile uint32_t secdbgset; /* ( /W) Secure Debug Configuration + * Set Register */ + volatile uint32_t secdbgclr; /* ( /W) Secure Debug Configuration + * Clear Register */ + volatile uint32_t scsecctrl; /* (R/W) System Control Security + * Control Register */ + volatile uint32_t fclk_div; /* (R/W) Fast Clock Divider + * Configuration Register */ + volatile uint32_t sysclk_div; /* (R/W) System Clock Divider + * Configuration Register */ + volatile uint32_t clockforce; /* (R/W) Clock Forces */ + volatile uint32_t reserved0[57]; + volatile uint32_t resetsyndrome; /* (R/W) Reset syndrome */ + volatile uint32_t resetmask; /* (R/W) Reset MASK */ + volatile uint32_t swreset; /* ( /W) Software Reset */ + volatile uint32_t gretreg; /* (R/W) General Purpose Retention + * Register */ + volatile uint32_t initsvtor0; /* (R/W) Initial Secure Reset Vector + * Register For CPU 0 */ + volatile uint32_t initsvtor1; /* (R/W) Initial Secure Reset + * Vector Register For CPU 1*/ + volatile uint32_t cpuwait; /* (R/W) CPU Boot wait control + * after reset */ + volatile uint32_t reserved1; + volatile uint32_t wicctrl; /* (R/W) CPU WIC Request and + * Acknowledgement */ + volatile uint32_t ewctrl; /* (R/W) External Wakeup Control */ + volatile uint32_t reserved2[54]; + volatile uint32_t pdcm_pd_sys_sense; /* (R/W) Power Control Dependency + * Matrix PD_SYS + * Power Domain Sensitivity.*/ + volatile uint32_t pdcm_pd_cpu0core_sense; /* (R/W) Power Control Dependency + * Matrix PD_CPU0CORE + * Power Domain Sensitivity.*/ + volatile uint32_t pdcm_pd_cpu1core_sense; /* (R/W) Power Control Dependency + * Matrix PD_CPU1CORE + * Power Domain Sensitivity.*/ + volatile uint32_t pdcm_pd_sram0_sense; /* (R/W) Power Control Dependency + * Matrix PD_SRAM0 Power + * Domain Sensitivity.*/ + volatile uint32_t pdcm_pd_sram1_sense; /* (R/W) Power Control Dependency + * Matrix PD_SRAM1 Power + * Domain Sensitivity.*/ + volatile uint32_t pdcm_pd_sram2_sense; /* (R/W) Power Control Dependency + * Matrix PD_SRAM2 Power + * Domain Sensitivity.*/ + volatile uint32_t pdcm_pd_sram3_sense; /* (R/W) Power Control Dependency + * Matrix PD_SRAM3 Power + * Domain Sensitivity.*/ + volatile uint32_t reserved3[5]; + volatile uint32_t pdcm_pd_cc_sense; /* (R/W) Power Control Dependency + * Matrix PD_CC + * Power Domain Sensitivity.*/ + volatile uint32_t pdcm_pd_exp0_out_sense; /* (R/W) Power Control Dependency + * Matrix PD_EXP0 Sensitivity. */ + volatile uint32_t pdcm_pd_exp1_out_sense; /* (R/W) Power Control Dependency + * Matrix PD_EXP1 Sensitivity. */ + volatile uint32_t pdcm_pd_exp2_out_sense; /* (R/W) Power Control Dependency + * Matrix PD_EXP2 Sensitivity. */ + volatile uint32_t pdcm_pd_exp3_out_sense; /* (R/W) Power Control Dependency + * Matrix PD_EXP3 Sensitivity. */ + volatile uint32_t reserved4[864]; + volatile uint32_t pidr4; /* (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved5[3]; + volatile uint32_t pidr0; /* (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* (R/ ) Component ID 3 */ +}; + +/* Secure Privilege Control */ +#define CMSDK_SPCTRL ((struct spctrl_def*)MUSCA_SPCTRL_S_BASE) + +/* SPCTRL memory mapped register access structure */ +struct spctrl_def { + volatile uint32_t spcsecctrl; /* (R/W) Secure Configuration Control + Register */ + volatile uint32_t buswait; /* (R/W) Bus Access wait control after reset.*/ + volatile uint32_t reserved[2]; + volatile uint32_t secrespcfg; /* (R/W) Security Violation Response + * Configuration register.*/ + volatile uint32_t nsccfg; /* (R/W) Non Secure Callable Configuration + * for IDAU. */ + volatile uint32_t reserved2; + volatile uint32_t secmpcintstat; /* (R/W) Secure MPC Interrupt Status. */ + volatile uint32_t secppcintstat; /* (R/W) Secure PPC Interrupt Status. */ + volatile uint32_t secppcintclr; /* (R/W) Secure PPC Interrupt Clear. */ + volatile uint32_t secppcinten; /* (R/W) Secure PPC Interrupt Enable. */ + volatile uint32_t reserved3; + volatile uint32_t secmscintstat; /* (R/W) Secure MSC Interrupt Status. */ + volatile uint32_t secmscintclr; /* (R/W) Secure MSC Interrupt Clear. */ + volatile uint32_t secmscinten; /* (R/W) Secure MSC Interrupt Enable. */ + volatile uint32_t reserved4; + volatile uint32_t brgintstat; /* (R/W) Bridge Buffer Error Interrupt Status. */ + volatile uint32_t brgintclr; /* (R/W) Bridge Buffer Error Interrupt Clear. */ + volatile uint32_t brginten; /* (R/W) Bridge Buffer Error Interrupt Enable. */ + volatile uint32_t reserved5; + volatile uint32_t ahbnsppc0; /* (R/W) Non-Secure Access AHB slave Peripheral + * Protection Control #0 */ + volatile uint32_t reserved6[3]; + volatile uint32_t ahbnsppcexp0; /* (R/W) Expansion 0 Non_Secure Access AHB slave + * Peripheral Protection Control */ + volatile uint32_t ahbnsppcexp1; /* (R/W) Expansion 1 Non_Secure Access AHB slave + * Peripheral Protection Control */ + volatile uint32_t ahbnsppcexp2; /* (R/W) Expansion 2 Non_Secure Access AHB slave + * Peripheral Protection Control */ + volatile uint32_t ahbnsppcexp3; /* (R/W) Expansion 3 Non_Secure Access AHB slave + * Peripheral Protection Control */ + volatile uint32_t apbnsppc0; /* (R/W) Non-Secure Access APB slave Peripheral + * Protection Control #0 */ + volatile uint32_t apbnsppc1; /* (R/W) Non-Secure Access APB slave Peripheral + * Protection Control #1 */ + volatile uint32_t reserved7[2]; + volatile uint32_t apbnsppcexp0; /* (R/W) Expansion 0 Non_Secure Access APB slave + * Peripheral Protection Control */ + volatile uint32_t apbnsppcexp1; /* (R/W) Expansion 1 Non_Secure Access APB slave + * Peripheral Protection Control */ + volatile uint32_t apbnsppcexp2; /* (R/W) Expansion 2 Non_Secure Access APB slave + * Peripheral Protection Control */ + volatile uint32_t apbnsppcexp3; /* (R/W) Expansion 3 Non_Secure Access APB slave + * Peripheral Protection Control */ + volatile uint32_t ahbspppc0; /* (R/W) Secure Unprivileged Access AHB slave + * Peripheral Protection Control #0. */ + volatile uint32_t reserved8[3]; + volatile uint32_t ahbspppcexp0; /* (R/W) Expansion 0 Secure Unprivileged Access + * AHB slave Peripheral Protection Control. */ + volatile uint32_t ahbspppcexp1; /* (R/W) Expansion 1 Secure Unprivileged Access + * AHB slave Peripheral Protection Control. */ + volatile uint32_t ahbspppcexp2; /* (R/W) Expansion 2 Secure Unprivileged Access + * AHB slave Peripheral Protection Control. */ + volatile uint32_t ahbspppcexp3; /* (R/W) Expansion 3 Secure Unprivileged Access + * AHB slave Peripheral Protection Control. */ + volatile uint32_t apbspppc0; /* (R/W) Secure Unprivileged Access APB slave + * Peripheral Protection Control #0 */ + volatile uint32_t apbspppc1; /* (R/W) Secure Unprivileged Access APB slave + * Peripheral Protection Control #1 */ + volatile uint32_t reserved9[2]; + volatile uint32_t apbspppcexp0; /* (R/W) Expansion 0 Secure Unprivileged Access + * APB slave Peripheral Protection Control */ + volatile uint32_t apbspppcexp1; /* (R/W) Expansion 1 Secure Unprivileged Access + * APB slave Peripheral Protection Control */ + volatile uint32_t apbspppcexp2; /* (R/W) Expansion 2 Secure Unprivileged Access + * APB slave Peripheral Protection Control */ + volatile uint32_t apbspppcexp3; /* (R/W) Expansion 3 Secure Unprivileged Access + * APB slave Peripheral Protection Control */ + volatile uint32_t nsmscexp; /* (R/W) Expansion MSC Non-Secure Configuration */ + volatile uint32_t reserved10[959]; + volatile uint32_t pid4; /* (R/W) Peripheral ID 4 */ + volatile uint32_t pid5; /* (R/W) Peripheral ID 5 */ + volatile uint32_t pid6; /* (R/W) Peripheral ID 6 */ + volatile uint32_t pid7; /* (R/W) Peripheral ID 7 */ + volatile uint32_t pid0; /* (R/W) Peripheral ID 0 */ + volatile uint32_t pid1; /* (R/W) Peripheral ID 1 */ + volatile uint32_t pid2; /* (R/W) Peripheral ID 2 */ + volatile uint32_t pid3; /* (R/W) Peripheral ID 3 */ + volatile uint32_t cid0; /* (R/W) Component ID 0 */ + volatile uint32_t cid1; /* (R/W) Component ID 1 */ + volatile uint32_t cid2; /* (R/W) Component ID 2 */ + volatile uint32_t cid3; /* (R/W) Component ID 3 */ +}; + +/* Secure PPC interrupt position mask */ +#define CMSDK_APB_PPC0_INT_POS_MASK (1UL << 0) +#define CMSDK_APB_PPC1_INT_POS_MASK (1UL << 1) +#define CMSDK_APB_PPCEXP0_INT_POS_MASK (1UL << 4) +#define CMSDK_APB_PPCEXP1_INT_POS_MASK (1UL << 5) +#define CMSDK_APB_PPCEXP2_INT_POS_MASK (1UL << 6) +#define CMSDK_APB_PPCEXP3_INT_POS_MASK (1UL << 7) +#define CMSDK_AHB_PPCEXP0_INT_POS_MASK (1UL << 20) +#define CMSDK_AHB_PPCEXP1_INT_POS_MASK (1UL << 21) +#define CMSDK_AHB_PPCEXP2_INT_POS_MASK (1UL << 22) +#define CMSDK_AHB_PPCEXP3_INT_POS_MASK (1UL << 23) + +/* Non-Secure Privilege Control */ +#define CMSDK_NSPCTRL ((struct nspctrl_def*)MUSCA_NSPCTRL_NS_BASE) + +/* NSPCTRL memory mapped register access structure */ +struct nspctrl_def { + volatile uint32_t reserved[36]; + volatile uint32_t ahbnspppc0; /* (R/W) Non-Secure Unprivileged Access AHB slave + * Peripheral Protection Control #0 */ + volatile uint32_t reserved3[3]; + volatile uint32_t ahbnspppcexp0; /* (R/W) Expansion 0 Non-Secure Unprivileged Access + * AHB slave Peripheral Protection Control */ + volatile uint32_t ahbnspppcexp1; /* (R/W) Expansion 1 Non-Secure Unprivileged Access + * AHB slave Peripheral Protection Control */ + volatile uint32_t ahbnspppcexp2; /* (R/W) Expansion 2 Non-Secure Unprivileged Access + * AHB slave Peripheral Protection Control */ + volatile uint32_t ahbnspppcexp3; /* (R/W) Expansion 3 Non-Secure Unprivileged Access + * AHB slave Peripheral Protection Control */ + volatile uint32_t apbnspppc0; /* (R/W) Non-Secure Unprivileged Access APB slave + * Peripheral Protection Control #0 */ + volatile uint32_t apbnspppc1; /* (R/W) Non-Secure Unprivileged Access APB slave + * Peripheral Protection Control #1 */ + volatile uint32_t reserved4[2]; + volatile uint32_t apbnspppcexp0; /* (R/W) Expansion 0 Non-Secure Unprivileged Access + * APB slave Peripheral Protection Control */ + volatile uint32_t apbnspppcexp1; /* (R/W) Expansion 1 Non-Secure Unprivileged Access + * APB slave Peripheral Protection Control */ + volatile uint32_t apbnspppcexp2; /* (R/W) Expansion 2 Non-Secure Unprivileged Access + * APB slave Peripheral Protection Control */ + volatile uint32_t apbnspppcexp3; /* (R/W) Expansion 3 Non-Secure Unprivileged Access + * APB slave Peripheral Protection Control */ + volatile uint32_t reserved5[960]; + volatile uint32_t pidr4; /* (R/W) Peripheral ID 3 */ + volatile uint32_t reserved7; + volatile uint32_t reserved8; + volatile uint32_t reserved9; + volatile uint32_t pidr0; /* (R/W) Peripheral ID 0 */ + volatile uint32_t pidr1; /* (R/W) Peripheral ID 1 */ + volatile uint32_t pidr2; /* (R/W) Peripheral ID 2 */ + volatile uint32_t pidr3; /* (R/W) Peripheral ID 3 */ + volatile uint32_t cidr0; /* (R/W) Component ID 0 */ + volatile uint32_t cidr2; /* (R/W) Component ID 1 */ + volatile uint32_t cidr1; /* (R/W) Component ID 2 */ + volatile uint32_t cidr3; /* (R/W) Component ID 3 */ +}; + +/* ARM APB PPC0 peripherals definition */ +#define CMSDK_TIMER0_APB_PPC_POS 0U +#define CMSDK_TIMER1_APB_PPC_POS 1U +#define CMSDK_DTIMER_APB_PPC_POS 2U +#define CMSDK_MHU0_APB_PPC_POS 3U +#define CMSDK_MHU1_APB_PPC_POS 4U +/* The bits 31:5 are reserved */ +/* End ARM APB PPC0 peripherals definition */ + +/* ARM APB PPC1 peripherals definition */ +#define CMSDK_S32K_TIMER_PPC_POS 0U +/* The bits 31:1 are reserved */ +/* End ARM APB PPC1 peripherals definition */ + +/* ARM AHB PPC0 peripherals definition */ +/* The bits 31:0 are reserved */ +/* End of ARM AHB PPC0 peripherals definition */ + +/* ARM AHB PPCEXP0 peripherals definition */ +#define MUSCA_PERIPHS_AHB_PPC_POS 0U +/* The bits 31:1 are reserved */ +/* End of ARM AHB PPCEXP0 peripherals definition */ + +/* ARM AHB PPCEXP1 peripherals definition */ +/* The bits 31:0 are reserved */ +/* End of ARM AHB PPCEXP1 peripherals definition */ + +/* ARM AHB PPCEXP2 peripherals definition */ +/* The bits 31:0 are reserved */ +/* End of ARM AHB PPCEXP2 peripherals definition */ + +/* ARM AHB PPCEXP3 peripherals definition */ +/* The bits 31:0 are reserved */ + +/* End of ARM AHB PPCEXP3 peripherals definition */ + +#endif /* __ARM_LTD_MUSCA_REGS_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget.h new file mode 100644 index 0000000000..979929e9d3 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file platform_retarget.h + * \brief This file defines all the peripheral base addresses for Musca platform. + */ + +#ifndef __ARM_LTD_MUSCA_RETARGET_H__ +#define __ARM_LTD_MUSCA_RETARGET_H__ + +#include "platform_regs.h" /* Platform registers */ +#include "system_cmsdk_musca.h" + + +/* SRAM MPC ranges and limits */ +/* Internal memory */ +#define MPC_ISRAM0_RANGE_BASE_NS 0x20000000 +#define MPC_ISRAM0_RANGE_LIMIT_NS 0x20007FFF +#define MPC_ISRAM0_RANGE_BASE_S 0x30000000 +#define MPC_ISRAM0_RANGE_LIMIT_S 0x30007FFF + +#define MPC_ISRAM1_RANGE_BASE_NS 0x20008000 +#define MPC_ISRAM1_RANGE_LIMIT_NS 0x2000FFFF +#define MPC_ISRAM1_RANGE_BASE_S 0x30008000 +#define MPC_ISRAM1_RANGE_LIMIT_S 0x3000FFFF + +#define MPC_ISRAM2_RANGE_BASE_NS 0x20010000 +#define MPC_ISRAM2_RANGE_LIMIT_NS 0x20017FFF +#define MPC_ISRAM2_RANGE_BASE_S 0x30010000 +#define MPC_ISRAM2_RANGE_LIMIT_S 0x30017FFF + +#define MPC_ISRAM3_RANGE_BASE_NS 0x20018000 +#define MPC_ISRAM3_RANGE_LIMIT_NS 0x2001FFFF +#define MPC_ISRAM3_RANGE_BASE_S 0x30018000 +#define MPC_ISRAM3_RANGE_LIMIT_S 0x3001FFFF + +/* Code SRAM memory */ +#define MPC_CODE_SRAM_RANGE_BASE_NS (0x00000000) +#define MPC_CODE_SRAM_RANGE_LIMIT_NS (0x00200000) +#define MPC_CODE_SRAM_RANGE_BASE_S (0x10000000) +#define MPC_CODE_SRAM_RANGE_LIMIT_S (0x10200000) + +/* QSPI Flash memory */ +#define MPC_QSPI_RANGE_BASE_NS (0x00200000) +#define MPC_QSPI_RANGE_LIMIT_NS (0x00240000) +#define MPC_QSPI_RANGE_BASE_S (0x10200000) +#define MPC_QSPI_RANGE_LIMIT_S (0x10240000) + +#endif /* __ARM_LTD_MUSCA_RETARGET_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget_dev.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget_dev.c new file mode 100644 index 0000000000..23d8ecbccd --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget_dev.c @@ -0,0 +1,492 @@ +/* + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file platform_retarget_dev.c + * \brief This file defines exports the structures based on the peripheral + * definitions from device_cfg.h. + * This retarget file is meant to be used as a helper for baremetal + * applications and/or as an example of how to configure the generic + * driver structures. + */ + +#include "platform_retarget_dev.h" +#include "platform_retarget.h" +#include "system_cmsdk_musca.h" + +/* ======= Peripheral configuration structure definitions ======= */ +/* MUSCA A1 SCC driver structures */ +#ifdef MUSCA_A1_SCC_S +static const struct musca_a1_scc_dev_cfg_t MUSCA_A1_SCC_DEV_CFG_S = { + .base = MUSCA_SCC_S_BASE}; +struct musca_a1_scc_dev_t MUSCA_A1_SCC_DEV_S = {&(MUSCA_A1_SCC_DEV_CFG_S)}; +#endif +#ifdef MUSCA_A1_SCC_NS +static const struct musca_a1_scc_dev_cfg_t MUSCA_A1_SCC_DEV_CFG_NS = { + .base = MUSCA_SCC_NS_BASE}; +struct musca_a1_scc_dev_t MUSCA_A1_SCC_DEV_NS = {&(MUSCA_A1_SCC_DEV_CFG_NS)}; +#endif + +/* ARM PPC SSE 200 driver structures */ +#ifdef AHB_PPC0_S +static struct ppc_sse200_dev_cfg_t AHB_PPC0_DEV_CFG_S = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t AHB_PPC0_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t AHB_PPC0_DEV_S = { + &AHB_PPC0_DEV_CFG_S, &AHB_PPC0_DEV_DATA_S }; +#endif + +#ifdef AHB_PPCEXP0_S +static struct ppc_sse200_dev_cfg_t AHB_PPCEXP0_DEV_CFG_S = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t AHB_PPCEXP0_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t AHB_PPCEXP0_DEV_S = { + &AHB_PPCEXP0_DEV_CFG_S, &AHB_PPCEXP0_DEV_DATA_S }; +#endif + +#ifdef AHB_PPCEXP1_S +static struct ppc_sse200_dev_cfg_t AHB_PPCEXP1_DEV_CFG_S = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t AHB_PPCEXP1_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t AHB_PPCEXP1_DEV_S = { + &AHB_PPCEXP1_DEV_CFG_S, &AHB_PPCEXP1_DEV_DATA_S }; +#endif + +#ifdef AHB_PPCEXP2_S +static struct ppc_sse200_dev_cfg_t AHB_PPCEXP2_DEV_CFG_S = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t AHB_PPCEXP2_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t AHB_PPCEXP2_DEV_S = { + &AHB_PPCEXP2_DEV_CFG_S, &AHB_PPCEXP2_DEV_DATA_S }; +#endif + +#ifdef AHB_PPCEXP3_S +static struct ppc_sse200_dev_cfg_t AHB_PPCEXP3_DEV_CFG_S = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t AHB_PPCEXP3_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t AHB_PPCEXP3_DEV_S = { + &AHB_PPCEXP3_DEV_CFG_S, &AHB_PPCEXP3_DEV_DATA_S }; +#endif + +#ifdef APB_PPC0_S +static struct ppc_sse200_dev_cfg_t APB_PPC0_DEV_CFG_S = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t APB_PPC0_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t APB_PPC0_DEV_S = { + &APB_PPC0_DEV_CFG_S, &APB_PPC0_DEV_DATA_S }; +#endif + +#ifdef APB_PPC1_S +static struct ppc_sse200_dev_cfg_t APB_PPC1_DEV_CFG_S = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t APB_PPC1_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t APB_PPC1_DEV_S = { + &APB_PPC1_DEV_CFG_S, &APB_PPC1_DEV_DATA_S}; +#endif + +#ifdef APB_PPCEXP0_S +static struct ppc_sse200_dev_cfg_t APB_PPCEXP0_DEV_CFG_S = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t APB_PPCEXP0_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t APB_PPCEXP0_DEV_S = { + &APB_PPCEXP0_DEV_CFG_S, &APB_PPCEXP0_DEV_DATA_S }; +#endif + +#ifdef APB_PPCEXP1_S +static struct ppc_sse200_dev_cfg_t APB_PPCEXP1_DEV_CFG = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t APB_PPCEXP1_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t APB_PPCEXP1_DEV_S = { + &APB_PPCEXP1_DEV_CFG, &APB_PPCEXP1_DEV_DATA_S }; +#endif + +#ifdef APB_PPCEXP2_S +static struct ppc_sse200_dev_cfg_t APB_PPCEXP2_DEV_CFG = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t APB_PPCEXP2_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t APB_PPCEXP2_DEV_S = { + &APB_PPCEXP2_DEV_CFG, &APB_PPCEXP2_DEV_DATA_S }; +#endif + +#ifdef APB_PPCEXP3_S +static struct ppc_sse200_dev_cfg_t APB_PPCEXP3_DEV_CFG = { + .spctrl_base = MUSCA_SPCTRL_S_BASE, + .nspctrl_base = MUSCA_NSPCTRL_NS_BASE }; +static struct ppc_sse200_dev_data_t APB_PPCEXP3_DEV_DATA_S = { + .p_ns_ppc = 0, + .p_sp_ppc = 0, + .p_nsp_ppc = 0, + .int_bit_mask = 0, + .state = 0 }; +struct ppc_sse200_dev_t APB_PPCEXP3_DEV_S = { + &APB_PPCEXP3_DEV_CFG, &APB_PPCEXP3_DEV_DATA_S }; +#endif + +/* ARM MPC SIE 200 driver structures */ +#ifdef MPC_ISRAM0_S +static const struct mpc_sie200_dev_cfg_t MPC_ISRAM0_DEV_CFG_S = { + .base = MUSCA_MPC_SRAM0_S_BASE}; +static struct mpc_sie200_dev_data_t MPC_ISRAM0_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .state = 0, + .reserved = 0}; +struct mpc_sie200_dev_t MPC_ISRAM0_DEV_S = { + &(MPC_ISRAM0_DEV_CFG_S), + &(MPC_ISRAM0_DEV_DATA_S)}; +#endif + +#ifdef MPC_ISRAM1_S +static const struct mpc_sie200_dev_cfg_t MPC_ISRAM1_DEV_CFG_S = { + .base = MUSCA_MPC_SRAM1_S_BASE}; +static struct mpc_sie200_dev_data_t MPC_ISRAM1_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .state = 0, + .reserved = 0}; +struct mpc_sie200_dev_t MPC_ISRAM1_DEV_S = { + &(MPC_ISRAM1_DEV_CFG_S), + &(MPC_ISRAM1_DEV_DATA_S)}; +#endif + +#ifdef MPC_ISRAM2_S +static const struct mpc_sie200_dev_cfg_t MPC_ISRAM2_DEV_CFG_S = { + .base = MUSCA_MPC_SRAM2_S_BASE}; +static struct mpc_sie200_dev_data_t MPC_ISRAM2_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .state = 0, + .reserved = 0}; +struct mpc_sie200_dev_t MPC_ISRAM2_DEV_S = { + &(MPC_ISRAM2_DEV_CFG_S), + &(MPC_ISRAM2_DEV_DATA_S)}; +#endif + +#ifdef MPC_ISRAM3_S +static const struct mpc_sie200_dev_cfg_t MPC_ISRAM3_DEV_CFG_S = { + .base = MUSCA_MPC_SRAM3_S_BASE}; +static struct mpc_sie200_dev_data_t MPC_ISRAM3_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .state = 0, + .reserved = 0}; +struct mpc_sie200_dev_t MPC_ISRAM3_DEV_S = { + &(MPC_ISRAM3_DEV_CFG_S), + &(MPC_ISRAM3_DEV_DATA_S)}; +#endif + +#ifdef MPC_CODE_SRAM_NS +static const struct mpc_sie200_dev_cfg_t MPC_CODE_SRAM_DEV_CFG_NS = { + .base = MUSCA_CODE_SRAM_MPC_NS_BASE}; +static struct mpc_sie200_dev_data_t MPC_CODE_SRAM_DEV_DATA_NS = { + .range_list = 0, + .nbr_of_ranges = 0, + .state = 0, + .reserved = 0}; +struct mpc_sie200_dev_t MPC_CODE_SRAM_DEV_NS = { + &(MPC_CODE_SRAM_DEV_CFG_NS), + &(MPC_CODE_SRAM_DEV_DATA_NS)}; +#endif + +#ifdef MPC_CODE_SRAM_S +static const struct mpc_sie200_dev_cfg_t MPC_CODE_SRAM_DEV_CFG_S = { + .base = MUSCA_CODE_SRAM_MPC_S_BASE}; +static struct mpc_sie200_dev_data_t MPC_CODE_SRAM_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .state = 0, + .reserved = 0}; +struct mpc_sie200_dev_t MPC_CODE_SRAM_DEV_S = { + &(MPC_CODE_SRAM_DEV_CFG_S), + &(MPC_CODE_SRAM_DEV_DATA_S)}; +#endif + +#ifdef MPC_QSPI_S +static const struct mpc_sie200_dev_cfg_t MPC_QSPI_DEV_CFG_S = { + .base = MUSCA_QSPI_MPC_S_BASE}; +static struct mpc_sie200_dev_data_t MPC_QSPI_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .state = 0, + .reserved = 0}; +struct mpc_sie200_dev_t MPC_QSPI_DEV_S = { + &(MPC_QSPI_DEV_CFG_S), + &(MPC_QSPI_DEV_DATA_S)}; +#endif + +#ifdef MPC_QSPI_NS +static const struct mpc_sie200_dev_cfg_t MPC_QSPI_DEV_CFG_NS = { + .base = MUSCA_QSPI_MPC_NS_BASE}; +static struct mpc_sie200_dev_data_t MPC_QSPI_DEV_DATA_NS = { + .range_list = 0, + .nbr_of_ranges = 0, + .state = 0, + .reserved = 0}; +struct mpc_sie200_dev_t MPC_QSPI_DEV_NS = { + &(MPC_QSPI_DEV_CFG_NS), + &(MPC_QSPI_DEV_DATA_NS)}; +#endif + +/* CMSDK Timers driver structures */ +#ifdef CMSDK_TIMER0_S +static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S = { + .base = MUSCA_CMSDK_TIMER0_S_BASE}; +static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_S = { + .is_initialized = 0}; +struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S = {&(CMSDK_TIMER0_DEV_CFG_S), + &(CMSDK_TIMER0_DEV_DATA_S)}; +#endif +#ifdef CMSDK_TIMER0_NS +static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_NS = { + .base = MUSCA_CMSDK_TIMER0_NS_BASE}; +static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_NS = { + .is_initialized = 0}; +struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_NS = {&(CMSDK_TIMER0_DEV_CFG_NS), + &(CMSDK_TIMER0_DEV_DATA_NS)}; +#endif + +#ifdef CMSDK_TIMER1_S +static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER1_DEV_CFG_S = { + .base = MUSCA_CMSDK_TIMER1_S_BASE}; +static struct timer_cmsdk_dev_data_t CMSDK_TIMER1_DEV_DATA_S = { + .is_initialized = 0}; +struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV_S = {&(CMSDK_TIMER1_DEV_CFG_S), + &(CMSDK_TIMER1_DEV_DATA_S)}; +#endif +#ifdef CMSDK_TIMER1_NS +static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER1_DEV_CFG_NS = { + .base = MUSCA_CMSDK_TIMER1_NS_BASE}; +static struct timer_cmsdk_dev_data_t CMSDK_TIMER1_DEV_DATA_NS = { + .is_initialized = 0}; +struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV_NS = {&(CMSDK_TIMER1_DEV_CFG_NS), + &(CMSDK_TIMER1_DEV_DATA_NS)}; +#endif + +/* General-Purpose Timer driver structures */ +#ifdef GP_TIMER_S +static const struct timer_gp_dev_cfg_t GP_TIMER_DEV_CFG_S = { + .base = MUSCA_TIMER_S_BASE}; +static struct timer_gp_dev_data_t GP_TIMER_DEV_DATA_S = { + .is_initialized = false, + .alarm0_init = 0, + .alarm1_init = 0}; +struct timer_gp_dev_t GP_TIMER_DEV_S = { + &(GP_TIMER_DEV_CFG_S), + &(GP_TIMER_DEV_DATA_S)}; +#endif + +#ifdef GP_TIMER_NS +static const struct timer_gp_dev_cfg_t GP_TIMER_DEV_CFG_NS = { + .base = MUSCA_TIMER_NS_BASE}; +static struct timer_gp_dev_data_t GP_TIMER_DEV_DATA_NS = { + .is_initialized = false, + .alarm0_init = 0, + .alarm1_init = 0}; +struct timer_gp_dev_t GP_TIMER_DEV_NS = { + &(GP_TIMER_DEV_CFG_NS), + &(GP_TIMER_DEV_DATA_NS)}; +#endif + +/* ARM UART PL011 driver structures */ +#ifdef UART0_PL011_S +static const struct uart_pl011_dev_cfg_t UART0_PL011_DEV_CFG_S = { + .base = MUSCA_UART0_S_BASE, + .def_baudrate = 115200, + .def_wlen = UART_PL011_WLEN_8, + .def_parity = UART_PL011_PARITY_DISABLED, + .def_stopbit = UART_PL011_STOPBIT_1}; +static struct uart_pl011_dev_data_t UART0_PL011_DEV_DATA_S = { + .state = 0, + .uart_clk = 0, + .baudrate = 0}; +struct uart_pl011_dev_t UART0_PL011_DEV_S = {&(UART0_PL011_DEV_CFG_S), + &(UART0_PL011_DEV_DATA_S)}; +#endif + +#ifdef UART0_PL011_NS +static const struct uart_pl011_dev_cfg_t UART0_PL011_DEV_CFG_NS = { + .base = MUSCA_UART0_NS_BASE, + .def_baudrate = 115200, + .def_wlen = UART_PL011_WLEN_8, + .def_parity = UART_PL011_PARITY_DISABLED, + .def_stopbit = UART_PL011_STOPBIT_1}; +static struct uart_pl011_dev_data_t UART0_PL011_DEV_DATA_NS = { + .state = 0, + .uart_clk = 0, + .baudrate = 0}; +struct uart_pl011_dev_t UART0_PL011_DEV_NS = {&(UART0_PL011_DEV_CFG_NS), + &(UART0_PL011_DEV_DATA_NS)}; +#endif + +#ifdef UART1_PL011_S +static const struct uart_pl011_dev_cfg_t UART1_PL011_DEV_CFG_S = { + .base = MUSCA_UART1_S_BASE, + .def_baudrate = 115200, + .def_wlen = UART_PL011_WLEN_8, + .def_parity = UART_PL011_PARITY_DISABLED, + .def_stopbit = UART_PL011_STOPBIT_1}; +static struct uart_pl011_dev_data_t UART1_PL011_DEV_DATA_S = { + .state = 0, + .uart_clk = 0, + .baudrate = 0}; +struct uart_pl011_dev_t UART1_PL011_DEV_S = {&(UART1_PL011_DEV_CFG_S), + &(UART1_PL011_DEV_DATA_S)}; +#endif + +#ifdef UART1_PL011_NS +static const struct uart_pl011_dev_cfg_t UART1_PL011_DEV_CFG_NS = { + .base = MUSCA_UART1_NS_BASE, + .def_baudrate = 115200, + .def_wlen = UART_PL011_WLEN_8, + .def_parity = UART_PL011_PARITY_DISABLED, + .def_stopbit = UART_PL011_STOPBIT_1}; +static struct uart_pl011_dev_data_t UART1_PL011_DEV_DATA_NS = { + .state = 0, + .uart_clk = 0, + .baudrate = 0}; +struct uart_pl011_dev_t UART1_PL011_DEV_NS = {&(UART1_PL011_DEV_CFG_NS), + &(UART1_PL011_DEV_DATA_NS)}; +#endif + +/* QSPI IP6514E driver structures */ +#ifdef QSPI_IP6514E_S +static const struct qspi_ip6514e_dev_cfg_t QSPI_DEV_CFG_S = { + .base = MUSCA_QSPI_REG_S_BASE, + /* + * On Musca-A1, only the 18 first address bits are used for any AHB + * address in a request coming to the QSPI Flash controller. + * It means that direct accesses are limited to the first 256 KiB of the + * Flash memory (if the Remap register is not used) and that the Indirect + * Trigger zone needs to be inside the first 256 KiB as well. + */ + .addr_mask = (1U << 18) - 1, /* 256 KiB minus 1 byte */ +}; +struct qspi_ip6514e_dev_t QSPI_DEV_S = { + &QSPI_DEV_CFG_S +}; +#endif + +#ifdef QSPI_IP6514E_NS +static const struct qspi_ip6514e_dev_cfg_t QSPI_DEV_CFG_NS = { + .base = MUSCA_QSPI_REG_NS_BASE, + /* + * On Musca-A1, only the 18 first address bits are used for any AHB + * address in a request coming to the QSPI Flash controller. + * It means that direct accesses are limited to the first 256 KiB of the + * Flash memory (if the Remap register is not used) and that the Indirect + * Trigger zone needs to be inside the first 256 KiB as well. + */ + .addr_mask = (1U << 18) - 1, /* 256 KiB minus 1 byte */ +}; +struct qspi_ip6514e_dev_t QSPI_DEV_NS = { + &QSPI_DEV_CFG_NS +}; +#endif + +/* ======= External peripheral configuration structure definitions ======= */ + +/* MT25QL Flash memory library structures */ +#if (defined(MT25QL_S) && defined(QSPI_IP6514E_S)) +struct mt25ql_dev_t MT25QL_DEV_S = { + .controller = &QSPI_DEV_S, + .direct_access_start_addr = MUSCA_QSPI_FLASH_S_BASE, + .baud_rate_div = 4U, + /* + * 8 MiB flash memory are advertised in the Arm Musca-A Test Chip and Board + * Technical Reference Manual. The MT25QL Flash device may however contain + * more. + */ + .size = 0x00800000U, /* 8 MiB */ + .func_state = MT25QL_FUNC_STATE_DEFAULT, +}; +#endif + +#if (defined(MT25QL_NS) && defined(QSPI_IP6514E_NS)) +struct mt25ql_dev_t MT25QL_DEV_NS = { + .controller = &QSPI_DEV_NS, + .direct_access_start_addr = MUSCA_QSPI_FLASH_NS_BASE, + .baud_rate_div = 4U, + /* + * 8 MiB flash memory are advertised in the Arm Musca-A Test Chip and Board + * Technical Reference Manual. The MT25QL Flash device may however contain + * more. + */ + .size = 0x00800000U, /* 8 MiB */ + .func_state = MT25QL_FUNC_STATE_DEFAULT, +}; +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget_dev.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget_dev.h new file mode 100644 index 0000000000..744e09ea43 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget_dev.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file platform_retarget_dev.h + * \brief The structure definitions in this file are exported based on the peripheral + * definitions from device_cfg.h. + * This retarget file is meant to be used as a helper for baremetal + * applications and/or as an example of how to configure the generic + * driver structures. + */ + +#ifndef __ARM_LTD_MUSCA_A1_RETARGET_DEV_H__ +#define __ARM_LTD_MUSCA_A1_RETARGET_DEV_H__ + +#include "device_cfg.h" + +/* ======= Peripheral configuration structure declarations ======= */ + +/* ARM SCC driver structures */ +#ifdef MUSCA_A1_SCC_S +#include "musca_a1_scc_drv.h" +extern struct musca_a1_scc_dev_t MUSCA_A1_SCC_DEV_S; +#endif +#ifdef MUSCA_A1_SCC_NS +#include "musca_a1_scc_drv.h" +extern struct musca_a1_scc_dev_t MUSCA_A1_SCC_DEV_NS; +#endif + +/* ARM MPC SIE 200 driver structures */ +#ifdef MPC_ISRAM0_S +#include "mpc_sie200_drv.h" +extern struct mpc_sie200_dev_t MPC_ISRAM0_DEV_S; +#endif +#ifdef MPC_ISRAM1_S +#include "mpc_sie200_drv.h" +extern struct mpc_sie200_dev_t MPC_ISRAM1_DEV_S; +#endif +#ifdef MPC_ISRAM2_S +#include "mpc_sie200_drv.h" +extern struct mpc_sie200_dev_t MPC_ISRAM2_DEV_S; +#endif +#ifdef MPC_ISRAM3_S +#include "mpc_sie200_drv.h" +extern struct mpc_sie200_dev_t MPC_ISRAM3_DEV_S; +#endif +#ifdef MPC_CODE_SRAM_S +#include "mpc_sie200_drv.h" +extern struct mpc_sie200_dev_t MPC_CODE_SRAM_DEV_S; +#endif +#ifdef MPC_CODE_SRAM_NS +#include "mpc_sie200_drv.h" +extern struct mpc_sie200_dev_t MPC_CODE_SRAM_DEV_NS; +#endif +#ifdef MPC_QSPI_S +#include "mpc_sie200_drv.h" +extern struct mpc_sie200_dev_t MPC_QSPI_DEV_S; +#endif +#ifdef MPC_QSPI_NS +#include "mpc_sie200_drv.h" +extern struct mpc_sie200_dev_t MPC_QSPI_DEV_NS; +#endif + +/* ARM UART PL011 driver structures */ +#ifdef UART0_PL011_S +#include "uart_pl011_drv.h" +extern struct uart_pl011_dev_t UART0_PL011_DEV_S; +#endif +#ifdef UART0_PL011_NS +#include "uart_pl011_drv.h" +extern struct uart_pl011_dev_t UART0_PL011_DEV_NS; +#endif +#ifdef UART1_PL011_S +#include "uart_pl011_drv.h" +extern struct uart_pl011_dev_t UART1_PL011_DEV_S; +#endif +#ifdef UART1_PL011_NS +#include "uart_pl011_drv.h" +extern struct uart_pl011_dev_t UART1_PL011_DEV_NS; +#endif + +/* CMSDK Timer driver structures */ +#ifdef CMSDK_TIMER0_S +#include "timer_cmsdk_drv.h" +extern struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S; +#endif +#ifdef CMSDK_TIMER0_NS +#include "timer_cmsdk_drv.h" +extern struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_NS; +#endif + +#ifdef CMSDK_TIMER1_S +#include "timer_cmsdk_drv.h" +extern struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV_S; +#endif +#ifdef CMSDK_TIMER1_NS +#include "timer_cmsdk_drv.h" +extern struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV_NS; +#endif + +/* General-Purpose Timer driver structures */ +#ifdef GP_TIMER_S +#include "timer_gp_drv.h" +extern struct timer_gp_dev_t GP_TIMER_DEV_S; +#endif +#ifdef GP_TIMER_NS +#include "timer_gp_drv.h" +extern struct timer_gp_dev_t GP_TIMER_DEV_NS; +#endif + +/* QSPI Flash Controller driver structures */ +#ifdef QSPI_IP6514E_S +#include "qspi_ip6514e_drv.h" +extern struct qspi_ip6514e_dev_t QSPI_DEV_S; +#endif + +#ifdef QSPI_IP6514E_NS +#include "qspi_ip6514e_drv.h" +extern struct qspi_ip6514e_dev_t QSPI_DEV_NS; +#endif + +/* ARM PPC driver structures */ +#ifdef AHB_PPC0_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t AHB_PPC0_DEV_S; +#endif + +#ifdef AHB_PPCEXP0_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t AHB_PPCEXP0_DEV_S; +#endif + +#ifdef AHB_PPCEXP1_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t AHB_PPCEXP1_DEV_S; +#endif + +#ifdef AHB_PPCEXP2_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t AHB_PPCEXP2_DEV_S; +#endif + +#ifdef AHB_PPCEXP3_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t AHB_PPCEXP3_DEV_S; +#endif + +#ifdef APB_PPC0_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t APB_PPC0_DEV_S; +#endif + +#ifdef APB_PPC1_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t APB_PPC1_DEV_S; +#endif + +#ifdef APB_PPCEXP0_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t APB_PPCEXP0_DEV_S; +#endif + +#ifdef APB_PPCEXP1_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t APB_PPCEXP1_DEV_S; +#endif + +#ifdef APB_PPCEXP2_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t APB_PPCEXP2_DEV_S; +#endif + +#ifdef APB_PPCEXP3_S +#include "ppc_sse200_drv.h" +extern struct ppc_sse200_dev_t APB_PPCEXP3_DEV_S; +#endif + +/* ======= External peripheral configuration structure declarations ======= */ + +/* MT25QL Flash memory library structures */ +#if (defined(MT25QL_S) && defined(QSPI_IP6514E_S)) +#include "Libraries/mt25ql_flash_lib.h" +extern struct mt25ql_dev_t MT25QL_DEV_S; +#endif +#if (defined(MT25QL_NS) && defined(QSPI_IP6514E_NS)) +#include "Libraries/mt25ql_flash_lib.h" +extern struct mt25ql_dev_t MT25QL_DEV_NS; +#endif + +#endif /* __ARM_LTD_MUSCA_A1_RETARGET_DEV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget_pins.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget_pins.h new file mode 100644 index 0000000000..b05ccca0c0 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/platform_retarget_pins.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016-2019 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file platform_retarget_pins.h + * \brief This file defines all the pins for this platform. + */ + +#ifndef __ARM_LTD_MUSCA_RETARGET_PINS_H__ +#define __ARM_LTD_MUSCA_RETARGET_PINS_H__ + +/* AHB GPIO pin names */ +enum arm_gpio_pin_name_t { + AHB_GPIO0_0 = 0U, + AHB_GPIO0_1, + AHB_GPIO0_2, + AHB_GPIO0_3, + AHB_GPIO0_4, + AHB_GPIO0_5, + AHB_GPIO0_6, + AHB_GPIO0_7, + AHB_GPIO0_8, + AHB_GPIO0_9, + AHB_GPIO0_10, + AHB_GPIO0_11, + AHB_GPIO0_12, + AHB_GPIO0_13, + AHB_GPIO0_14, + AHB_GPIO0_15, +}; + +#endif /* __ARM_LTD_MUSCA_RETARGET_PINS_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_cmsdk_musca.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_cmsdk_musca.c new file mode 100644 index 0000000000..9d2c3cf1e6 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_cmsdk_musca.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is derivative of CMSIS V5.01 \Device\ARM\ARMCM33\Source\system_ARMCM33.c + * https://github.com/ARM-software/CMSIS_5/tree/5.0.1 + * Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75 + */ + +#include "system_cmsdk_musca.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ +#define XTAL (50000000UL) +#define SYSTEM_CLOCK (XTAL) +#define SYSTEM_REFCLK (32768UL) + +/*---------------------------------------------------------------------------- + Externals + *----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = SYSTEM_CLOCK; +uint32_t RefClock = SYSTEM_REFCLK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = SYSTEM_CLOCK; + RefClock = SYSTEM_REFCLK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + extern uint32_t __Vectors; + SCB->VTOR = (uint32_t) &__Vectors; +#endif + +#if defined (__FPU_USED) && (__FPU_USED == 1U) + SCB->CPACR |= ((3U << 10U*2U) | /* set CP10 Full Access */ + (3U << 11U*2U) ); /* set CP11 Full Access */ +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + SystemCoreClock = SYSTEM_CLOCK; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_cmsdk_musca.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_cmsdk_musca.h new file mode 100644 index 0000000000..33863c139e --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_cmsdk_musca.h @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2017-2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.01 Device\_Template_Vendor\Vendor\Device\Include\Device.h + */ + +#ifndef SYSTEM_CMSDK_MUSCA_H +#define SYSTEM_CMSDK_MUSCA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* =========================================================================================================================== */ +/* ================ Interrupt Number Definition ================ */ +/* =========================================================================================================================== */ + +typedef enum IRQn +{ +/* =========================================== Core Specific Interrupt Numbers ============================================= */ + NonMaskableInt_IRQn = -14, /* -14 Non Maskable Interrupt */ + HardFault_IRQn = -13, /* -13 HardFault Interrupt */ + MemoryManagement_IRQn = -12, /* -12 Memory Management Interrupt */ + BusFault_IRQn = -11, /* -11 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /* -10 Usage Fault Interrupt */ + SecureFault_IRQn = -9, /* -9 Secure Fault Interrupt */ + SVCall_IRQn = -5, /* -5 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /* -4 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /* -2 Pend SV Interrupt */ + SysTick_IRQn = -1, /* -1 System Tick Interrupt */ + +/* ======================================== Musca Specific SSE-200 Interrupt Numbers ====================================== */ + NS_WATCHDOG_RESET_IRQn = 0, /* Non-Secure Watchdog Reset Request Interrupt */ + NS_WATCHDOG_IRQn = 1, /* Non-Secure Watchdog Interrupt */ + S32K_TIMER_IRQn = 2, /* S32K Timer Interrupt */ + TIMER0_IRQn = 3, /* CMSDK Timer 0 Interrupt */ + TIMER1_IRQn = 4, /* CMSDK Timer 1 Interrupt */ + DUALTIMER_IRQn = 5, /* CMSDK Dual Timer Interrupt */ + MHU0_IRQn = 6, /* Message Handling Unit 0 Interrupt */ + MHU1_IRQn = 7, /* Message Handling Unit 1 Interrupt */ + CRYPTOCELL_IRQn = 8, /* CryptoCell-312 Interrupt */ + S_MPC_COMBINED_IRQn = 9, /* Secure Combined MPC Interrupt */ + S_PPC_COMBINED_IRQn = 10, /* Secure Combined PPC Interrupt */ + S_MSC_COMBINED_IRQn = 11, /* Secure Combined MSC Interrupt */ + S_BRIDGE_ERR_IRQn = 12, /* Secure Bridge Error Combined Interrupt */ + I_CACHE_INV_ERR_IRQn = 13, /* Instruction Cache Invalidation Interrupt */ + /* Reserved = 14, Reserved */ + SYS_PPU_IRQn = 15, /* System PPU Interrupt */ + CPU0_PPU_IRQn = 16, /* CPU0 PPU Interrupt */ + CPU1_PPU_IRQn = 17, /* CPU1 PPU Interrupt */ + CPU0_DGB_PPU_IRQn = 18, /* CPU0 Debug PPU Interrupt */ + CPU1_DGB_PPU_IRQn = 19, /* CPU1 Debug PPU Interrupt */ + CRYPTOCELL_PPU_IRQn = 20, /* CryptoCell PPU Interrupt */ + /* Reserved = 21, Reserved */ + RAM0_PPU_IRQn = 22, /* RAM 0 PPU Interrupt */ + RAM1_PPU_IRQn = 23, /* RAM 1 PPU Interrupt */ + RAM2_PPU_IRQn = 24, /* RAM 2 PPU Interrupt */ + RAM3_PPU_IRQn = 25, /* RAM 3 PPU Interrupt */ + DEBUG_PPU_IRQn = 26, /* Debug PPU Interrupt */ + /* Reserved = 27, Reserved */ + CPU0_CTI_IRQn = 28, /* CPU0 CTI Interrupt */ + CPU1_CTI_IRQn = 29, /* CPU1 CTI Interrupt */ + /* Reserved = 30, Reserved */ + /* Reserved = 31, Reserved */ +/* ========================================== Musca Specific Expansion Interrupt Numbers =================================== */ + /* None = 32, Not used. Tied to 0 */ + GpTimer_IRQn = 33, /* General Purpose Timer Interrupt */ + I2C0_IRQn = 34, /* I2C0 Interrupt */ + I2C1_IRQn = 35, /* I2C1 Interrupt */ + I2S_IRQn = 36, /* I2S Interrupt */ + SPI_IRQn = 37, /* SPI Interrupt */ + QSPI_IRQn = 38, /* QSPI Interrupt */ + UART0_Rx_IRQn = 39, /* UART0 receive FIFO interrupt */ + UART0_Tx_IRQn = 40, /* UART0 transmit FIFO interrupt */ + UART0_RxTimeout_IRQn = 41, /* UART0 receive timeout interrupt */ + UART0_ModemStatus_IRQn = 42, /* UART0 modem status interrupt */ + UART0_Error_IRQn = 43, /* UART0 error interrupt */ + UART0_IRQn = 44, /* UART0 interrupt */ + UART1_Rx_IRQn = 45, /* UART1 receive FIFO interrupt */ + UART1_Tx_IRQn = 46, /* UART1 transmit FIFO interrupt */ + UART1_RxTimeout_IRQn = 47, /* UART1 receive timeout interrupt */ + UART1_ModemStatus_IRQn = 48, /* UART1 modem status interrupt */ + UART1_Error_IRQn = 49, /* UART1 error interrupt */ + UART1_IRQn = 50, /* UART1 interrupt */ + GPIO_0_IRQn = 51, /* GPIO 0 interrupt */ + GPIO_1_IRQn = 52, /* GPIO 1 interrupt */ + GPIO_2_IRQn = 53, /* GPIO 2 interrupt */ + GPIO_3_IRQn = 54, /* GPIO 3 interrupt */ + GPIO_4_IRQn = 55, /* GPIO 4 interrupt */ + GPIO_5_IRQn = 56, /* GPIO 5 interrupt */ + GPIO_6_IRQn = 57, /* GPIO 6 interrupt */ + GPIO_7_IRQn = 58, /* GPIO 7 interrupt */ + GPIO_8_IRQn = 59, /* GPIO 8 interrupt */ + GPIO_9_IRQn = 60, /* GPIO 9 interrupt */ + GPIO_10_IRQn = 61, /* GPIO 10 interrupt */ + GPIO_11_IRQn = 62, /* GPIO 11 interrupt */ + GPIO_12_IRQn = 63, /* GPIO 12 interrupt */ + GPIO_13_IRQn = 64, /* GPIO 13 interrupt */ + GPIO_14_IRQn = 65, /* GPIO 14 interrupt */ + GPIO_15_IRQn = 66, /* GPIO 15 interrupt */ + Combined_IRQn = 67, /* Combined interrupt */ + PVT_IRQn = 68, /* PVT sensor interrupt */ + /* Reserved = 69, Reserved */ + PWM_0_IRQn = 70, /* PWM0 interrupt */ + RTC_IRQn = 71, /* RTC interrupt */ + GpTimer1_IRQn = 72, /* General Purpose Timer1 Interrupt */ + GpTimer0_IRQn = 73, /* General Purpose Timer0 Interrupt */ + PWM_1_IRQn = 74, /* PWM1 interrupt */ + PWM_2_IRQn = 75, /* PWM2 interrupt */ + IOMUX_IRQn = 76, /* IOMUX interrupt */ +} IRQn_Type; + + + +/* =========================================================================================================================== */ +/* ================ Processor and Core Peripheral Section ================ */ +/* =========================================================================================================================== */ + +#include "system_core_musca.h" + +/** @} */ /* End of group Configuration_of_CMSIS */ + + +#include /*!< ARM Cortex-M33 processor and core peripherals */ +#include "system_musca.h" /*!< Musca System */ + + + +/* ======================================== Start of section using anonymous unions ======================================== */ +#if defined (__CC_ARM) + #pragma push + #pragma anon_unions +#elif defined (__ICCARM__) + #pragma language=extended +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wc11-extensions" + #pragma clang diagnostic ignored "-Wreserved-id-macro" +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning 586 +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#else + #warning Not supported compiler type +#endif + + +/* =========================================================================================================================== */ +/* ================ Device Specific Peripheral Section ================ */ +/* =========================================================================================================================== */ + + +/** @addtogroup Device_Peripheral_peripherals + * @{ + */ + +/*@}*/ /* end of group _Peripherals */ + +/* ========================================= End of section using anonymous unions ========================================= */ +#if defined (__CC_ARM) + #pragma pop +#elif defined (__ICCARM__) + /* leave anonymous unions enabled */ +#elif (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic pop +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning restore +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#else + #warning Not supported compiler type +#endif + + +/* =========================================================================================================================== */ +/* ================ Device Specific Peripheral Address Map ================ */ +/* =========================================================================================================================== */ + + +/** @addtogroup Device_Peripheral_peripheralAddr + * @{ + */ + +/* Non-Secure Peripheral and SRAM base address */ +#define MUSCA_CODE_SRAM_NS_BASE (0x00000000UL) /*!< (Non-Secure Code SRAM ) Base Address */ +#define MUSCA_QSPI_FLASH_NS_BASE (0x00200000UL) /*!< (Non-Secure QSPI FLASH ) Base Address */ +#define MUSCA_OTP_NS_BASE (0x0E000000UL) /*!< (Non-Secure OTP ) Base Address */ +#define MUSCA_SRAM_NS_BASE (0x20000000UL) /*!< (Non-Secure Internal SRAM ) Base Address */ +#define MUSCA_BASE_ELEMENT_NS_BASE (0x40000000UL) /*!< (Non-Secure Base Peripherals ) Base Address */ +#define MUSCA_CMSDK_TIMER0_NS_BASE (0x40000000UL) /*!< (Non-Secure CMSDK Timer0 ) Base Address */ +#define MUSCA_CMSDK_TIMER1_NS_BASE (0x40001000UL) /*!< (Non-Secure CMSDK Timer1 ) Base Address */ +#define MUSCA_CMSDK_DUALTIMER_NS_BASE (0x40002000UL) /*!< (Non-Secure CMSDK Dual Timer ) Base Address */ +#define MUSCA_MHU0_NS_BASE (0x40003000UL) /*!< (Non-Secure MHU0 ) Base Address */ +#define MUSCA_MHU1_NS_BASE (0x40004000UL) /*!< (Non-Secure MHU1 ) Base Address */ +#define MUSCA_CPU_ELEMENT_NS_BASE (0x40010000UL) /*!< (Non-Secure CPU Peripherals ) Base Address */ +#define MUSCA_SYSTEM_INFO_NS_BASE (0x40020000UL) /*!< (Non-Secure System Info ) Base Address */ +#define MUSCA_CMSDK_S32KTIMER_NS_BASE (0x4002F000UL) /*!< (Non-Secure CMSDK S32K Timer ) Base Address */ +#define MUSCA_NSPCTRL_NS_BASE (0x40080000UL) /*!< (Non-Secure Privilege Ctrl Blk) Base Address */ +#define MUSCA_CMSDK_WATCHDOG_NS_BASE (0x40081000UL) /*!< (Non-Secure CMSDK Watchdog ) Base Address */ +#define MUSCA_UART0_NS_BASE (0x40101000UL) /*!< (Non-Secure UART0 ) Base Address */ +#define MUSCA_UART1_NS_BASE (0x40102000UL) /*!< (Non-Secure UART1 ) Base Address */ +#define MUSCA_SPI0_NS_BASE (0x40103000UL) /*!< (Non-Secure SPI0 ) Base Address */ +#define MUSCA_I2C0_NS_BASE (0x40104000UL) /*!< (Non-Secure I2C0 ) Base Address */ +#define MUSCA_I2C1_NS_BASE (0x40105000UL) /*!< (Non-Secure I2C1 ) Base Address */ +#define MUSCA_I2S_NS_BASE (0x40106000UL) /*!< (Non-Secure I2S ) Base Address */ +#define MUSCA_PWM0_NS_BASE (0x40107000UL) /*!< (Non-Secure PWM0 ) Base Address */ +#define MUSCA_RTC_NS_BASE (0x40108000UL) /*!< (Non-Secure RTC ) Base Address */ +#define MUSCA_PVT_NS_BASE (0x40109000UL) /*!< (Non-Secure PVT sensors ) Base Address */ +#define MUSCA_QSPI_REG_NS_BASE (0x4010A000UL) /*!< (Non-Secure QSPI registers ) Base Address */ +#define MUSCA_TIMER_NS_BASE (0x4010B000UL) /*!< (Non-Secure Timer ) Base Address */ +#define MUSCA_SCC_NS_BASE (0x4010C000UL) /*!< (Non-Secure SCC ) Base Address */ +#define MUSCA_PWM1_NS_BASE (0x4010E000UL) /*!< (Non-Secure PWM1 ) Base Address */ +#define MUSCA_PWM2_NS_BASE (0x4010F000UL) /*!< (Non-Secure PWM2 ) Base Address */ +#define MUSCA_GPIO_NS_BASE (0x40110000UL) /*!< (Non-Secure GPIO ) Base Address */ +#define MUSCA_QSPI_MPC_NS_BASE (0x40120000UL) /*!< (Non-Secure QSPI MPC ) Base Address */ +#define MUSCA_CODE_SRAM_MPC_NS_BASE (0x40130000UL) /*!< (Non-Secure Code SRAM MPC ) Base Address */ +#define MUSCA_DEFAULT_SLAVE_NS_BASE (0x60000000UL) /*!< (Non-Secure Unused AHB ) Base Address */ +/* Secure Peripheral and SRAM base address */ +#define MUSCA_CODE_SRAM_S_BASE (0x10000000UL) /*!< (Secure Code SRAM ) Base Address */ +#define MUSCA_QSPI_FLASH_S_BASE (0x10200000UL) /*!< (Secure QSPI FLASH ) Base Address */ +#define MUSCA_OTP_S_BASE (0x1E000000UL) /*!< (Secure OTP ) Base Address */ +#define MUSCA_SRAM_S_BASE (0x30000000UL) /*!< (Secure Internal SRAM ) Base Address */ +#define MUSCA_BASE_ELEMENT_S_BASE (0x50000000UL) /*!< (Secure Base Peripherals ) Base Address */ +#define MUSCA_MHU0_S_BASE (0x50003000UL) /*!< (Secure MHU0 ) Base Address */ +#define MUSCA_MHU1_S_BASE (0x50004000UL) /*!< (Secure MHU1 ) Base Address */ +#define MUSCA_CPU_ELEMENT_S_BASE (0x50010000UL) /*!< (Secure CPU Peripherals ) Base Address */ +#define MUSCA_SYSTEM_INFO_S_BASE (0x50020000UL) /*!< (Secure System Info ) Base Address */ +#define MUSCA_SYSTEM_CTRL_S_BASE (0x50021000UL) /*!< (Secure System Control ) Base Address */ +#define MUSCA_CMSDK_S32KTIMER_S_BASE (0x5002F000UL) /*!< (Secure CMSDK S32K Timer ) Base Address */ +#define MUSCA_CMSDK_TIMER0_S_BASE (0x50000000UL) /*!< (Secure CMSDK Timer0 ) Base Address */ +#define MUSCA_CMSDK_TIMER1_S_BASE (0x50001000UL) /*!< (Secure CMSDK Timer1 ) Base Address */ +#define MUSCA_CMSDK_DUALTIMER_S_BASE (0x50002000UL) /*!< (Secure CMSDK Dual Timer ) Base Address */ +#define MUSCA_SPCTRL_S_BASE (0x50080000UL) /*!< (Secure Privilege Ctrl Blk) Base Address */ +#define MUSCA_CMSDK_WATCHDOG_S_BASE (0x50081000UL) /*!< (Secure CMSDK Watchdog ) Base Address */ +#define MUSCA_MPC_SRAM0_S_BASE (0x50083000UL) /*!< (Secure MPC SRAM Bank 0 ) Base Address */ +#define MUSCA_MPC_SRAM1_S_BASE (0x50084000UL) /*!< (Secure MPC SRAM Bank 1 ) Base Address */ +#define MUSCA_MPC_SRAM2_S_BASE (0x50085000UL) /*!< (Secure MPC SRAM Bank 2 ) Base Address */ +#define MUSCA_MPC_SRAM3_S_BASE (0x50086000UL) /*!< (Secure MPC SRAM Bank 3 ) Base Address */ +#define MUSCA_UART0_S_BASE (0x50101000UL) /*!< (Secure UART0 ) Base Address */ +#define MUSCA_UART1_S_BASE (0x50102000UL) /*!< (Secure UART1 ) Base Address */ +#define MUSCA_SPI0_S_BASE (0x50103000UL) /*!< (Secure SPI0 ) Base Address */ +#define MUSCA_I2C0_S_BASE (0x50104000UL) /*!< (Secure I2C0 ) Base Address */ +#define MUSCA_I2C1_S_BASE (0x50105000UL) /*!< (Secure I2C1 ) Base Address */ +#define MUSCA_I2S_S_BASE (0x50106000UL) /*!< (Secure I2S ) Base Address */ +#define MUSCA_PWM0_S_BASE (0x50107000UL) /*!< (Secure PWM0 ) Base Address */ +#define MUSCA_RTC_S_BASE (0x50108000UL) /*!< (Secure RTC ) Base Address */ +#define MUSCA_PVT_S_BASE (0x50109000UL) /*!< (Secure PVT sensors ) Base Address */ +#define MUSCA_QSPI_REG_S_BASE (0x5010A000UL) /*!< (Secure QSPI registers ) Base Address */ +#define MUSCA_TIMER_S_BASE (0x5010B000UL) /*!< (Secure Timer ) Base Address */ +#define MUSCA_SCC_S_BASE (0x5010C000UL) /*!< (Secure SCC ) Base Address */ +#define MUSCA_PWM1_S_BASE (0x5010E000UL) /*!< (Secure PWM1 ) Base Address */ +#define MUSCA_PWM2_S_BASE (0x5010F000UL) /*!< (Secure PWM2 ) Base Address */ +#define MUSCA_GPIO_S_BASE (0x50110000UL) /*!< (Secure GPIO ) Base Address */ +#define MUSCA_QSPI_MPC_S_BASE (0x50120000UL) /*!< (Secure QSPI MPC ) Base Address */ +#define MUSCA_CODE_SRAM_MPC_S_BASE (0x50130000UL) /*!< (Secure Code SRAM MPC ) Base Address */ +#define MUSCA_DEFAULT_SLAVE_S_BASE (0x70000000UL) /*!< (Secure Unused AHB ) Base Address */ + + +/* Peripheral memory map */ + +/** @} */ /* End of group Device_Peripheral_peripheralAddr */ + + +/* =========================================================================================================================== */ +/* ================ Peripheral declaration ================ */ +/* =========================================================================================================================== */ + + +/** @addtogroup Device_Peripheral_declaration + * @{ + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_CMSDK_MUSCA_H */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_core_musca.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_core_musca.h new file mode 100644 index 0000000000..f1fe54328c --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_core_musca.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SYSTEM_CORE_MUSCA_H +#define SYSTEM_CORE_MUSCA_H + +#ifdef DUAL_CORE +/* Both cores are used */ +/* -------- Configuration of the Cortex-M33 Processor and Core Peripherals ------ */ +#define __CM33_REV 0x0001U /* Core revision r0p1 */ +#define __SAUREGION_PRESENT 1U /* SAU regions present */ +#define __MPU_PRESENT 1U /* MPU present */ +#define __VTOR_PRESENT 1U /* VTOR present */ +#define __NVIC_PRIO_BITS 3U /* Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0U /* Set to 1 if different SysTick Config is used */ + +#if defined CORE0 +#define __FPU_PRESENT 0U /* no FPU present */ +#define __DSP_PRESENT 0U /* no DSP extension present */ +#elif defined CORE1 +#define __FPU_PRESENT 1U /* FPU present */ +#define __DSP_PRESENT 1U /* DSP extension present */ +#else +#error "Either CORE0 or CORE1 must be defined" +#endif /* CORE0/1 */ + +#else /* DUAL_CORE */ + +/* Single core is used */ +/* -------- Configuration of the Cortex-M33 Processor and Core Peripherals ------ */ +#define __CM33_REV 0x0000U /* Core revision r0p1 */ +#define __SAUREGION_PRESENT 1U /* SAU regions present */ +#define __MPU_PRESENT 1U /* MPU present */ +#define __VTOR_PRESENT 1U /* VTOR present */ +#define __NVIC_PRIO_BITS 3U /* Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0U /* Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 0U /* no FPU present */ +#define __DSP_PRESENT 0U /* no DSP extension present */ +#endif /* DUAL_CORE */ + +#endif /* SYSTEM_CORE_MUSCA_H */ + diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_musca.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_musca.h new file mode 100644 index 0000000000..2bee5f74c2 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/device/system_musca.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017-2019 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is derivative of CMSIS V5.01 \Device\ARM\ARMCM33\Include\system_ARMCM33.h + * Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75 + * + */ + +#ifndef SYSTEM_MUSCA_H +#define SYSTEM_MUSCA_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ +extern uint32_t PeripheralClock; /*!< Peripheral Clock Frequency */ +extern uint32_t RefClock; /*!< External Reference Clock Frequency */ + +/** + \brief Setup the microcontroller system. + + Initialize the System and update the SystemCoreClock variable. + It should be called from Reset Handler within the first few steps. + The minimal feature set should be initialised for successful exit + from Reset Handler to main entry point. + */ +extern void SystemInit (void); + + +/** + \brief Update SystemCoreClock variable. + + Updates the SystemCoreClock with current core Clock retrieved from cpu registers. + */ +extern void SystemCoreClockUpdate (void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_MUSCA_H */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/gpio_api.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/gpio_api.c new file mode 100644 index 0000000000..449a7db65f --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/gpio_api.c @@ -0,0 +1,81 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file implements APIS defined in hal/gpio_api.h + * Note: Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ + +#include +#include "gpio_api.h" +#include "pinmap.h" +#include "objects.h" +#include "mbed_error.h" + +uint32_t gpio_set(PinName pin) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ + return 0; +} + +void gpio_init(gpio_t *obj, PinName pin) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ +} + +void gpio_mode(gpio_t *obj, PinMode mode) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ +} + +void gpio_dir(gpio_t *obj, PinDirection direction) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ +} + +int gpio_is_connected(const gpio_t *obj) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ + return 0; +} + +void gpio_write(gpio_t *obj, int value) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ +} + +int gpio_read(gpio_t *obj) +{ + /* Due to a HW limitation, GPIO in Musca-A1 is Secure only, so secure + * service should be used for GPIO in NS domain. + */ + return 0; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/gpio_object.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/gpio_object.h new file mode 100644 index 0000000000..e46aa5a07c --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/gpio_object.h @@ -0,0 +1,47 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_GPIO_OBJECT_H +#define MBED_GPIO_OBJECT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Object to store GPIO specific data through the configuration + */ +typedef struct gpio_s { + /** GPIO is not available in Musca-A1 in non-secure domain, so this dummy + * structure is needed for successful build. + */ + uint32_t dummy; +} gpio_t; + +struct gpio_irq_s { + /** GPIO is not available in Musca-A1 in non-secure domain, so this dummy + * structure is needed for successful build. + */ + uint32_t dummy; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/objects.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/objects.h new file mode 100644 index 0000000000..5e0c4d14af --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/objects.h @@ -0,0 +1,60 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_OBJECTS_H +#define MBED_OBJECTS_H + +#include "cmsis.h" +#include "PeripheralNames.h" +#include "PinNames.h" +#include "platform_retarget_dev.h" +#include "gpio_object.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#if TARGET_MUSCA_A1_NS +struct serial_s { + struct uart_pl011_dev_t *uart_dev; + UARTName uart_index; /* UART device number */ + IRQn_Type tx_irq; + IRQn_Type rx_irq; + IRQn_Type rx_timeout_irq; +}; +#endif // TARGET_MUSCA_A1_NS + +#if DEVICE_FLASH +struct flash_s { + uint8_t dummy; +}; +#endif // DEVICE_FLASH + +#if DEVICE_TRNG +struct trng_s { + /* nothing to be stored for now */ + void *dummy; +}; +#endif // DEVICE_TRNG + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/partition/flash_layout.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/partition/flash_layout.h new file mode 100644 index 0000000000..6091ee7dc6 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/partition/flash_layout.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2018-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __FLASH_LAYOUT_H__ +#define __FLASH_LAYOUT_H__ + +/* Flash layout on Musca with BL2: + * 0x0020_0000 BL2 - MCUBoot(128 KB) + * 0x0022_0000 Flash_area_image_0(1 MB) + * 0x0022_0000 Secure image primary + * 0x002A_0000 Non-secure image primary + * 0x0032_0000 Flash_area_image_1(1 MB) + * 0x0032_0000 Secure image secondary + * 0x003A_0000 Non-secure image secondary + * 0x0042_0000 Secure Storage Area(0.02 MB) + * 0x0042_5000 NV counters area(16 Bytes) + * 0x0042_5010 Unused + */ + +/* Code SRAM layout on Musca (with BL2, which is mandatory) after the newest + * image has been copied to SRAM: + * 0x0000_0000 BL2 - MCUBoot(128 KB) + * 0x0002_0000 Flash_area_newest_image(1 MB) + * 0x0002_0000 Secure image primary + * 0x000A_0000 Non-secure image primary + * 0x0012_00000 Unused + */ + +/* This header file is included from linker scatter file as well, where only a + * limited C constructs are allowed. Therefore it is not possible to include + * here the platform_retarget.h to access flash related defines. To resolve this + * some of the values are redefined here with different names, these are marked + * with comment. + */ + +/* The size of a partition. This should be large enough to contain a S or NS + * sw binary. Each FLASH_AREA_IMAGE contains two partitions. See Flash layout + * above. + */ +#define FLASH_PARTITION_SIZE (0x80000) /* 512KB */ + +/* Sector size of the flash hardware */ +#define FLASH_AREA_IMAGE_SECTOR_SIZE (0x1000) /* 4KB */ +#define FLASH_TOTAL_SIZE (0x800000) /* 8MB */ + +/* Flash layout info for BL2 bootloader */ +#define FLASH_BASE_ADDRESS (0x10200000) /* same as FLASH0_BASE_S */ + +/* Offset and size definitions of the flash partitions that are handled by the + * bootloader. The image swapping is done between IMAGE_0 and IMAGE_1, SCRATCH + * is used as a temporary storage during image swapping. + */ +#define FLASH_AREA_BL2_OFFSET (0x0) +#define FLASH_AREA_BL2_SIZE (0x20000) /* 128KB */ + +#define FLASH_AREA_IMAGE_0_OFFSET (0x20000) +#define FLASH_AREA_IMAGE_0_SIZE (2 * FLASH_PARTITION_SIZE) + +#define FLASH_AREA_IMAGE_1_OFFSET (0x120000) +#define FLASH_AREA_IMAGE_1_SIZE (2 * FLASH_PARTITION_SIZE) + +/* Not used, only RAM loading is supported on Musca A1 */ +#define FLASH_AREA_IMAGE_SCRATCH_OFFSET (0x220000) +#define FLASH_AREA_IMAGE_SCRATCH_SIZE (0) + +/* + * Not used, only RAM loading is supported on Musca A1. + * The maximum number of status entries supported by the bootloader. + */ +#define BOOT_STATUS_MAX_ENTRIES (0) + +/** Maximum number of image sectors supported by the bootloader. */ +#define BOOT_MAX_IMG_SECTORS ((2 * FLASH_PARTITION_SIZE) / \ + FLASH_AREA_IMAGE_SECTOR_SIZE) + +#define FLASH_SST_AREA_OFFSET (FLASH_AREA_IMAGE_SCRATCH_OFFSET + \ + FLASH_AREA_IMAGE_SCRATCH_SIZE) +#define FLASH_SST_AREA_SIZE (0x5000) /* 20 KB */ + +#define FLASH_NV_COUNTERS_AREA_OFFSET (FLASH_SST_AREA_OFFSET + \ + FLASH_SST_AREA_SIZE) +#define FLASH_NV_COUNTERS_AREA_SIZE (0x10) /* 16 Bytes */ + +/* Offset and size definition in flash area, used by assemble.py */ +#define SECURE_IMAGE_OFFSET 0x0 +#define SECURE_IMAGE_MAX_SIZE 0x80000 + +#define NON_SECURE_IMAGE_OFFSET 0x80000 +#define NON_SECURE_IMAGE_MAX_SIZE 0x80000 + +#define S_QSPI_ALIAS_BASE (0x10200000) +#define NS_QSPI_ALIAS_BASE (0x00200000) + +#define S_SRAM_ALIAS_BASE (0x10000000) +#define NS_SRAM_ALIAS_BASE (0x00000000) + +/* Address that tells the bootloader where in SRAM to copy the image from flash + * E.g. Lowest address = S_SRAM_ALIAS_BASE + * + FLASH_AREA_BL2_SIZE + * = 0x10000000 + 0x20000 = 0x10020000 + * Please make sure the value is in the form of hex. here + */ +#define IMAGE_LOAD_ADDRESS 0x10020000 + +/* Flash device name used by BL2 and SST + * Name is defined in flash driver file: Driver_Flash.c + */ +#define FLASH_DEV_NAME Driver_FLASH0 + +/* Secure Storage (SST) Service definitions */ +/* In this target the CMSIS driver requires only the offset from the base + * address instead of the full memory address. + */ +#define SST_FLASH_AREA_ADDR FLASH_SST_AREA_OFFSET +#define SST_SECTOR_SIZE FLASH_AREA_IMAGE_SECTOR_SIZE +/* The sectors must be in consecutive memory location */ +#define SST_NBR_OF_SECTORS (FLASH_SST_AREA_SIZE / SST_SECTOR_SIZE) +/* Specifies the smallest flash programmable unit in bytes */ +#define SST_FLASH_PROGRAM_UNIT 0x1 + +/* NV Counters definitions */ +#define TFM_NV_COUNTERS_AREA_ADDR FLASH_NV_COUNTERS_AREA_OFFSET +#define TFM_NV_COUNTERS_AREA_SIZE FLASH_NV_COUNTERS_AREA_SIZE +#define TFM_NV_COUNTERS_SECTOR_ADDR FLASH_NV_COUNTERS_AREA_OFFSET +#define TFM_NV_COUNTERS_SECTOR_SIZE FLASH_AREA_IMAGE_SECTOR_SIZE + +/* FIXME: Use SRAM2 memory to store RW data */ +#define S_RAM_ALIAS_BASE (0x30000000) +#define NS_RAM_ALIAS_BASE (0x20000000) + +/* Shared data area between bootloader and runtime firmware. + * Shared data area is allocated at the beginning of the RAM, it is overlapping + * with TF-M Secure code's MSP stack + */ +#define BOOT_TFM_SHARED_DATA_BASE S_RAM_ALIAS_BASE +#define BOOT_TFM_SHARED_DATA_SIZE 0x400 + +#endif /* __FLASH_LAYOUT_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/partition/region_defs.h b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/partition/region_defs.h new file mode 100644 index 0000000000..16ae45829d --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/partition/region_defs.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2017-2019 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __REGION_DEFS_H__ +#define __REGION_DEFS_H__ + +#include "flash_layout.h" + +#define TOTAL_ROM_SIZE (0x00200000) /* 2 MB */ +#define TOTAL_RAM_SIZE (0x00020000) /* 128KB */ + +#define BL2_HEAP_SIZE 0x0001000 +#define BL2_MSP_STACK_SIZE 0x0001000 + +#define S_HEAP_SIZE 0x0004000 +#define S_MSP_STACK_SIZE_INIT 0x0000400 +#define S_MSP_STACK_SIZE 0x0000800 +#define S_PSP_STACK_SIZE 0x0000800 + +#define NS_HEAP_SIZE 0x0001000 +#define NS_MSP_STACK_SIZE 0x0000400 +#define NS_PSP_STACK_SIZE 0x0000C00 + +/* + * MPC granularity is 128 KB on Musca. Alignment + * of partitions is defined in accordance with this constraint. + */ +#define S_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_IMAGE_0_OFFSET) +#define S_IMAGE_SECONDARY_PARTITION_OFFSET (FLASH_AREA_IMAGE_1_OFFSET) + +#define NS_IMAGE_PRIMARY_PARTITION_OFFSET (S_IMAGE_PRIMARY_PARTITION_OFFSET + \ + FLASH_PARTITION_SIZE) + +/* + * Boot partition structure if MCUBoot is used: + * 0x0_0000 Bootloader header + * 0x0_0400 Image area + * 0x1_FC00 Trailer + */ +/* IMAGE_CODE_SIZE is the space available for the software binary image. + * It is less than the FLASH_PARTITION_SIZE because we reserve space + * for the image header and trailer introduced by the bootloader. + */ +#define BL2_HEADER_SIZE (0x400) +#define BL2_TRAILER_SIZE (0x400) + +#define IMAGE_CODE_SIZE \ + (FLASH_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE) + +#define CMSE_VENEER_REGION_SIZE (0x000001C0) + +/* + * Since we enable/disable flash during s/ns code copy to code sram we cannot + * access bl2 code from flash, hence we need to copy the bl2 code to code sram + */ +#define BL2_CODE_SRAM_ALIAS_BASE (S_SRAM_ALIAS_BASE) +#define BL2_CODE_SRAM_ALIAS(x) (BL2_CODE_SRAM_ALIAS_BASE + x) +#define BL2_CODE_SRAM_BASE (BL2_CODE_SRAM_ALIAS(FLASH_AREA_BL2_OFFSET)) + +/* Use QSPI Flash memory to store Code data */ +#define S_ROM_ALIAS_BASE (0x10200000) +#define NS_ROM_ALIAS_BASE (0x00200000) + +#define S_RAM_ALIAS_BASE (0x30000000) +#define NS_RAM_ALIAS_BASE (0x20000000) + +/* Alias definitions for secure and non-secure areas*/ +#define S_ROM_ALIAS(x) (S_SRAM_ALIAS_BASE + x) +#define NS_ROM_ALIAS(x) (NS_SRAM_ALIAS_BASE + x) + +#define S_RAM_ALIAS(x) (S_RAM_ALIAS_BASE + x) +#define NS_RAM_ALIAS(x) (NS_RAM_ALIAS_BASE + x) + +/* Secure regions */ +#define S_IMAGE_PRIMARY_AREA_OFFSET \ + (S_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE) +#define S_CODE_START (S_ROM_ALIAS(S_IMAGE_PRIMARY_AREA_OFFSET)) +#define S_CODE_SIZE (IMAGE_CODE_SIZE - CMSE_VENEER_REGION_SIZE) +#define S_CODE_LIMIT (S_CODE_START + S_CODE_SIZE - 1) + +#define S_DATA_START (S_RAM_ALIAS(0x0)) + +#if defined(TEST_FRAMEWORK_S) || defined(TEST_FRAMEWORK_NS) +/* Increase secure DATA area to run the regression tests on Musca A1 */ +#define S_DATA_SIZE ((TOTAL_RAM_SIZE / 4) * 3) +#else +#define S_DATA_SIZE ((TOTAL_RAM_SIZE / 2) + 0x1000) +#endif + +#define S_DATA_LIMIT (S_DATA_START + S_DATA_SIZE - 1) + +/* CMSE Veneers region */ +#define CMSE_VENEER_REGION_START (S_CODE_LIMIT + 1) + +/* Non-secure regions */ +#define NS_IMAGE_PRIMARY_AREA_OFFSET \ + (NS_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE) +#define NS_CODE_START (NS_ROM_ALIAS(NS_IMAGE_PRIMARY_AREA_OFFSET)) +#define NS_CODE_SIZE (IMAGE_CODE_SIZE - FLASH_AREA_BL2_SIZE) +#define NS_CODE_LIMIT (NS_CODE_START + NS_CODE_SIZE - 1) + +#define NS_DATA_START (NS_RAM_ALIAS(S_DATA_SIZE)) +#define NS_DATA_SIZE (TOTAL_RAM_SIZE - S_DATA_SIZE) + +#define NS_DATA_LIMIT (NS_DATA_START + NS_DATA_SIZE - 1) + +/* NS partition information is used for MPC and SAU configuration */ +#define NS_PARTITION_START \ + (NS_ROM_ALIAS(NS_IMAGE_PRIMARY_PARTITION_OFFSET)) + +#define NS_PARTITION_SIZE (FLASH_PARTITION_SIZE) + +/* Secondary partition for new images in case of firmware upgrade */ +#define SECONDARY_PARTITION_START \ + (NS_ROM_ALIAS(S_IMAGE_SECONDARY_PARTITION_OFFSET)) + +#define SECONDARY_PARTITION_SIZE (FLASH_AREA_IMAGE_1_SIZE) + +/* Code SRAM area */ +#define TOTAL_CODE_SRAM_SIZE (TOTAL_ROM_SIZE) +#define S_CODE_SRAM_ALIAS_BASE (0x10000000) +#define NS_CODE_SRAM_ALIAS_BASE (0x00000000) + +#define BL2_CODE_SRAM_EXEC_BASE (S_CODE_SRAM_ALIAS_BASE) +#define S_CODE_SRAM_EXEC_BASE (S_CODE_SRAM_ALIAS_BASE) +#define S_CODE_SRAM_EXEC_LIMIT (S_CODE_SRAM_EXEC_BASE + \ + (TOTAL_CODE_SRAM_SIZE / 2) - 1) +#define NS_CODE_SRAM_EXEC_BASE (NS_CODE_SRAM_ALIAS_BASE + \ + (TOTAL_CODE_SRAM_SIZE / 2)) +#define NS_CODE_SRAM_EXEC_LIMIT (NS_CODE_SRAM_EXEC_BASE + \ + (TOTAL_CODE_SRAM_SIZE / 2) - 1) + +/* Bootloader regions */ +#define BL2_CODE_START (S_QSPI_ALIAS_BASE) +#define BL2_CODE_SIZE (FLASH_AREA_BL2_SIZE) +#define BL2_CODE_LIMIT (BL2_CODE_START + BL2_CODE_SIZE - 1) + +#define BL2_DATA_START (S_RAM_ALIAS(0x0)) +#define BL2_DATA_SIZE (TOTAL_RAM_SIZE) +#define BL2_DATA_LIMIT (BL2_DATA_START + BL2_DATA_SIZE - 1) + +#endif /* __REGION_DEFS_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/pinmap.c b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/pinmap.c new file mode 100644 index 0000000000..a4264b02de --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/pinmap.c @@ -0,0 +1,122 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed_assert.h" +#include "mbed_error.h" +#include "pinmap.h" +#include "objects.h" +#include "musca_a1_scc_drv.h" + +#if TARGET_MUSCA_A1_NS + +const PinMap PinMap_UART_TX[] = { + {UART0_TX, UART_0, ALTERNATE_FUNC_1}, + {UART1_TX, UART_1, PRIMARY_FUNC}, + {NC, NC, 0} +}; + +const PinMap PinMap_UART_RX[] = { + {UART0_RX, UART_0, ALTERNATE_FUNC_1}, + {UART1_RX, UART_1, PRIMARY_FUNC}, + {NC, NC, 0} +}; + +/** + * \brief Configures the GPIO pin and sets the alternate function + * + * \param[in] pin GPIO pin number \ref PinName + * \param[in] function Alternate function to set \ref PinFunction + */ +void pin_function(PinName pin, int function) +{ + enum gpio_altfunc_t flags; + + MBED_ASSERT(pin != NC); + + /* The pin has to be a GPIO pin */ + if (pin >= PA0 && pin <= PA15) { + switch (function) { + case PRIMARY_FUNC: + flags = GPIO_MAIN_FUNC; + break; + case ALTERNATE_FUNC_1: + flags = GPIO_ALTFUNC_1; + break; + case ALTERNATE_FUNC_2: + flags = GPIO_ALTFUNC_2; + break; + case ALTERNATE_FUNC_3: + flags = GPIO_ALTFUNC_3; + break; + default: + return; + } + +#ifdef MUSCA_A1_SCC_DEV + musca_a1_scc_set_alt_func(&MUSCA_A1_SCC_DEV, flags, (1u< + #if defined(TARGET_BEETLE) #ifndef INITIAL_SP @@ -39,6 +43,21 @@ #define INITIAL_SP (ZBT_SSRAM23_START + ZBT_SSRAM23_SIZE) #endif -#endif /* defined(TARGET_...) */ +#elif defined(TARGET_MUSCA_A1) + +#if defined(__ARMCC_VERSION) + extern uint32_t Image$$ARM_LIB_HEAP$$ZI$$Base[]; + extern uint32_t Image$$ARM_LIB_HEAP$$ZI$$Length[]; + #define HEAP_START Image$$ARM_LIB_HEAP$$ZI$$Base + #define HEAP_SIZE Image$$ARM_LIB_HEAP$$ZI$$Length +#elif defined(__GNUC__) + /* No region declarations needed */ +#elif defined(__ICCARM__) + /* No region declarations needed */ +#else + #error "no toolchain defined" +#endif + +#endif /* TARGET_MUSCA_A1 */ #endif /* MBED_MBED_RTX_H */ diff --git a/targets/targets.json b/targets/targets.json index ff37a39409..f397249d12 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -5427,6 +5427,62 @@ "target.network-default-interface-type": "ETHERNET" } }, + "ARM_MUSCA_A1": { + "public": false, + "inherits": ["Target"], + "default_toolchain": "ARMC6", + "extra_labels": ["ARM_SSG", "MUSCA_A1"], + "forced_reset_timeout": 7, + "release_versions": ["5"] + }, + "ARM_MUSCA_A1_NS": { + "inherits": ["NSPE_Target", "ARM_MUSCA_A1"], + "core": "Cortex-M33-NS", + "supported_toolchains": ["ARMC6", "GCC_ARM", "IAR"], + "device_has_add": ["INTERRUPTIN", "LPTICKER", "SERIAL", "SLEEP", "USTICKER"], + "macros": [ + "__STARTUP_CLEAR_BSS", + "MBED_FAULT_HANDLER_DISABLED", + "CMSIS_NVIC_VIRTUAL", + "LPTICKER_DELAY_TICKS=1", + "MBED_MPU_CUSTOM", + "MBEDTLS_PSA_CRYPTO_C" + ], + "extra_labels_add": ["MUSCA_A1_NS", "PSA", "TFM"], + "post_binary_hook": {"function": "ArmMuscaA1Code.binary_hook"}, + "secure_image_filename": "tfm.bin", + "overrides": { + "non-secure-rom-start": "0x000a0400", + "non-secure-rom-size": "0x5f800", + "non-secure-ram-start": "0x20011000", + "non-secure-ram-size": "0xf000" + } + }, + "ARM_MUSCA_A1_S": { + "inherits": ["SPE_Target", "ARM_MUSCA_A1"], + "core": "Cortex-M33", + "supported_toolchains": ["ARMC6", "GCC_ARM"], + "device_has_add": ["FLASH"], + "macros": [ + "__STARTUP_CLEAR_BSS_MULTIPLE", + "__STARTUP_COPY_MULTIPLE", + "MBED_MPU_CUSTOM", + "DAUTH_CHIP_DEFAULT", + "MBEDTLS_PSA_CRYPTO_SPM", + "MBEDTLS_PSA_CRYPTO_C", + "MBEDTLS_ENTROPY_NV_SEED" + ], + "components_add": ["FLASHIAP"], + "extra_labels_add": ["MUSCA_A1_S", "PSA", "TFM"], + "deliver_to_target": "ARM_MUSCA_A1_NS", + "delivery_dir": "TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt", + "overrides": { + "secure-rom-start": "0x10020400", + "secure-rom-size": "0x7f800", + "secure-ram-start": "0x30000000", + "secure-ram-size": "0x11000" + } + }, "RZ_A1XX": { "inherits": ["Target"], "core": "Cortex-A9", diff --git a/tools/targets/ARM_MUSCA_A1.py b/tools/targets/ARM_MUSCA_A1.py new file mode 100644 index 0000000000..6143fad32f --- /dev/null +++ b/tools/targets/ARM_MUSCA_A1.py @@ -0,0 +1,87 @@ +#!/usr/bin/python +# Copyright (c) 2017-2018 ARM Limited +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +from os.path import abspath, basename, dirname, splitext, isdir +from os.path import join as path_join +import re +from argparse import Namespace +from tools.psa.tfm.bin_utils.assemble import Assembly +from tools.psa.tfm.bin_utils.imgtool import do_sign +from tools.psa.tfm.bin_utils.imgtool_lib import version + +SCRIPT_DIR = dirname(abspath(__file__)) +MBED_OS_ROOT = abspath(path_join(SCRIPT_DIR, os.pardir, os.pardir)) +MUSCA_A1_BASE = path_join(MBED_OS_ROOT, 'targets', 'TARGET_ARM_SSG', 'TARGET_MUSCA_A1') + + +def musca_tfm_bin(t_self, non_secure_bin, secure_bin): + + assert os.path.isfile(secure_bin) + assert os.path.isfile(non_secure_bin) + + build_dir = dirname(non_secure_bin) + tempdir = path_join(build_dir, 'temp') + if not isdir(tempdir): + os.makedirs(tempdir) + flash_layout = path_join(MUSCA_A1_BASE, 'partition', 'flash_layout.h') + mcuboot_bin = path_join(MUSCA_A1_BASE, 'TARGET_MUSCA_A1_NS', 'prebuilt', 'mcuboot.bin') + ns_bin_name, ns_bin_ext = splitext(basename(non_secure_bin)) + concatenated_bin = path_join(tempdir, 'tfm_' + ns_bin_name + ns_bin_ext) + signed_bin = path_join(tempdir, 'tfm_' + ns_bin_name + '_signed' + ns_bin_ext) + + assert os.path.isfile(flash_layout) + + #1. Concatenate secure TFM and non-secure mbed binaries + output = Assembly(flash_layout, concatenated_bin) + output.add_image(secure_bin, "SECURE") + output.add_image(non_secure_bin, "NON_SECURE") + + #2. Run imgtool to sign the concatenated binary + sign_args = Namespace( + layout=flash_layout, + key=path_join(SCRIPT_DIR, 'musca_a1-root-rsa-2048.pem'), + align=1, + version=version.decode_version('1.0'), + header_size=0x400, + pad=0x100000, + rsa_pkcs1_15=False, + included_header=False, + infile=concatenated_bin, + outfile=signed_bin + ) + do_sign(sign_args) + + #3. Concatenate mcuboot and signed binary and overwrite mbed built binary file + mcuboot_image_size = find_bl2_size(flash_layout) + with open(mcuboot_bin, "rb") as mcuboot_fh, open(signed_bin, "rb") as signed_fh: + with open(non_secure_bin, "w+b") as out_fh: + out_fh.write(mcuboot_fh.read()) + out_fh.seek(mcuboot_image_size) + out_fh.write(signed_fh.read()) + + +def find_bl2_size(configFile): + bl2_size_re = re.compile(r"^#define\s+FLASH_AREA_BL2_SIZE\s+\({0,1}(0x[0-9a-fA-F]+)\){0,1}") + bl2_size = None + with open(configFile, 'r') as flash_layout_file: + for line in flash_layout_file: + m = bl2_size_re.match(line) + if m is not None: + bl2_size = int(m.group(1), 0) + break + return bl2_size diff --git a/tools/targets/__init__.py b/tools/targets/__init__.py index 421630fd3a..72fc498d58 100644 --- a/tools/targets/__init__.py +++ b/tools/targets/__init__.py @@ -31,6 +31,7 @@ from tools.paths import TOOLS_BOOTLOADERS from tools.utils import json_file_to_dict, NotSupportedException from tools.psa import find_secure_image + __all__ = ["target", "TARGETS", "TARGET_MAP", "TARGET_NAMES", "CORE_LABELS", "CORE_ARCH", "HookError", "generate_py_target", "Target", "CUMULATIVE_ATTRIBUTES", "get_resolution_order"] @@ -675,6 +676,22 @@ class PSOC6Code: psoc6_complete(t_self, elf, binf) +class ArmMuscaA1Code: + """Musca-A1 Hooks""" + @staticmethod + def binary_hook(t_self, resources, elf, binf): + from tools.targets.ARM_MUSCA_A1 import musca_tfm_bin + configured_secure_image_filename = t_self.target.secure_image_filename + secure_bin = find_secure_image( + t_self.notify, + resources, + binf, + configured_secure_image_filename, + FileType.BIN + ) + musca_tfm_bin(t_self, binf, secure_bin) + + class LPC55S69Code: """LPC55S69 Hooks""" @staticmethod diff --git a/tools/targets/musca_a1-root-rsa-2048.md b/tools/targets/musca_a1-root-rsa-2048.md new file mode 100644 index 0000000000..ba112361f1 --- /dev/null +++ b/tools/targets/musca_a1-root-rsa-2048.md @@ -0,0 +1,11 @@ +# Musca-A1 RSA keypair + +A default RSA key pair is given to the Musca-A1 target. + +Public key was pre-compiled to `targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/mcuboot.bin` and private key is in `musca_a1-root-rsa-2048.pem`. + +DO NOT use them in production code, they are exclusively for testing! + +Private key must be stored in a safe place outside of the repository. + +`tools/psa/tfm/bin_utils/imgtool.py` can be used to generate new key pairs. diff --git a/tools/targets/musca_a1-root-rsa-2048.pem b/tools/targets/musca_a1-root-rsa-2048.pem new file mode 100644 index 0000000000..78c0c34194 --- /dev/null +++ b/tools/targets/musca_a1-root-rsa-2048.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA0QYIGhhELBjo+/33DaNPH7vuXvmq0ksY01rpbRiAGfnwnDQb +y/O8dNtC54x/EFN+Q14NVyxE0WcIDw27XO7ss5nf4E2EC6p3QWDtFShJpwG0PBDm +aYwvX6xBTZ5cFN/y+M89Hm/nW7q0qciIfkc8lMN3Z1RLqo04NcpiYX634RXbd3PU +vntyIYlpJPv4ZW5kPsgO14XVXErkUw0v/7f98xM5gz+jrtIPp2qd+f64zvoqvq+4 +4PqCN1T0PuEr0NMIWBj2XkzIiIExrV+wghfyimknI/Orhz6TGh3+6PgaJGZZ+Byr +3M5oG2ZkNez6DRGdr1w6p9FnxkfvsUssYuHRyQIDAQABAoIBAEahFCHFK1v/OtLT +eSSZl0Xw2dYr5QXULFpWsOOVUMv2QdB2ZyIehQKziEL3nYPlwpd+82EOa16awwVb +LYF0lnUFvLltV/4dJtjnqJTqnSCamc1mJIVrwiJA8XwJ07GWDuL2G//p7jJ3v05T +nZOV/KmD9xfqSvshZun+LgolqHqcrAa1f4cmuP9C9oqenZryljyfj7piaIZGI0JR +PrJJ5kImYJqRcMgKTyHP4L8nwQ4moMJr6zbfbWxxb5TC7KVZSQ9UKZZ+ZLuy/pkU +Qe4G8XSE0r+R9u4JCg87I1vgHhn8WJSxVX027OVUq5HfOzg2skQBTcExph5V9B2b +onNxd8UCgYEA/32PW+ZwRcdKXMj+QVkxXUd6xkXy7mTXPEaQuOLWZQgrSqAFH1l4 +5/6d099KAJrjM6kR8pKXtz72IIyMHTPm332ghymjKvaEl2XP9sF+f6FmYURar4y6 +8Zh3eivP86+Q/YzOGKwtRSziBMzrAfoIXgtwH8pwIPYLP3zBV4449ZsCgYEA0XC/ +gu2ub5M6EXBnjq9K2d4LlTyAPsIbAcMSwkhOUH4YJFS22qXLYQUA9zM+DUyLCrl/ +PKN2G0HQVgMb4DIbeHv8kXB5oGm5zfbWorWqOomXB3AsI7X8YDMtf/PsZV2amBei +qVskmPJQV21qFyeOcHlT+dHuRb0O0un3dK8RHmsCgYEApDCH4dJ80osZoflVVJ/C +VqTqJOOtFEFgBQ+AUCEPEQyn7aRaxmPUjJsXyKJVx3/ChV+g9hf5Qj1HJXHNVbMW +KwhsEpDSmHimizlV5clBxzntNpMcCHdTaJHILo5bbMqmThugE0ELMsp+UgFzAeky +WWXWX8fUOYqFff5prh/rQQMCgYBQQ8FhT+113Rp37HgDerJY5HvT6afMZV8sQbJC +uqsotepSohShnsBeoihIlF7HgfoXVhepCYwNzh8ll3NrbEiS2BFnO4+hJmOKx3pi +SPTAElLLCvYfiXL6+yII01ZZUpIYj5ZLCR7xbovTtZ7e2M4B1L2WFBoYp+eydO/c +y+rnmQKBgCh0gfyBT/OKPkfKv+Bbt8HcoxgEj+TyH+vYdeTbP9ZSJ6y5utMbPg7z +iLLbJ+9IcSwPCwJSmI+I0Om4xEp4ZblCrzAG7hWvG2NNzxQjmoOOrAANyTvJR/ap +N+UkQA4WrMSKEYyBlRS/hR9Unz31vMc2k9Re0ukWhWh/QksQGDfJ +-----END RSA PRIVATE KEY-----