mirror of https://github.com/ARMmbed/mbed-os.git
psa: Remove v8-M S targets
Remove PSA v8-M S target binaries will be built outside of Mbed OS and added in as binaries which NS targets consume. Mbed OS no longer implements PSA for v8-M targets, so there is no reason for it to build PSA S targets. Signed-off-by: Jaeden Amero <jaeden.amero@arm.com>pull/12737/head
parent
493a043528
commit
6b3a9cb4fa
|
@ -49,9 +49,6 @@ TLS_SRC := \
|
|||
# COMPONENT_PSA_SRV_IMPL - Include secure service implementation code. For
|
||||
# example PSA Crypto or PSA Secure Time implementations
|
||||
TARGET_SRV_IMPL:=$(TARGET_PREFIX)/platform/COMPONENT_PSA_SRV_IMPL
|
||||
# COMPONENT_SPE - Include code that compiles ONLY to the SPE image and never
|
||||
# compiles to the NSPE image
|
||||
TARGET_SPE:=$(TARGET_PREFIX)/platform/COMPONENT_SPE
|
||||
# COMPONENT_NSPE - Include code that compiles ONLY to the NSPE image and never
|
||||
# compiles to the SPE image
|
||||
TARGET_NSPE:=$(TARGET_SRV_IMPL)/COMPONENT_NSPE
|
||||
|
@ -88,15 +85,12 @@ rsync:
|
|||
#
|
||||
# Copying Mbed Crypto into Mbed OS...
|
||||
rm -rf $(TARGET_SRV_IMPL)
|
||||
rm -rf $(TARGET_SPE)
|
||||
rm -rf $(TARGET_SRC)
|
||||
|
||||
mkdir -p $(TARGET_SRV_IMPL)
|
||||
mkdir -p $(TARGET_SPE)
|
||||
mkdir -p $(TARGET_NSPE)
|
||||
|
||||
rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_NSPE)/
|
||||
rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_SPE)/crypto_struct_spe.h
|
||||
rsync -a --delete $(CRYPTO_DIR)/library/psa_*.c $(TARGET_SRV_IMPL)/
|
||||
rsync -a --delete $(CRYPTO_DIR)/library/psa_*.h $(TARGET_SRV_IMPL)/
|
||||
rsync -a --delete $(CRYPTO_DIR)/library/*.c $(TARGET_SRC)/
|
||||
|
@ -135,4 +129,3 @@ clean:
|
|||
rm -rf $(TARGET_SRC)
|
||||
rm -rf $(CRYPTO_DIR)
|
||||
rm -rf $(TARGET_SRV_IMPL)
|
||||
rm -rf $(TARGET_SPE)
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
|
||||
// <i> Configuration settings for Driver_ISRAM0_MPC in component ::Drivers:MPC
|
||||
#define RTE_ISRAM0_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
|
||||
// <i> Configuration settings for Driver_SRAM1_MPC in component ::Drivers:MPC
|
||||
#define RTE_ISRAM1_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
|
||||
// <i> Configuration settings for Driver_ISRAM2_MPC in component ::Drivers:MPC
|
||||
#define RTE_ISRAM2_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM3_MPC]
|
||||
// <i> Configuration settings for Driver_SRAM2_MPC in component ::Drivers:MPC
|
||||
#define RTE_ISRAM3_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_SRAM3_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
|
||||
// <i> Configuration settings for Driver_CODE_SRAM_MPC in component ::Drivers:MPC
|
||||
#define RTE_CODE_SRAM_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
|
||||
// <i> Configuration settings for Driver_QSPI_MPC in component ::Drivers:MPC
|
||||
#define RTE_QSPI_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
|
||||
|
||||
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
|
||||
// <i> Configuration settings for Driver_USART0 in component ::Drivers:USART
|
||||
#define RTE_USART0 1
|
||||
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
|
||||
|
||||
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
|
||||
// <i> Configuration settings for Driver_USART1 in component ::Drivers:USART
|
||||
#define RTE_USART1 1
|
||||
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
|
||||
// <i> Configuration settings for Driver_AHB_PPC0 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPC0 1
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
|
||||
// <i> Configuration settings for Driver_AHB_PPCEXP0 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPCEXP0 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
|
||||
// <i> Configuration settings for Driver_AHB_PPCEXP1 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPCEXP1 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
|
||||
// <i> Configuration settings for Driver_AHB_PPCEXP2 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPCEXP2 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
|
||||
// <i> Configuration settings for Driver_AHB_PPCEXP3 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPCEXP3 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
|
||||
// <i> Configuration settings for Driver_APB_PPC0 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPC0 1
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
|
||||
// <i> Configuration settings for Driver_APB_PPC1 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPC1 1
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
|
||||
// <i> Configuration settings for Driver_APB_PPCEXP0 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPCEXP0 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
|
||||
// <i> Configuration settings for Driver_APB_PPCEXP1 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPCEXP1 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
|
||||
// <i> Configuration settings for Driver_APB_PPCEXP2 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPCEXP2 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
|
||||
// <i> Configuration settings for Driver_APB_PPCEXP3 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPCEXP3 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
|
||||
|
||||
// <e> FLASH (Flash Memory) [Driver_FLASH0]
|
||||
// <i> Configuration settings for Driver_FLASH0 in component ::Drivers:FLASH
|
||||
#define RTE_FLASH0 1
|
||||
// </e> FLASH (Flash Memory) [Driver_FLASH0]
|
||||
|
||||
#endif /* __RTE_DEVICE_H */
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* 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 */
|
||||
|
|
@ -1,969 +0,0 @@
|
|||
/*
|
||||
* 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 */
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* 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__ */
|
||||
|
|
@ -1,944 +0,0 @@
|
|||
/*
|
||||
* 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 <stdlib.h>
|
||||
/* Use memcpy function */
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -1,252 +0,0 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -1,153 +0,0 @@
|
|||
#! 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 {
|
||||
}
|
||||
}
|
|
@ -1,254 +0,0 @@
|
|||
;/*
|
||||
; * 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 >>> ------------------
|
||||
;*/
|
||||
|
||||
|
||||
; <h> Stack Configuration
|
||||
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
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
|
|
@ -1,366 +0,0 @@
|
|||
;/*
|
||||
; * 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);
|
||||
PROVIDE(__StackTop = __stack);
|
||||
PROVIDE(__StackLimit = __StackTop - SIZEOF(.psp_stack));
|
||||
}
|
|
@ -1,365 +0,0 @@
|
|||
;/*
|
||||
; * 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
|
|
@ -1,652 +0,0 @@
|
|||
/*
|
||||
* 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 <stddef.h>
|
||||
|
||||
#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; i<limit_word_idx; i++) {
|
||||
p_mpc->blk_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; i<limit_word_idx; i++) {
|
||||
p_mpc->blk_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;
|
||||
}
|
|
@ -1,282 +0,0 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#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__ */
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#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__ */
|
|
@ -1,325 +0,0 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
/* 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__ */
|
|
@ -1,757 +0,0 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
/* Use memcpy */
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
|
@ -1,418 +0,0 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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__ */
|
|
@ -1,132 +0,0 @@
|
|||
/* 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
|
|
@ -1,324 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#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));
|
||||
}
|
|
@ -1,370 +0,0 @@
|
|||
/*
|
||||
* 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; i<sizeof(NVIC->ITNS)/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;
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -18,7 +18,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "../../../partition/region_defs.h"
|
||||
#include "../../partition/region_defs.h"
|
||||
#include "../cmsis_nvic.h"
|
||||
|
||||
#if !defined(MBED_ROM_START)
|
|
@ -22,7 +22,7 @@
|
|||
/* Linker script to configure memory regions. */
|
||||
/* This file will be run trough the pre-processor. */
|
||||
|
||||
#include "../../../partition/region_defs.h"
|
||||
#include "../../partition/region_defs.h"
|
||||
#include "../cmsis_nvic.h"
|
||||
|
||||
/* Stack size is 1K for Mbed-OS */
|
|
@ -24,7 +24,7 @@
|
|||
#ifndef MBED_CMSIS_NVIC_H
|
||||
#define MBED_CMSIS_NVIC_H
|
||||
|
||||
#include "../../partition/region_defs.h"
|
||||
#include "../partition/region_defs.h"
|
||||
|
||||
#define NVIC_NUM_VECTORS (16 + 76)
|
||||
/** Location of vectors to move in RAM */
|
|
@ -30,91 +30,28 @@
|
|||
*/
|
||||
|
||||
/* 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
|
||||
|
@ -144,6 +81,5 @@
|
|||
#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__ */
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if TARGET_MUSCA_A1_NS
|
||||
struct serial_s {
|
||||
struct uart_pl011_dev_t *uart_dev;
|
||||
UARTName uart_index; /* UART device number */
|
||||
|
@ -38,7 +37,6 @@ struct serial_s {
|
|||
IRQn_Type rx_irq;
|
||||
IRQn_Type rx_timeout_irq;
|
||||
};
|
||||
#endif // TARGET_MUSCA_A1_NS
|
||||
|
||||
#if DEVICE_FLASH
|
||||
struct flash_s {
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Arm Limited. All rights reserved
|
||||
*
|
||||
* 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__
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
|
||||
// <i> Configuration settings for Driver_ISRAM0_MPC in component ::Drivers:MPC
|
||||
#define RTE_ISRAM0_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
|
||||
// <i> Configuration settings for Driver_SRAM1_MPC in component ::Drivers:MPC
|
||||
#define RTE_ISRAM1_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
|
||||
// <i> Configuration settings for Driver_ISRAM2_MPC in component ::Drivers:MPC
|
||||
#define RTE_ISRAM2_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM3_MPC]
|
||||
// <i> Configuration settings for Driver_SRAM2_MPC in component ::Drivers:MPC
|
||||
#define RTE_ISRAM3_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_SRAM3_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
|
||||
// <i> Configuration settings for Driver_CODE_SRAM_MPC in component ::Drivers:MPC
|
||||
#define RTE_CODE_SRAM_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
|
||||
// <i> Configuration settings for Driver_QSPI_MPC in component ::Drivers:MPC
|
||||
#define RTE_QSPI_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_EFLASH0_MPC]
|
||||
// <i> Configuration settings for Driver_EFLASH0_MPC in component ::Drivers:MPC
|
||||
#define RTE_EFLASH0_MPC 1
|
||||
// </e> MPC (Memory Protection Controller) [Driver_EFLASH0_MPC]
|
||||
|
||||
// <e> MPC (Memory Protection Controller) [Driver_EFLASH1_MPC]
|
||||
// <i> Configuration settings for Driver_EFLASH1_MPC in component ::Drivers:MPC
|
||||
#define RTE_EFLASH1_MPC 0
|
||||
// </e> MPC (Memory Protection Controller) [Driver_EFLASH1_MPC]
|
||||
|
||||
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
|
||||
// <i> Configuration settings for Driver_USART0 in component ::Drivers:USART
|
||||
#define RTE_USART0 1
|
||||
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
|
||||
|
||||
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
|
||||
// <i> Configuration settings for Driver_USART1 in component ::Drivers:USART
|
||||
#define RTE_USART1 1
|
||||
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
|
||||
// <i> Configuration settings for Driver_AHB_PPC0 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPC0 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
|
||||
// <i> Configuration settings for Driver_AHB_PPCEXP0 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPCEXP0 1
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
|
||||
// <i> Configuration settings for Driver_AHB_PPCEXP1 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPCEXP1 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
|
||||
// <i> Configuration settings for Driver_AHB_PPCEXP2 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPCEXP2 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
|
||||
// <i> Configuration settings for Driver_AHB_PPCEXP3 in component ::Drivers:PPC
|
||||
#define RTE_AHB_PPCEXP3 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
|
||||
// <i> Configuration settings for Driver_APB_PPC0 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPC0 1
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
|
||||
// <i> Configuration settings for Driver_APB_PPC1 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPC1 1
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
|
||||
// <i> Configuration settings for Driver_APB_PPCEXP0 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPCEXP0 1
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
|
||||
// <i> Configuration settings for Driver_APB_PPCEXP1 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPCEXP1 1
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
|
||||
// <i> Configuration settings for Driver_APB_PPCEXP2 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPCEXP2 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
|
||||
|
||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
|
||||
// <i> Configuration settings for Driver_APB_PPCEXP3 in component ::Drivers:PPC
|
||||
#define RTE_APB_PPCEXP3 0
|
||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
|
||||
|
||||
// <e> FLASH (Flash Memory) [Driver_FLASH0]
|
||||
// <i> Configuration settings for Driver_FLASH0 in component ::Drivers:FLASH
|
||||
#define RTE_FLASH0 1
|
||||
// </e> FLASH (Flash Memory) [Driver_FLASH0]
|
||||
|
||||
#endif /* __RTE_DEVICE_H__ */
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 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_description.h"
|
||||
#include "device_definition.h"
|
||||
|
||||
#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 MPC_EFLASH0_DEV MPC_EFLASH0_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_B1_SCC_DEV MUSCA_B1_SCC_DEV_S
|
||||
|
||||
#endif /* __CMSIS_DRIVER_CONFIG_H__ */
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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 */
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* 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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,970 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2019 Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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_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);
|
||||
|
||||
if (ret != PPC_SSE200_ERR_NONE) {
|
||||
return ARM_DRIVER_ERROR;
|
||||
}
|
||||
|
||||
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 */
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
* 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 __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__ */
|
|
@ -1,901 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-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 <stdlib.h>
|
||||
/* Use memcpy function */
|
||||
#include <string.h>
|
||||
|
||||
#include "mt25ql_flash_lib.h"
|
||||
#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 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
|
||||
|
||||
/*
|
||||
* 10 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 10U
|
||||
#define FAST_READ_DUMMY_CYCLES 8U
|
||||
#define RESET_STATE_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 f_state)
|
||||
{
|
||||
enum qspi_ip6514e_error_t controller_error;
|
||||
enum mt25ql_error_t library_error;
|
||||
|
||||
switch(f_state) {
|
||||
case MT25QL_FUNC_STATE_DEFAULT:
|
||||
dev->config_state.spi_mode = QSPI_IP6514E_SPI_MODE;
|
||||
dev->config_state.opcode_read = READ_CMD;
|
||||
dev->config_state.dummy_cycles_read = DEFAULT_READ_DUMMY_CYCLES;
|
||||
dev->config_state.opcode_write = PAGE_PROGRAM_CMD;
|
||||
dev->config_state.dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
|
||||
break;
|
||||
case MT25QL_FUNC_STATE_FAST:
|
||||
dev->config_state.spi_mode = QSPI_IP6514E_SPI_MODE;
|
||||
dev->config_state.opcode_read = FAST_READ_CMD;
|
||||
dev->config_state.dummy_cycles_read = FAST_READ_DUMMY_CYCLES;
|
||||
dev->config_state.opcode_write = PAGE_PROGRAM_CMD;
|
||||
dev->config_state.dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
|
||||
break;
|
||||
case MT25QL_FUNC_STATE_QUAD_FAST:
|
||||
dev->config_state.spi_mode = QSPI_IP6514E_QSPI_MODE;
|
||||
dev->config_state.opcode_read = QUAD_OUTPUT_FAST_READ_CMD;
|
||||
dev->config_state.dummy_cycles_read =
|
||||
QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES;
|
||||
dev->config_state.opcode_write = QUAD_INPUT_FAST_PROGRAM_CMD;
|
||||
dev->config_state.dummy_cycles_write =
|
||||
QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES;
|
||||
break;
|
||||
default:
|
||||
return MT25QL_ERR_WRONG_ARGUMENT;
|
||||
}
|
||||
|
||||
dev->config_state.func_state = f_state;
|
||||
|
||||
/* 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, dev->config_state.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, dev->config_state.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, dev->config_state.opcode_read,
|
||||
dev->config_state.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, dev->config_state.opcode_write,
|
||||
dev->config_state.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);
|
||||
|
||||
return MT25QL_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mt25ql_error_t mt25ql_restore_reset_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 direct read commands. */
|
||||
library_error = change_dummy_cycles(dev, RESET_STATE_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->config_state = (struct mt25ql_config_state_t){ 0 };
|
||||
dev->config_state.func_state = MT25QL_FUNC_STATE_NOT_INITED;
|
||||
|
||||
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;
|
||||
|
||||
if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
|
||||
return MT25QL_ERR_NOT_INITED;
|
||||
}
|
||||
|
||||
for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
|
||||
controller_error = qspi_ip6514e_send_read_cmd(
|
||||
dev->controller,
|
||||
dev->config_state.opcode_read,
|
||||
data, CMD_DATA_MAX_SIZE, addr,
|
||||
ADDR_BYTES,
|
||||
dev->config_state.dummy_cycles_read);
|
||||
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,
|
||||
dev->config_state.opcode_read,
|
||||
data, len, addr, ADDR_BYTES,
|
||||
dev->config_state.dummy_cycles_read);
|
||||
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;
|
||||
|
||||
if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
|
||||
return MT25QL_ERR_NOT_INITED;
|
||||
}
|
||||
|
||||
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, dev->config_state.opcode_write,
|
||||
data, CMD_DATA_MAX_SIZE, addr,
|
||||
ADDR_BYTES,
|
||||
dev->config_state.dummy_cycles_write);
|
||||
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,
|
||||
dev->config_state.opcode_write,
|
||||
data, CMD_DATA_MAX_SIZE, addr,
|
||||
ADDR_BYTES,
|
||||
dev->config_state.dummy_cycles_write);
|
||||
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, dev->config_state.opcode_write,
|
||||
data, len, addr, ADDR_BYTES,
|
||||
dev->config_state.dummy_cycles_write);
|
||||
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,
|
||||
dev->config_state.opcode_write,
|
||||
data, len, addr, ADDR_BYTES,
|
||||
dev->config_state.dummy_cycles_write);
|
||||
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;
|
||||
|
||||
if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
|
||||
return MT25QL_ERR_NOT_INITED;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_NOT_INITED,
|
||||
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_NOT_INITED = 0U,
|
||||
/*!< QSPI Flash controller is not initialized, only direct read
|
||||
* is guaranteed to be working
|
||||
*/
|
||||
MT25QL_FUNC_STATE_DEFAULT = 1U,
|
||||
/*!< The QSPI Flash controller and memory is in default state,
|
||||
* using basic read/write commands
|
||||
*/
|
||||
MT25QL_FUNC_STATE_FAST = 2U,
|
||||
/*!< 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 = 3U,
|
||||
/*!< 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_config_state_t {
|
||||
enum mt25ql_functional_state_t func_state;
|
||||
/*!< Functional state id */
|
||||
enum qspi_ip6514e_spi_mode_t spi_mode;
|
||||
/*!< SPI mode for the current functional state */
|
||||
uint8_t opcode_read;
|
||||
/*!< Read opcode for the current functional state */
|
||||
uint8_t opcode_write;
|
||||
/*!< Write opcode for the current functional state */
|
||||
uint32_t dummy_cycles_read;
|
||||
/*!< Dummy cycles for the read command for the current functional state */
|
||||
uint32_t dummy_cycles_write;
|
||||
/*!< Dummy cycles for the write command for the current functional state */
|
||||
};
|
||||
|
||||
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 */
|
||||
struct mt25ql_config_state_t config_state;
|
||||
/*!< Configured functional state (with 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] f_state Functional state 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 f_state);
|
||||
|
||||
/**
|
||||
* \brief Restore the QSPI Flash controller and MT25QL to reset 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_reset_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__ */
|
|
@ -1,153 +0,0 @@
|
|||
#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018-2020 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 // 0x1A020400
|
||||
#endif
|
||||
|
||||
#if !defined(MBED_ROM_SIZE)
|
||||
#define MBED_ROM_SIZE IMAGE_S_CODE_SIZE // 0x4f800
|
||||
#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 // 0x40000
|
||||
#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)
|
||||
device_definition.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)
|
||||
device_definition.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 {
|
||||
}
|
||||
}
|
|
@ -1,291 +0,0 @@
|
|||
;/*
|
||||
; * Copyright (c) 2017-2020 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 >>> ------------------
|
||||
;*/
|
||||
|
||||
|
||||
; <h> Stack Configuration
|
||||
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
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 0 ; 20: Reserved
|
||||
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 CPUn_CTI_0_IRQHandler ; 28: CPUn CTI Interrupt 0
|
||||
DCD CPUn_CTI_1_IRQHandler ; 29: CPUn CTI Interrupt 1
|
||||
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 GPIO_Combined_IRQHandler ; 67: GPIO 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 GPIO_Combined_NS_IRQHandler ; 76: GPIO Combined Non-secure interrupt
|
||||
DCD SDIO_IRQHandler ; 77: SDIO interrupt handler
|
||||
DCD 0 ; 78: Reserved
|
||||
DCD 0 ; 79: Reserved
|
||||
DCD 0 ; 80: Reserved
|
||||
DCD 0 ; 81: Reserved
|
||||
DCD 0 ; 82: Reserved
|
||||
DCD 0 ; 83: Reserved
|
||||
DCD CryptoSS_Reset_Status_IRQHandler ; 84: Crypto SS reset status
|
||||
DCD HostMHUS0_Int_Acc_NR2R_IRQHandler ; 85: MHU0 Sender IRQ not-ready to ready
|
||||
DCD HostMHUS0_Int_Acc_R2NR_IRQHandler ; 86: MHU0 Sender IRQ ready to not ready
|
||||
DCD HostMHUR0_IRQ_Reg0_IRQHandler ; 87: MHU0 Receiver IRQ Register 0
|
||||
DCD HostMHUR0_IRQ_Reg1_IRQHandler ; 88: MHU0 Receiver IRQ Register 1
|
||||
DCD HostMHUR0_IRQComb_IRQHandler ; 89: MHU0 Receiver IRQ combined
|
||||
DCD HostMHUS1_Int_Acc_NR2R_IRQHandler ; 90: MHU1 Sender IRQ not-ready to ready
|
||||
DCD HostMHUS1_Int_Acc_R2NR_IRQHandler ; 91: MHU1 Sender IRQ ready to not ready
|
||||
DCD HostMHUR1_IRQ_Reg0_IRQHandler ; 92: MHU1 Receiver IRQ Register 0
|
||||
DCD HostMHUR1_IRQ_Reg1_IRQHandler ; 93: MHU1 Receiver IRQ Register 1
|
||||
DCD HostMHUR1_IRQComb_IRQHandler ; 94: MHU1 Receiver IRQ combined
|
||||
DCD EFlash0_Controller_IRQHandler ; 95: GFC-100 EFlash 0 controller interrupt
|
||||
DCD EFlash1_Controller_IRQHandler ; 96: GFC-100 EFlash 1 controller interrupt
|
||||
DCD 0 ; 97:127 Reserved
|
||||
|
||||
|
||||
__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 .
|
||||
|
||||
ALIGN 4
|
||||
|
||||
; 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 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 CPUn_CTI_0_IRQHandler
|
||||
Default_Handler CPUn_CTI_1_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 GPIO_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 GPIO_Combined_NS_IRQHandler
|
||||
Default_Handler SDIO_IRQHandler
|
||||
Default_Handler CryptoSS_Reset_Status_IRQHandler
|
||||
Default_Handler HostMHUS0_Int_Acc_NR2R_IRQHandler
|
||||
Default_Handler HostMHUS0_Int_Acc_R2NR_IRQHandler
|
||||
Default_Handler HostMHUR0_IRQ_Reg0_IRQHandler
|
||||
Default_Handler HostMHUR0_IRQ_Reg1_IRQHandler
|
||||
Default_Handler HostMHUR0_IRQComb_IRQHandler
|
||||
Default_Handler HostMHUS1_Int_Acc_NR2R_IRQHandler
|
||||
Default_Handler HostMHUS1_Int_Acc_R2NR_IRQHandler
|
||||
Default_Handler HostMHUR1_IRQ_Reg0_IRQHandler
|
||||
Default_Handler HostMHUR1_IRQ_Reg1_IRQHandler
|
||||
Default_Handler HostMHUR1_IRQComb_IRQHandler
|
||||
Default_Handler EFlash0_Controller_IRQHandler
|
||||
Default_Handler EFlash1_Controller_IRQHandler
|
||||
|
||||
|
||||
ALIGN
|
||||
|
||||
END
|
|
@ -1,366 +0,0 @@
|
|||
;/*
|
||||
; * Copyright (c) 2018-2020 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 : ALIGN(32)
|
||||
{
|
||||
*(.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);
|
||||
PROVIDE(__StackTop = __stack);
|
||||
PROVIDE(__StackLimit = __StackTop - SIZEOF(.psp_stack));
|
||||
}
|
|
@ -1,401 +0,0 @@
|
|||
;/*
|
||||
; * Copyright (c) 2009-2020 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 0 /* 20: Reserved */
|
||||
.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 GPIO_Combined_IRQHandler /* 67: GPIO 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 GPIO_Combined_NS_IRQHandler /* 76: GPIO Combined Non-secure interrupt */
|
||||
.long SDIO_IRQHandler /* 77: SDIO interrupt handler */
|
||||
.long 0 /* 78 Reserved */
|
||||
.long 0 /* 79 Reserved */
|
||||
.long 0 /* 80 Reserved */
|
||||
.long 0 /* 81 Reserved */
|
||||
.long 0 /* 82 Reserved */
|
||||
.long 0 /* 83 Reserved */
|
||||
.long CryptoSS_Reset_Status_IRQHandler /* 84: Crypto SS reset status */
|
||||
.long HostMHUS0_Int_Acc_NR2R_IRQHandler /* 85: MHU0 Sender IRQ not-ready to ready */
|
||||
.long HostMHUS0_Int_Acc_R2NR_IRQHandler /* 86: MHU0 Sender IRQ ready to not ready */
|
||||
.long HostMHUR0_IRQ_Reg0_IRQHandler /* 87: MHU0 Receiver IRQ Register 0 */
|
||||
.long HostMHUR0_IRQ_Reg1_IRQHandler /* 88: MHU0 Receiver IRQ Register 1 */
|
||||
.long HostMHUR0_IRQComb_IRQHandler /* 89: MHU0 Receiver IRQ combined */
|
||||
.long HostMHUS1_Int_Acc_NR2R_IRQHandler /* 90: MHU1 Sender IRQ not-ready to ready */
|
||||
.long HostMHUS1_Int_Acc_R2NR_IRQHandler /* 91: MHU1 Sender IRQ ready to not ready */
|
||||
.long HostMHUR1_IRQ_Reg0_IRQHandler /* 92: MHU1 Receiver IRQ Register 0 */
|
||||
.long HostMHUR1_IRQ_Reg1_IRQHandler /* 93: MHU1 Receiver IRQ Register 1 */
|
||||
.long HostMHUR1_IRQComb_IRQHandler /* 94: MHU1 Receiver IRQ combined */
|
||||
.long EFlash0_Controller_IRQHandler /* 95: GFC-100 EFlash 0 controller interrupt */
|
||||
.long EFlash1_Controller_IRQHandler /* 96: GFC-100 EFlash 1 controller interrupt */
|
||||
.long 0 /* 97:127 Reserved */
|
||||
|
||||
|
||||
.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 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 GPIO_Combined_IRQHandler /* 67: GPIO 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 GPIO_Combined_NS_IRQHandler /* 76: GPIO Combined Non-secure interrupt */
|
||||
def_irq_handler SDIO_IRQHandler /* 77: SDIO interrupt handler */
|
||||
def_irq_handler CryptoSS_Reset_Status_IRQHandler /* 84: Crypto SS reset status */
|
||||
def_irq_handler HostMHUS0_Int_Acc_NR2R_IRQHandler /* 85: MHU0 Sender IRQ not-ready to ready */
|
||||
def_irq_handler HostMHUS0_Int_Acc_R2NR_IRQHandler /* 86: MHU0 Sender IRQ ready to not ready */
|
||||
def_irq_handler HostMHUR0_IRQ_Reg0_IRQHandler /* 87: MHU0 Receiver IRQ Register 0 */
|
||||
def_irq_handler HostMHUR0_IRQ_Reg1_IRQHandler /* 88: MHU0 Receiver IRQ Register 1 */
|
||||
def_irq_handler HostMHUR0_IRQComb_IRQHandler /* 89: MHU0 Receiver IRQ combined */
|
||||
def_irq_handler HostMHUS1_Int_Acc_NR2R_IRQHandler /* 90: MHU1 Sender IRQ not-ready to ready */
|
||||
def_irq_handler HostMHUS1_Int_Acc_R2NR_IRQHandler /* 91: MHU1 Sender IRQ ready to not ready */
|
||||
def_irq_handler HostMHUR1_IRQ_Reg0_IRQHandler /* 92: MHU1 Receiver IRQ Register 0 */
|
||||
def_irq_handler HostMHUR1_IRQ_Reg1_IRQHandler /* 93: MHU1 Receiver IRQ Register 1 */
|
||||
def_irq_handler HostMHUR1_IRQComb_IRQHandler /* 94: MHU1 Receiver IRQ combined */
|
||||
def_irq_handler EFlash0_Controller_IRQHandler /* 95: GFC-100 EFlash 0 controller interrupt */
|
||||
def_irq_handler EFlash1_Controller_IRQHandler /* 96: GFC-100 EFlash 1 controller interrupt */
|
||||
|
||||
|
||||
.end
|
|
@ -1,791 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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_sie_drv.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "cmsis_compiler.h"
|
||||
|
||||
/* Values for hardware version in PIDR0 reg */
|
||||
#define SIE200 0x60
|
||||
#define SIE300 0x65
|
||||
|
||||
#define MPC_SIE_BLK_CFG_OFFSET 5U
|
||||
|
||||
/* Defines with numbering (eg: SIE300) are only relevant to the given SIE
|
||||
* version. Defines without the numbering are applicable to all SIE versions.
|
||||
*/
|
||||
|
||||
/* CTRL register bit indexes */
|
||||
#define MPC_SIE200_CTRL_SEC_RESP (1UL << 4UL) /* MPC fault triggers a
|
||||
* bus error
|
||||
*/
|
||||
#define MPC_SIE300_CTRL_GATE_REQ (1UL << 6UL) /* Request for gating
|
||||
* incoming transfers
|
||||
*/
|
||||
#define MPC_SIE300_CTRL_GATE_ACK (1UL << 7UL) /* Acknowledge for gating
|
||||
* incoming transfers
|
||||
*/
|
||||
#define MPC_SIE_CTRL_AUTOINCREMENT (1UL << 8UL) /* BLK_IDX auto increment */
|
||||
#define MPC_SIE300_CTRL_SEC_RESP (1UL << 16UL) /* Response type when SW
|
||||
* asks to gate the transfer
|
||||
*/
|
||||
#define MPC_SIE300_CTRL_GATE_PRESENT (1UL << 23UL) /* Gating feature present */
|
||||
#define MPC_SIE_CTRL_SEC_LOCK_DOWN (1UL << 31UL) /* MPC Security lock down */
|
||||
|
||||
/* PIDR register bit masks */
|
||||
#define MPC_PIDR0_SIE_VERSION_MASK ((1UL << 8UL) - 1UL)
|
||||
|
||||
/* ARM MPC interrupt */
|
||||
#define MPC_SIE_INT_BIT (1UL)
|
||||
|
||||
/* Error code returned by the internal driver functions */
|
||||
enum mpc_sie_intern_error_t {
|
||||
MPC_SIE_INTERN_ERR_NONE = MPC_SIE_ERR_NONE,
|
||||
MPC_SIE_INTERN_ERR_NOT_IN_RANGE = MPC_SIE_ERR_NOT_IN_RANGE,
|
||||
MPC_SIE_INTERN_ERR_NOT_ALIGNED = MPC_SIE_ERR_NOT_ALIGNED,
|
||||
MPC_SIE_INTERN_ERR_INVALID_RANGE = MPC_SIE_ERR_INVALID_RANGE,
|
||||
MPC_INTERN_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE =
|
||||
MPC_SIE_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_SIE_INTERN_ERR_BLK_IDX_TOO_HIGH = -1,
|
||||
|
||||
};
|
||||
|
||||
/* ARM MPC memory mapped register access structure */
|
||||
struct mpc_sie_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[998]; /* 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 initialize \ref mpc_sie_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_sie_dev_t* dev,
|
||||
uint32_t addr,
|
||||
const struct mpc_sie_memory_range_t** addr_range)
|
||||
{
|
||||
uint32_t i;
|
||||
const struct mpc_sie_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_sie_intern_error_t
|
||||
*/
|
||||
static enum mpc_sie_intern_error_t get_lut_masks(
|
||||
struct mpc_sie_dev_t* dev,
|
||||
const uint32_t base, const uint32_t limit,
|
||||
const struct mpc_sie_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_sie_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_sie_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_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_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_SIE_INTERN_ERR_NOT_IN_RANGE;
|
||||
}
|
||||
|
||||
/* Base and limit should be part of the same range */
|
||||
if(base_range != limit_range) {
|
||||
return MPC_SIE_INTERN_ERR_INVALID_RANGE;
|
||||
}
|
||||
*range = base_range;
|
||||
|
||||
block_size = (1 << (p_mpc->blk_cfg + MPC_SIE_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_SIE_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_SIE_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_SIE_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_SIE_INTERN_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_init(struct mpc_sie_dev_t* dev,
|
||||
const struct mpc_sie_memory_range_t** range_list,
|
||||
uint8_t nbr_of_ranges)
|
||||
{
|
||||
if((range_list == NULL) || (nbr_of_ranges == 0)) {
|
||||
return MPC_SIE_INVALID_ARG;
|
||||
}
|
||||
|
||||
dev->data->sie_version = get_sie_version(dev);
|
||||
|
||||
if ((dev->data->sie_version != SIE200) &&
|
||||
(dev->data->sie_version != SIE300)) {
|
||||
return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION;
|
||||
}
|
||||
|
||||
dev->data->range_list = range_list;
|
||||
dev->data->nbr_of_ranges = nbr_of_ranges;
|
||||
dev->data->is_initialized = true;
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_get_block_size(struct mpc_sie_dev_t* dev,
|
||||
uint32_t* blk_size)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_NOT_INIT;
|
||||
}
|
||||
|
||||
if(blk_size == 0) {
|
||||
return MPC_SIE_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Calculate the block size in byte according to the manual */
|
||||
*blk_size = (1 << (p_mpc->blk_cfg + MPC_SIE_BLK_CFG_OFFSET));
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_config_region(struct mpc_sie_dev_t* dev,
|
||||
const uint32_t base,
|
||||
const uint32_t limit,
|
||||
enum mpc_sie_sec_attr_t attr)
|
||||
{
|
||||
enum mpc_sie_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_sie_memory_range_t* range;
|
||||
uint32_t word_value;
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_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_SIE_INTERN_ERR_NONE) {
|
||||
/* Map internal error code lower than 0 to a generic errpr */
|
||||
if(error < 0) {
|
||||
return MPC_SIE_ERR_INVALID_RANGE;
|
||||
}
|
||||
return (enum mpc_sie_error_t)error;
|
||||
}
|
||||
|
||||
/*
|
||||
* The memory range should allow accesses in with the wanted security
|
||||
* attribute if it requires special attribute for successful accesses
|
||||
*/
|
||||
if(range->attr != attr) {
|
||||
return MPC_SIE_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_SIE_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_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
/* First word */
|
||||
word_value = p_mpc->blk_lutn;
|
||||
if(attr == MPC_SIE_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; i<limit_word_idx; i++) {
|
||||
p_mpc->blk_idx = i;
|
||||
if(attr == MPC_SIE_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_SIE_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_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_get_region_config(
|
||||
struct mpc_sie_dev_t* dev,
|
||||
uint32_t base, uint32_t limit,
|
||||
enum mpc_sie_sec_attr_t* attr)
|
||||
{
|
||||
enum mpc_sie_sec_attr_t attr_prev;
|
||||
uint32_t block_size;
|
||||
uint32_t block_size_mask;
|
||||
enum mpc_sie_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_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
const struct mpc_sie_memory_range_t* range;
|
||||
uint32_t word_value;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_NOT_INIT;
|
||||
}
|
||||
|
||||
if(attr == 0) {
|
||||
return MPC_SIE_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_SIE_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_SIE_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_SIE_INTERN_ERR_NONE) {
|
||||
/* Map internal error code lower than 0 to generic error */
|
||||
if(error < 0) {
|
||||
return MPC_SIE_ERR_INVALID_RANGE;
|
||||
}
|
||||
return (enum mpc_sie_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_SIE_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_SIE_SEC_ATTR_MIXED;
|
||||
} else {
|
||||
*attr = MPC_SIE_SEC_ATTR_NONSECURE;
|
||||
}
|
||||
return MPC_SIE_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_SIE_SEC_ATTR_SECURE;
|
||||
} else if(word_value ^ first_word_mask) {
|
||||
*attr = MPC_SIE_SEC_ATTR_MIXED;
|
||||
/*
|
||||
* Bail out as the security attribute will be the same regardless
|
||||
* of the configuration of other blocks
|
||||
*/
|
||||
return MPC_SIE_ERR_NONE;
|
||||
} else {
|
||||
*attr = MPC_SIE_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; i<limit_word_idx; i++) {
|
||||
p_mpc->blk_idx = i;
|
||||
word_value = p_mpc->blk_lutn;
|
||||
if(word_value == 0x00000000) {
|
||||
*attr = MPC_SIE_SEC_ATTR_SECURE;
|
||||
} else if(word_value == 0xFFFFFFFF) {
|
||||
*attr = MPC_SIE_SEC_ATTR_NONSECURE;
|
||||
} else {
|
||||
*attr = MPC_SIE_SEC_ATTR_MIXED;
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
/* If the attribute is different than the one found before, bail out */
|
||||
if(*attr != attr_prev) {
|
||||
*attr = MPC_SIE_SEC_ATTR_MIXED;
|
||||
return MPC_SIE_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_SIE_SEC_ATTR_SECURE;
|
||||
} else if(word_value ^ first_word_mask) {
|
||||
*attr = MPC_SIE_SEC_ATTR_MIXED;
|
||||
return MPC_SIE_ERR_NONE;
|
||||
} else {
|
||||
*attr = MPC_SIE_SEC_ATTR_NONSECURE;
|
||||
}
|
||||
|
||||
if(*attr != attr_prev) {
|
||||
*attr = MPC_SIE_SEC_ATTR_MIXED;
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_get_ctrl(struct mpc_sie_dev_t* dev,
|
||||
uint32_t* ctrl_val)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_NOT_INIT;
|
||||
}
|
||||
|
||||
if(ctrl_val == 0) {
|
||||
return MPC_SIE_INVALID_ARG;
|
||||
}
|
||||
|
||||
*ctrl_val = p_mpc->ctrl;
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_set_ctrl(struct mpc_sie_dev_t* dev,
|
||||
uint32_t mpc_ctrl)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_NOT_INIT;
|
||||
}
|
||||
|
||||
p_mpc->ctrl = mpc_ctrl;
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_get_sec_resp(struct mpc_sie_dev_t* dev,
|
||||
enum mpc_sie_sec_resp_t* sec_rep)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
bool gating_present = false;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_NOT_INIT;
|
||||
}
|
||||
|
||||
if(sec_rep == NULL) {
|
||||
return MPC_SIE_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (dev->data->sie_version == SIE200) {
|
||||
if(p_mpc->ctrl & MPC_SIE200_CTRL_SEC_RESP) {
|
||||
*sec_rep = MPC_SIE_RESP_BUS_ERROR;
|
||||
} else {
|
||||
*sec_rep = MPC_SIE_RESP_RAZ_WI;
|
||||
}
|
||||
|
||||
} else if (dev->data->sie_version == SIE300) {
|
||||
mpc_sie_is_gating_present(dev, &gating_present);
|
||||
if (!gating_present) {
|
||||
return MPC_SIE_ERR_GATING_NOT_PRESENT;
|
||||
}
|
||||
|
||||
if(p_mpc->ctrl & MPC_SIE300_CTRL_SEC_RESP) {
|
||||
/* MPC returns a BUS ERROR response */
|
||||
*sec_rep = MPC_SIE_RESP_BUS_ERROR;
|
||||
} else {
|
||||
/* MPC sets the ready signals LOW, which stalls any transactions */
|
||||
*sec_rep = MPC_SIE_RESP_WAIT_GATING_DISABLED;
|
||||
}
|
||||
} else {
|
||||
return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION;
|
||||
}
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_set_sec_resp(struct mpc_sie_dev_t* dev,
|
||||
enum mpc_sie_sec_resp_t sec_rep)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
bool gating_present = false;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_NOT_INIT;
|
||||
}
|
||||
|
||||
if (dev->data->sie_version == SIE200) {
|
||||
if (sec_rep == MPC_SIE_RESP_BUS_ERROR) {
|
||||
p_mpc->ctrl |= MPC_SIE200_CTRL_SEC_RESP;
|
||||
} else if (sec_rep == MPC_SIE_RESP_RAZ_WI) {
|
||||
p_mpc->ctrl &= ~MPC_SIE200_CTRL_SEC_RESP;
|
||||
} else {
|
||||
return MPC_SIE_INVALID_ARG;
|
||||
}
|
||||
|
||||
} else if (dev->data->sie_version == SIE300) {
|
||||
mpc_sie_is_gating_present(dev, &gating_present);
|
||||
if (!gating_present) {
|
||||
return MPC_SIE_ERR_GATING_NOT_PRESENT;
|
||||
}
|
||||
|
||||
if (sec_rep == MPC_SIE_RESP_BUS_ERROR) {
|
||||
p_mpc->ctrl |= MPC_SIE300_CTRL_SEC_RESP;
|
||||
} else if (sec_rep == MPC_SIE_RESP_WAIT_GATING_DISABLED) {
|
||||
p_mpc->ctrl &= ~MPC_SIE300_CTRL_SEC_RESP;
|
||||
} else {
|
||||
return MPC_SIE_INVALID_ARG;
|
||||
}
|
||||
|
||||
} else {
|
||||
return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION;
|
||||
}
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_irq_enable(struct mpc_sie_dev_t* dev)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_NOT_INIT;
|
||||
}
|
||||
|
||||
p_mpc->int_en |= MPC_SIE_INT_BIT;
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
void mpc_sie_irq_disable(struct mpc_sie_dev_t* dev)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
p_mpc->int_en &= ~MPC_SIE_INT_BIT;
|
||||
}
|
||||
|
||||
void mpc_sie_clear_irq(struct mpc_sie_dev_t* dev)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
p_mpc->int_clear = MPC_SIE_INT_BIT;
|
||||
}
|
||||
|
||||
uint32_t mpc_sie_irq_state(struct mpc_sie_dev_t* dev)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
return (p_mpc->int_stat & MPC_SIE_INT_BIT);
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_lock_down(struct mpc_sie_dev_t* dev)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_NOT_INIT;
|
||||
}
|
||||
|
||||
p_mpc->ctrl |= (MPC_SIE_CTRL_AUTOINCREMENT
|
||||
| MPC_SIE_CTRL_SEC_LOCK_DOWN);
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
enum mpc_sie_error_t mpc_sie_is_gating_present(struct mpc_sie_dev_t* dev,
|
||||
bool* gating_present)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->is_initialized != true) {
|
||||
return MPC_SIE_NOT_INIT;
|
||||
}
|
||||
|
||||
if (dev->data->sie_version != SIE300) {
|
||||
return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION;
|
||||
}
|
||||
|
||||
*gating_present = (bool)(p_mpc->ctrl & MPC_SIE300_CTRL_GATE_PRESENT);
|
||||
|
||||
return MPC_SIE_ERR_NONE;
|
||||
}
|
||||
|
||||
uint32_t get_sie_version(struct mpc_sie_dev_t* dev)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
return p_mpc->pidr0 & MPC_PIDR0_SIE_VERSION_MASK;
|
||||
}
|
||||
|
||||
bool mpc_sie_get_gate_ack(struct mpc_sie_dev_t* dev)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
return (bool)(p_mpc->ctrl & MPC_SIE300_CTRL_GATE_ACK);
|
||||
}
|
||||
|
||||
void mpc_sie_request_gating(struct mpc_sie_dev_t* dev)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
p_mpc->ctrl |= MPC_SIE300_CTRL_GATE_REQ;
|
||||
}
|
||||
|
||||
void mpc_sie_release_gating(struct mpc_sie_dev_t* dev)
|
||||
{
|
||||
struct mpc_sie_reg_map_t* p_mpc =
|
||||
(struct mpc_sie_reg_map_t*)dev->cfg->base;
|
||||
|
||||
p_mpc->ctrl &= ~MPC_SIE300_CTRL_GATE_REQ;
|
||||
}
|
|
@ -1,354 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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_sie_drv.h
|
||||
* \brief Generic driver for ARM SIE Memory Protection
|
||||
* Controllers (MPC).
|
||||
*/
|
||||
|
||||
#ifndef __MPC_SIE__DRV_H__
|
||||
#define __MPC_SIE__DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Error code returned by the driver functions */
|
||||
enum mpc_sie_error_t {
|
||||
MPC_SIE_ERR_NONE, /*!< No error */
|
||||
MPC_SIE_INVALID_ARG, /*!< MPC invalid input arguments */
|
||||
MPC_SIE_NOT_INIT, /*!< MPC not initialized */
|
||||
MPC_SIE_ERR_NOT_IN_RANGE, /*!< Address does not belong to a range
|
||||
* controlled by the MPC */
|
||||
MPC_SIE_ERR_NOT_ALIGNED, /*!< Address is not aligned on the block size
|
||||
* of this MPC
|
||||
*/
|
||||
MPC_SIE_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_SIE_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE, /*!< The given range cannot be
|
||||
* accessed with the wanted
|
||||
* security attributes
|
||||
*/
|
||||
MPC_SIE_UNSUPPORTED_HARDWARE_VERSION, /*!< MPC hardware version read from
|
||||
* PIDR0 is not supported
|
||||
*/
|
||||
MPC_SIE_ERR_GATING_NOT_PRESENT /*!< MPC gating not present in HW */
|
||||
};
|
||||
|
||||
/* Security attribute used in various place of the API */
|
||||
enum mpc_sie_sec_attr_t {
|
||||
MPC_SIE_SEC_ATTR_SECURE, /*!< Secure attribute */
|
||||
MPC_SIE_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_SIE_SEC_ATTR_MIXED,
|
||||
};
|
||||
|
||||
/* What can happen when trying to do an illegal memory access */
|
||||
enum mpc_sie_sec_resp_t {
|
||||
MPC_SIE_RESP_RAZ_WI, /*!< Read As Zero, Write Ignored */
|
||||
MPC_SIE_RESP_BUS_ERROR, /*!< Bus error */
|
||||
MPC_SIE_RESP_WAIT_GATING_DISABLED /*!< Wait until gating is disabled */
|
||||
};
|
||||
|
||||
/* Description of a memory range controlled by the MPC */
|
||||
struct mpc_sie_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_sie_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 device configuration structure */
|
||||
struct mpc_sie_dev_cfg_t {
|
||||
const uint32_t base; /*!< MPC base address */
|
||||
};
|
||||
|
||||
/* ARM MPC SIE device data structure */
|
||||
struct mpc_sie_dev_data_t {
|
||||
/*!< Array of pointers to memory ranges controlled by the MPC */
|
||||
const struct mpc_sie_memory_range_t** range_list;
|
||||
uint8_t nbr_of_ranges; /*!< Number of memory ranges in the list */
|
||||
bool is_initialized; /*!< Indicates if the MPC driver
|
||||
* is initialized and enabled
|
||||
*/
|
||||
uint32_t sie_version; /*!< SIE version */
|
||||
};
|
||||
|
||||
/* ARM MPC SIE device structure */
|
||||
struct mpc_sie_dev_t {
|
||||
const struct mpc_sie_dev_cfg_t* const cfg; /*!< MPC configuration */
|
||||
struct mpc_sie_dev_data_t* const data; /*!< MPC data */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initializes a MPC device.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
* \param[in] range_list List of memory ranges controller by the MPC
|
||||
* (\ref mpc_sie_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_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_init(struct mpc_sie_dev_t* dev,
|
||||
const struct mpc_sie_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_sie_dev_t
|
||||
* \param[out] blk_size MPC block size
|
||||
*
|
||||
* \return Returns error code as specified in \ref mpc_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_get_block_size(struct mpc_sie_dev_t* dev,
|
||||
uint32_t* blk_size);
|
||||
|
||||
/**
|
||||
* \brief Configures a memory region (base and limit included).
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_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_sie_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_SIE_ATTR_MIXED.
|
||||
*
|
||||
* \return Returns error code as specified in \ref mpc_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_config_region(struct mpc_sie_dev_t* dev,
|
||||
const uint32_t base,
|
||||
const uint32_t limit,
|
||||
enum mpc_sie_sec_attr_t attr);
|
||||
|
||||
/**
|
||||
* \brief Gets a memory region configuration(base and limit included).
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_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_sie_sec_attr_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref mpc_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_get_region_config(struct mpc_sie_dev_t* dev,
|
||||
uint32_t base,
|
||||
uint32_t limit,
|
||||
enum mpc_sie_sec_attr_t* attr);
|
||||
|
||||
/**
|
||||
* \brief Gets the MPC control value.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
* \param[out] ctrl_val Current MPC control value.
|
||||
*
|
||||
* \return Returns error code as specified in \ref mpc_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_get_ctrl(struct mpc_sie_dev_t* dev,
|
||||
uint32_t* ctrl_val);
|
||||
|
||||
/**
|
||||
* \brief Sets the MPC control value.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
* \param[in] mpc_ctrl New MPC control value
|
||||
*
|
||||
* \return Returns error code as specified in \ref mpc_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_set_ctrl(struct mpc_sie_dev_t* dev,
|
||||
uint32_t mpc_ctrl);
|
||||
|
||||
/**
|
||||
* \brief Gets the configured secure response.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
* \param[out] sec_rep Configured secure response (\ref mpc_sie_sec_resp_t).
|
||||
*
|
||||
* \return Returns error code as specified in \ref mpc_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_get_sec_resp(struct mpc_sie_dev_t* dev,
|
||||
enum mpc_sie_sec_resp_t* sec_rep);
|
||||
|
||||
/**
|
||||
* \brief Sets the response type when SW asks to gate the incoming transfers.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
* \param[in] sec_rep Secure response to configure (\ref mpc_sie_sec_resp_t).
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_set_sec_resp(struct mpc_sie_dev_t* dev,
|
||||
enum mpc_sie_sec_resp_t sec_rep);
|
||||
|
||||
/**
|
||||
* \brief Enables MPC interrupt.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref mpc_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_irq_enable(struct mpc_sie_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables MPC interrupt
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void mpc_sie_irq_disable(struct mpc_sie_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Clears MPC interrupt.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void mpc_sie_clear_irq(struct mpc_sie_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns the MPC interrupt state.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_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_sie_irq_state(struct mpc_sie_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Locks down the MPC configuration.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref mpc_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_lock_down(struct mpc_sie_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns if gating is present in hardware.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
* \param[out] gating_present Returns if gating is present in hardware.
|
||||
*
|
||||
* \return Returns error code as specified in \ref mpc_sie_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum mpc_sie_error_t mpc_sie_is_gating_present(struct mpc_sie_dev_t* dev,
|
||||
bool* gating_present);
|
||||
|
||||
/**
|
||||
* \brief Returns the value of Peripheral ID 0 register.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
*
|
||||
* \return Returns the value of Peripheral ID 0 register.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t get_sie_version(struct mpc_sie_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Reads bit indicating acknowledge for gating incoming transfers.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
*
|
||||
* \return True if acknowledge is set.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
bool mpc_sie_get_gate_ack(struct mpc_sie_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets bit to request for gating incoming transfers.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void mpc_sie_request_gating(struct mpc_sie_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Clears bit to request for gating incoming transfers.
|
||||
*
|
||||
* \param[in] dev MPC device \ref mpc_sie_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void mpc_sie_release_gating(struct mpc_sie_dev_t* dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __MPC_SIE_DRV_H__ */
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mpu_armv8m_drv.h"
|
||||
#include "cmsis.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;
|
||||
|
||||
/*
|
||||
* FixMe: Set 3 pre-defined MAIR_ATTR for memory. The attributes come
|
||||
* from default memory map, need to check if fine-tune is necessary.
|
||||
*
|
||||
* MAIR0_0: Peripheral, Device-nGnRE.
|
||||
* MAIR0_1: Code, WT RA. Same attr for Outer and Inner.
|
||||
* MAIR0_2: SRAM, WBWA RA. Same attr for Outer and Inner.
|
||||
*/
|
||||
mpu->MAIR0 = (MPU_ARMV8M_MAIR_ATTR_DEVICE_VAL << MPU_MAIR0_Attr0_Pos) |
|
||||
(MPU_ARMV8M_MAIR_ATTR_CODE_VAL << MPU_MAIR0_Attr1_Pos) |
|
||||
(MPU_ARMV8M_MAIR_ATTR_DATA_VAL << MPU_MAIR0_Attr2_Pos);
|
||||
|
||||
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 */
|
||||
__DSB();
|
||||
__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;
|
||||
|
||||
limit_cfg |= (region_cfg->region_attridx << MPU_RLAR_AttrIndx_Pos) &
|
||||
MPU_RLAR_AttrIndx_Msk;
|
||||
|
||||
limit_cfg |= MPU_RLAR_EN_Msk;
|
||||
|
||||
mpu->RLAR = limit_cfg;
|
||||
|
||||
/*Restore main MPU control*/
|
||||
mpu->CTRL = ctrl_before;
|
||||
|
||||
/* Enable MPU before the next instruction */
|
||||
__DSB();
|
||||
__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;
|
||||
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MPU_ARMV8M_DRV_H__
|
||||
#define __MPU_ARMV8M_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PRIVILEGED_DEFAULT_ENABLE 1
|
||||
#define HARDFAULT_NMI_ENABLE 1
|
||||
|
||||
/* MAIR_ATTR */
|
||||
#define MPU_ARMV8M_MAIR_ATTR_DEVICE_VAL 0x04
|
||||
#define MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX 0
|
||||
#define MPU_ARMV8M_MAIR_ATTR_CODE_VAL 0xAA
|
||||
#define MPU_ARMV8M_MAIR_ATTR_CODE_IDX 1
|
||||
#define MPU_ARMV8M_MAIR_ATTR_DATA_VAL 0xFF
|
||||
#define MPU_ARMV8M_MAIR_ATTR_DATA_IDX 2
|
||||
|
||||
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;
|
||||
uint32_t region_attridx;
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MPU_ARMV8M_DRV_H__ */
|
|
@ -1,347 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019 Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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)
|
||||
/* Reserved 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)
|
||||
/* Reserved bits 8:15 */
|
||||
#define AHB_PPC0_INT_POS_MASK (1UL << 16)
|
||||
/* Reserved 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)
|
||||
/* Reserved 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);
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019 Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 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 initialized 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 initialized 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 initialized 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PPC_SSE_200_DRV_H__ */
|
|
@ -1,755 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-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 <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
/* Use memcpy */
|
||||
#include <string.h>
|
||||
|
||||
#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 (0x80080080U)
|
||||
#define DEVICE_READ_INSTR_REG_RESET_VALUE (0x080220EBU)
|
||||
#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);
|
||||
}
|
|
@ -1,416 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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__ */
|
|
@ -1,138 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2020 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_S
|
||||
|
||||
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 reset state */
|
||||
err = mt25ql_restore_reset_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;
|
||||
|
||||
address -= FLASH_DEV.direct_access_start_addr;
|
||||
|
||||
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;
|
||||
|
||||
address -= FLASH_DEV.direct_access_start_addr;
|
||||
|
||||
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;
|
||||
|
||||
address -= FLASH_DEV.direct_access_start_addr;
|
||||
|
||||
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 >= S_QSPI_ALIAS_BASE) && (address < S_QSPI_ALIAS_BASE + QSPI_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 S_QSPI_ALIAS_BASE;
|
||||
}
|
||||
|
||||
uint32_t flash_get_size(const flash_t *obj)
|
||||
{
|
||||
(void)(obj);
|
||||
return QSPI_FLASH_TOTAL_SIZE;
|
||||
}
|
||||
|
||||
uint8_t flash_get_erase_value(const flash_t *obj)
|
||||
{
|
||||
(void)obj;
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
#endif // DEVICE_FLASH
|
|
@ -1,102 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2020 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file implements APIS defined in hal/gpio_api.h
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "gpio_api.h"
|
||||
#include "pinmap.h"
|
||||
#include "objects.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
uint32_t gpio_set(PinName pin)
|
||||
{
|
||||
pin_function(pin, (int)PRIMARY_FUNC);
|
||||
|
||||
/* Return the correct mask of the given PIN */
|
||||
return (1 << GPIO_PIN_NUMBER(pin));
|
||||
}
|
||||
|
||||
void gpio_init(gpio_t *obj, PinName pin)
|
||||
{
|
||||
struct gpio_cmsdk_dev_t *gpio_dev;
|
||||
obj->pin_num = (uint32_t)NC;
|
||||
|
||||
if (pin >= PA0 && pin <= PA15) {
|
||||
#ifdef GPIO0_CMSDK_DEV
|
||||
gpio_dev = &GPIO0_CMSDK_DEV;
|
||||
#else
|
||||
error("GPIO associated with expansion pin %d, is disabled", pin);
|
||||
/* error() calls exit() eventually, but to be safe we return here */
|
||||
return;
|
||||
#endif
|
||||
|
||||
gpio_cmsdk_init(gpio_dev);
|
||||
|
||||
obj->gpio_dev = gpio_dev;
|
||||
obj->pin_num = pin;
|
||||
/* GPIO is input by default */
|
||||
obj->direction = PIN_INPUT;
|
||||
return;
|
||||
}
|
||||
|
||||
error("pin %d is not a GPIO", pin);
|
||||
}
|
||||
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
{
|
||||
pin_mode(obj->pin_num, mode);
|
||||
}
|
||||
|
||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||
{
|
||||
enum gpio_cmsdk_direction_t pin_dir =
|
||||
(direction == PIN_INPUT) ? GPIO_CMSDK_INPUT : GPIO_CMSDK_OUTPUT;
|
||||
|
||||
if (gpio_cmsdk_pin_config(obj->gpio_dev, obj->pin_num, pin_dir,
|
||||
GPIO_CMSDK_MAIN_FUNC) == GPIO_CMSDK_ERR_NONE) {
|
||||
obj->direction = direction;
|
||||
}
|
||||
}
|
||||
|
||||
int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
if (obj->pin_num == (uint32_t)NC) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_write(gpio_t *obj, int value)
|
||||
{
|
||||
enum gpio_cmsdk_error_t ret =
|
||||
gpio_cmsdk_pin_write(obj->gpio_dev, obj->pin_num, (uint32_t)value);
|
||||
|
||||
if (ret) {
|
||||
error("Can not write pin %d", obj->pin_num);
|
||||
}
|
||||
}
|
||||
|
||||
int gpio_read(gpio_t *obj)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
(void)gpio_cmsdk_pin_read(obj->gpio_dev, obj->pin_num, &data);
|
||||
|
||||
return (int)data;
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2020 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file implements APIS defined in hal/pinmap.h
|
||||
*
|
||||
* Pin functions are not available in interrupt context, because the
|
||||
* NS side is only allowed to call TF-M secure functions (veneers) from
|
||||
* the NS Thread mode.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mbed_assert.h"
|
||||
#include "mbed_error.h"
|
||||
#include "device_definition.h"
|
||||
#include "objects.h"
|
||||
#include "pinmap.h"
|
||||
#include "musca_b1_scc_drv.h"
|
||||
|
||||
/**
|
||||
* \brief Translates between different pin mode enums
|
||||
*
|
||||
* \param[in] mode Pin mode to translate \ref PinMode
|
||||
*
|
||||
* \return Translated pin mode \ref pinmode_select_t
|
||||
*/
|
||||
static enum pinmode_select_t translate_pinmode(PinMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case PullNone:
|
||||
return PINMODE_NONE;
|
||||
case PullDown:
|
||||
return PINMODE_PULL_DOWN;
|
||||
case PullUp:
|
||||
return PINMODE_PULL_UP;
|
||||
default:
|
||||
return PINMODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \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;
|
||||
uint32_t result = 0;
|
||||
|
||||
MBED_ASSERT(pin != NC);
|
||||
|
||||
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_B1_SCC_DEV
|
||||
result = musca_b1_scc_set_alt_func(&MUSCA_B1_SCC_DEV, flags, (1u<<pin));
|
||||
if (result != SCC_ERR_NONE) {
|
||||
error("Can not set pin alt func %d", pin);
|
||||
}
|
||||
#else
|
||||
error("SCC device associated with expansion pin %d, is disabled", pin);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets pin mode for the given GPIO pin
|
||||
*
|
||||
* \param[in] pin GPIO pin number \ref PinName
|
||||
* \param[in] mode Pin mode to set \ref PinMode
|
||||
*/
|
||||
void pin_mode(PinName pin, PinMode mode)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
MBED_ASSERT(pin != NC);
|
||||
|
||||
#ifdef MUSCA_B1_SCC_DEV
|
||||
result = musca_b1_scc_set_pinmode(&MUSCA_B1_SCC_DEV, (1u<<pin),
|
||||
translate_pinmode(mode));
|
||||
if (result != SCC_ERR_NONE) {
|
||||
error("Can not set pin mode %d", pin);
|
||||
}
|
||||
#else
|
||||
error("SCC device associated with expansion pin %d, is disabled", pin);
|
||||
#endif
|
||||
}
|
|
@ -1,324 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#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));
|
||||
}
|
|
@ -1,533 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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 "target_cfg.h"
|
||||
#include "Driver_MPC.h"
|
||||
#include "Driver_PPC.h"
|
||||
#include "platform_description.h"
|
||||
#include "device_definition.h"
|
||||
#include "region_defs.h"
|
||||
#include "tfm_secure_api.h"
|
||||
#include "mbed_assert.h"
|
||||
#include "platform_srv_impl.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(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_EFLASH0_MPC;
|
||||
extern ARM_DRIVER_MPC Driver_ISRAM0_MPC, Driver_ISRAM1_MPC;
|
||||
extern ARM_DRIVER_MPC Driver_ISRAM2_MPC, Driver_ISRAM3_MPC;
|
||||
|
||||
/* Import PPC driver */
|
||||
extern ARM_DRIVER_PPC Driver_APB_PPC0, Driver_APB_PPC1;
|
||||
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP0;
|
||||
extern ARM_DRIVER_PPC Driver_APB_PPCEXP0, Driver_APB_PPCEXP1;
|
||||
|
||||
/* 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 MASKS */
|
||||
#define DBG_CTRL_MASK_DBGEN (0x01 << 1)
|
||||
#define DBG_CTRL_MASK_NIDEN (0x01 << 2)
|
||||
#define DBG_CTRL_MASK_SPIDEN (0x01 << 3)
|
||||
#define DBG_CTRL_MASK_SPNIDEN (0x01 << 4)
|
||||
|
||||
#define DBG_CTRL_ADDR 0x50089E00UL
|
||||
|
||||
#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_B1_UART1_NS_BASE,
|
||||
MUSCA_B1_UART1_NS_BASE + 0xFFF,
|
||||
PPC_SP_DO_NOT_CONFIGURE,
|
||||
-1
|
||||
};
|
||||
|
||||
static ARM_DRIVER_PPC *const ppc_bank_drivers[] = {
|
||||
0, /* AHB PPC0 */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
&Driver_AHB_PPCEXP0, /* AHB PPCEXP0 */
|
||||
0, /* AHB PPCEXP1 */
|
||||
0, /* AHB PPCEXP2 */
|
||||
0, /* AHB PPCEXP3 */
|
||||
&Driver_APB_PPC0, /* APB PPC0 */
|
||||
&Driver_APB_PPC1, /* APB PPC1 */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
&Driver_APB_PPCEXP0, /* APB PPCEXP0 */
|
||||
&Driver_APB_PPCEXP1, /* APB PPCEXP1 */
|
||||
};
|
||||
|
||||
#define PPC_BANK_COUNT \
|
||||
(sizeof(ppc_bank_drivers)/sizeof(ppc_bank_drivers[0]))
|
||||
|
||||
void enable_fault_handlers(void)
|
||||
{
|
||||
/* Explicitly set secure fault priority to the highest */
|
||||
NVIC_SetPriority(SecureFault_IRQn, 0);
|
||||
|
||||
/* 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 uint32_t *dbg_ctrl_p = (uint32_t*)DBG_CTRL_ADDR;
|
||||
|
||||
#if defined(DAUTH_NONE)
|
||||
|
||||
*dbg_ctrl_p &= ~(DBG_CTRL_MASK_DBGEN |
|
||||
DBG_CTRL_MASK_NIDEN |
|
||||
DBG_CTRL_MASK_SPIDEN |
|
||||
DBG_CTRL_MASK_SPNIDEN);
|
||||
|
||||
#elif defined(DAUTH_NS_ONLY)
|
||||
*dbg_ctrl_p &= ~(DBG_CTRL_MASK_SPIDEN |
|
||||
DBG_CTRL_MASK_SPNIDEN);
|
||||
*dbg_ctrl_p |= DBG_CTRL_MASK_DBGEN |
|
||||
DBG_CTRL_MASK_NIDEN;
|
||||
|
||||
#elif defined(DAUTH_FULL)
|
||||
*dbg_ctrl_p |= DBG_CTRL_MASK_DBGEN |
|
||||
DBG_CTRL_MASK_NIDEN |
|
||||
DBG_CTRL_MASK_SPIDEN |
|
||||
DBG_CTRL_MASK_SPNIDEN;
|
||||
#else
|
||||
|
||||
#if !defined(DAUTH_CHIP_DEFAULT)
|
||||
#error "No debug authentication setting is provided."
|
||||
#endif
|
||||
/* No need to set any enable bits because the value depends on
|
||||
* input signals.
|
||||
*/
|
||||
(void)dbg_ctrl_p;
|
||||
#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; i<sizeof(NVIC->ITNS)/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()
|
||||
{
|
||||
int32_t ret = ARM_DRIVER_OK;
|
||||
/* MPC interrupt enabling */
|
||||
ret |= Driver_EFLASH0_MPC.EnableInterrupt();
|
||||
ret |= Driver_CODE_SRAM_MPC.EnableInterrupt();
|
||||
if (ret != ARM_DRIVER_OK) {
|
||||
MBED_ASSERT("MPC IRQ enable failed!");
|
||||
}
|
||||
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
|
||||
*/
|
||||
Driver_APB_PPC0.ClearInterrupt();
|
||||
|
||||
/* Enable PPC interrupts for APB PPC */
|
||||
ret |= Driver_APB_PPC0.EnableInterrupt();
|
||||
ret |= Driver_APB_PPC1.EnableInterrupt();
|
||||
ret |= Driver_APB_PPCEXP0.EnableInterrupt();
|
||||
ret |= Driver_APB_PPCEXP1.EnableInterrupt();
|
||||
if (ret != ARM_DRIVER_OK) {
|
||||
MBED_ASSERT("PPC IRQ enable failed!");
|
||||
}
|
||||
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;
|
||||
|
||||
/* Secondary image partition */
|
||||
SAU->RNR = TFM_NS_SECONDARY_IMAGE_REGION;
|
||||
SAU->RBAR = (memory_regions.secondary_partition_base & SAU_RBAR_BADDR_Msk);
|
||||
SAU->RLAR = (memory_regions.secondary_partition_limit & SAU_RLAR_LADDR_Msk)
|
||||
| SAU_RLAR_ENABLE_Msk;
|
||||
|
||||
/* 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;
|
||||
int32_t ret = ARM_DRIVER_OK;
|
||||
|
||||
ret |= Driver_EFLASH0_MPC.Initialize();
|
||||
ret |= Driver_EFLASH0_MPC.ConfigRegion(memory_regions.non_secure_partition_base,
|
||||
memory_regions.non_secure_partition_limit,
|
||||
ARM_MPC_ATTR_NONSECURE);
|
||||
|
||||
/* Secondary image region */
|
||||
ret |= Driver_EFLASH0_MPC.ConfigRegion(memory_regions.secondary_partition_base,
|
||||
memory_regions.secondary_partition_limit,
|
||||
ARM_MPC_ATTR_NONSECURE);
|
||||
|
||||
ret |= mpc_data_region0->Initialize();
|
||||
ret |= mpc_data_region0->ConfigRegion(MPC_ISRAM0_RANGE_BASE_S,
|
||||
MPC_ISRAM0_RANGE_LIMIT_S,
|
||||
ARM_MPC_ATTR_SECURE);
|
||||
|
||||
ret |= mpc_data_region1->Initialize();
|
||||
ret |= mpc_data_region1->ConfigRegion(MPC_ISRAM1_RANGE_BASE_S,
|
||||
MPC_ISRAM1_RANGE_LIMIT_S,
|
||||
ARM_MPC_ATTR_SECURE);
|
||||
|
||||
ret |= mpc_data_region2->Initialize();
|
||||
ret |= mpc_data_region2->ConfigRegion(MPC_ISRAM2_RANGE_BASE_NS,
|
||||
MPC_ISRAM2_RANGE_LIMIT_NS,
|
||||
ARM_MPC_ATTR_NONSECURE);
|
||||
|
||||
ret |= mpc_data_region3->Initialize();
|
||||
ret |= mpc_data_region3->ConfigRegion(MPC_ISRAM3_RANGE_BASE_NS,
|
||||
MPC_ISRAM3_RANGE_LIMIT_NS,
|
||||
ARM_MPC_ATTR_NONSECURE);
|
||||
|
||||
if (ret != ARM_DRIVER_OK) {
|
||||
MBED_ASSERT("MPC init failed!");
|
||||
}
|
||||
|
||||
/* Add barriers to assure the MPC configuration is done before continue
|
||||
* the execution.
|
||||
*/
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
void mpc_revert_non_secure_to_secure_cfg(void)
|
||||
{
|
||||
ARM_DRIVER_MPC* mpc_data_region2 = &Driver_ISRAM2_MPC;
|
||||
ARM_DRIVER_MPC* mpc_data_region3 = &Driver_ISRAM3_MPC;
|
||||
int32_t ret = ARM_DRIVER_OK;
|
||||
|
||||
ret |= Driver_EFLASH0_MPC.ConfigRegion(MPC_EFLASH0_RANGE_BASE_S,
|
||||
MPC_EFLASH0_RANGE_LIMIT_S,
|
||||
ARM_MPC_ATTR_SECURE);
|
||||
|
||||
ret |= mpc_data_region2->ConfigRegion(MPC_ISRAM2_RANGE_BASE_S,
|
||||
MPC_ISRAM2_RANGE_LIMIT_S,
|
||||
ARM_MPC_ATTR_SECURE);
|
||||
|
||||
ret |= mpc_data_region3->ConfigRegion(MPC_ISRAM3_RANGE_BASE_S,
|
||||
MPC_ISRAM3_RANGE_LIMIT_S,
|
||||
ARM_MPC_ATTR_SECURE);
|
||||
|
||||
if (ret != ARM_DRIVER_OK) {
|
||||
MBED_ASSERT("MPC revert config failed!");
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int32_t ret = ARM_DRIVER_OK;
|
||||
|
||||
/* Grant non-secure access to peripherals in the APB PPC0
|
||||
* (timer0 and 1, dualtimer, mhu 0 and 1)
|
||||
*/
|
||||
ret |= Driver_APB_PPC0.Initialize();
|
||||
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_TIMER0_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_TIMER1_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_DTIMER_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_MHU0_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_MHU1_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
|
||||
/* Grant non-secure access for APB MHU0 on EXP0 */
|
||||
ret |= Driver_APB_PPCEXP0.Initialize();
|
||||
ret |= Driver_APB_PPCEXP0.ConfigPeriph(MUSCA_B1_CI_MHU0_S_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP0.ConfigPeriph(MUSCA_B1_CI_MHU0_R_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
|
||||
/* Grant non-secure access for APB peripherals on EXP1 */
|
||||
ret |= Driver_APB_PPCEXP1.Initialize();
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_PWM0_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_PWM1_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_PWM2_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_I2S_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_UART0_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_UART1_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_AND_NONPRIV);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_I2C0_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_I2C1_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_SPI_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_GPTIMER_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_RTC_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_PVT_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_SDIO_APB_PPC_POS,
|
||||
ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
|
||||
if (ret != ARM_DRIVER_OK) {
|
||||
MBED_ASSERT("PPC init failed!");
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
ARM_DRIVER_PPC *ppc_driver;
|
||||
|
||||
if (bank >= PPC_BANK_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
ppc_driver = ppc_bank_drivers[bank];
|
||||
if (ppc_driver) {
|
||||
ppc_driver->ConfigPeriph(pos, ARM_PPC_NONSECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t pos)
|
||||
{
|
||||
/* Clear NS flag for peripheral to prevent NS access */
|
||||
ARM_DRIVER_PPC *ppc_driver;
|
||||
|
||||
if (bank >= PPC_BANK_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
ppc_driver = ppc_bank_drivers[bank];
|
||||
if (ppc_driver) {
|
||||
ppc_driver->ConfigPeriph(pos, ARM_PPC_SECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
|
||||
{
|
||||
ARM_DRIVER_PPC *ppc_driver;
|
||||
|
||||
if (bank >= PPC_BANK_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
ppc_driver = ppc_bank_drivers[bank];
|
||||
if (ppc_driver) {
|
||||
ppc_driver->ConfigPeriph(pos, ARM_PPC_SECURE_ONLY,
|
||||
ARM_PPC_PRIV_AND_NONPRIV);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
|
||||
{
|
||||
ARM_DRIVER_PPC *ppc_driver;
|
||||
|
||||
if (bank >= PPC_BANK_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
ppc_driver = ppc_bank_drivers[bank];
|
||||
if (ppc_driver) {
|
||||
ppc_driver->ConfigPeriph(pos, ARM_PPC_SECURE_ONLY,
|
||||
ARM_PPC_PRIV_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_clear_irq(void)
|
||||
{
|
||||
Driver_AHB_PPCEXP0.ClearInterrupt();
|
||||
Driver_APB_PPC0.ClearInterrupt();
|
||||
Driver_APB_PPC1.ClearInterrupt();
|
||||
Driver_APB_PPCEXP0.ClearInterrupt();
|
||||
Driver_APB_PPCEXP1.ClearInterrupt();
|
||||
}
|
||||
|
||||
|
||||
void mbed_psa_system_reset_impl(void)
|
||||
{
|
||||
__disable_irq();
|
||||
mpc_revert_non_secure_to_secure_cfg();
|
||||
|
||||
NVIC->ICPR[0] = UINT32_MAX; /* Clear all pending interrupts */
|
||||
NVIC->ICPR[1] = UINT32_MAX; /* Clear all pending interrupts */
|
||||
NVIC->ICPR[2] = UINT32_MAX; /* Clear all pending interrupts */
|
||||
NVIC->ICPR[3] = UINT32_MAX; /* Clear all pending interrupts */
|
||||
NVIC->ICPR[4] = UINT32_MAX; /* Clear all pending interrupts */
|
||||
NVIC->ICPR[5] = UINT32_MAX; /* Clear all pending interrupts */
|
||||
NVIC->ICPR[6] = UINT32_MAX; /* Clear all pending interrupts */
|
||||
NVIC->ICPR[7] = UINT32_MAX; /* Clear all pending interrupts */
|
||||
|
||||
NVIC_SystemReset();
|
||||
|
||||
}
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 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 __TARGET_CFG_H__
|
||||
#define __TARGET_CFG_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "tfm_peripherals_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \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;
|
||||
uint32_t secondary_partition_base;
|
||||
uint32_t secondary_partition_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 Set to secure the initialized non-secure regions of
|
||||
* the Memory Protection Controller.
|
||||
*/
|
||||
void mpc_revert_non_secure_to_secure_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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TARGET_CFG_H__ */
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 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__ */
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "platform_description.h"
|
||||
#include "target_cfg.h"
|
||||
#include "device_definition.h"
|
||||
#include "psa/client.h"
|
||||
#include "tfm_secure_api.h"
|
||||
#include "tfm_ioctl_api.h"
|
||||
#include "platform_srv_impl.h"
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
/*!
|
||||
* \brief Verify access rights for memory addresses sent in io vectors
|
||||
*
|
||||
* \param[in] in_vec Pointer to in_vec array, which contains pointer
|
||||
* to input arguments for the service
|
||||
* \param[in] out_vec Pointer out_vec array, which contains pointer to
|
||||
* output data of the pin service
|
||||
*
|
||||
* \return Returns true if memory is accessible by the service
|
||||
*/
|
||||
static bool memory_addr_check(const psa_invec *in_vec,
|
||||
const psa_outvec *out_vec)
|
||||
{
|
||||
if ((in_vec->base != NULL) &&
|
||||
(tfm_core_memory_permission_check((void *)in_vec->base, in_vec->len,
|
||||
TFM_MEMORY_ACCESS_RO) == TFM_SUCCESS) &&
|
||||
(out_vec->base != NULL) &&
|
||||
(tfm_core_memory_permission_check((void *)out_vec->base, out_vec->len,
|
||||
TFM_MEMORY_ACCESS_RW) == TFM_SUCCESS)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* TFM_PSA_API */
|
||||
|
||||
static enum tfm_platform_err_t
|
||||
musca_b1_pin_service(const psa_invec *in_vec,
|
||||
const psa_outvec *out_vec)
|
||||
{
|
||||
struct tfm_pin_service_args_t *args;
|
||||
uint32_t *result;
|
||||
enum gpio_altfunc_t altfunc;
|
||||
enum pinmode_select_t pin_mode;
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
if (memory_addr_check(in_vec, out_vec) == false) {
|
||||
return TFM_PLATFORM_ERR_SYSTEM_ERROR;
|
||||
}
|
||||
#endif /* TFM_PSA_API */
|
||||
|
||||
if (in_vec->len != sizeof(struct tfm_pin_service_args_t) ||
|
||||
out_vec->len != sizeof(uint32_t)) {
|
||||
return TFM_PLATFORM_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
args = (struct tfm_pin_service_args_t *)in_vec->base;
|
||||
result = (uint32_t *)out_vec->base;
|
||||
switch (args->type) {
|
||||
case TFM_PIN_SERVICE_TYPE_SET_ALTFUNC:
|
||||
altfunc = (enum gpio_altfunc_t)args->u.set_altfunc.alt_func;
|
||||
*result = musca_b1_scc_set_alt_func(&MUSCA_B1_SCC_DEV_S, altfunc,
|
||||
args->u.set_altfunc.pin_mask);
|
||||
break;
|
||||
case TFM_PIN_SERVICE_TYPE_SET_DEFAULT_IN:
|
||||
altfunc = (enum gpio_altfunc_t)args->u.set_altfunc.alt_func;
|
||||
*result = musca_b1_scc_set_default_in(&MUSCA_B1_SCC_DEV_S, altfunc,
|
||||
args->u.set_default_in.pin_value,
|
||||
args->u.set_default_in.default_in_value);
|
||||
break;
|
||||
case TFM_PIN_SERVICE_TYPE_SET_PIN_MODE:
|
||||
pin_mode = (enum pinmode_select_t)args->u.set_pin_mode.pin_mode;
|
||||
*result = musca_b1_scc_set_pinmode(&MUSCA_B1_SCC_DEV_S,
|
||||
args->u.set_pin_mode.pin_mask,
|
||||
pin_mode);
|
||||
break;
|
||||
default:
|
||||
*result = SCC_INVALID_ARG;
|
||||
break;
|
||||
}
|
||||
|
||||
return TFM_PLATFORM_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
enum tfm_platform_err_t
|
||||
tfm_platform_hal_gpio_service(const psa_invec *in_vec,
|
||||
const psa_outvec *out_vec)
|
||||
{
|
||||
struct tfm_gpio_service_args_t *args;
|
||||
struct tfm_gpio_service_out_t *out;
|
||||
enum gpio_cmsdk_direction_t dir;
|
||||
/* Alternate function is configured through the SCC, this is not used
|
||||
* on Musca-B1, the default value is passed to the driver
|
||||
*/
|
||||
enum gpio_cmsdk_altfunc_t altfunc = GPIO_CMSDK_MAIN_FUNC;
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
if (memory_addr_check(in_vec, out_vec) == false) {
|
||||
return TFM_PLATFORM_ERR_SYSTEM_ERROR;
|
||||
}
|
||||
#endif /* TFM_PSA_API */
|
||||
|
||||
if (in_vec->len != sizeof(struct tfm_gpio_service_args_t) ||
|
||||
out_vec->len != sizeof(struct tfm_gpio_service_out_t)) {
|
||||
return TFM_PLATFORM_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
args = (struct tfm_gpio_service_args_t *)in_vec->base;
|
||||
out = (struct tfm_gpio_service_out_t *)out_vec->base;
|
||||
switch (args->type) {
|
||||
case TFM_GPIO_SERVICE_TYPE_INIT:
|
||||
gpio_cmsdk_init(&GPIO0_CMSDK_DEV_S);
|
||||
out->u.result = GPIO_CMSDK_ERR_NONE;
|
||||
break;
|
||||
case TFM_GPIO_SERVICE_TYPE_PIN_CONFIG:
|
||||
dir = (enum gpio_cmsdk_direction_t)args->u.gpio_config.direction;
|
||||
out->u.result = gpio_cmsdk_pin_config(
|
||||
&GPIO0_CMSDK_DEV_S,
|
||||
args->u.gpio_config.pin_num_or_mask,
|
||||
dir, altfunc);
|
||||
break;
|
||||
case TFM_GPIO_SERVICE_TYPE_PIN_WRITE:
|
||||
out->u.result = gpio_cmsdk_pin_write(
|
||||
&GPIO0_CMSDK_DEV_S,
|
||||
args->u.gpio_write.pin_num_or_mask,
|
||||
args->u.gpio_write.value);
|
||||
break;
|
||||
case TFM_GPIO_SERVICE_TYPE_PIN_READ:
|
||||
out->u.gpio_read_result.result =
|
||||
gpio_cmsdk_pin_read(&GPIO0_CMSDK_DEV_S,
|
||||
args->u.gpio_read.pin_num_or_mask,
|
||||
&out->u.gpio_read_result.data);
|
||||
break;
|
||||
case TFM_GPIO_SERVICE_TYPE_PORT_CONFIG:
|
||||
dir = (enum gpio_cmsdk_direction_t)args->u.gpio_config.direction;
|
||||
out->u.result = gpio_cmsdk_port_config(
|
||||
&GPIO0_CMSDK_DEV_S,
|
||||
args->u.gpio_config.pin_num_or_mask,
|
||||
dir, altfunc);
|
||||
break;
|
||||
case TFM_GPIO_SERVICE_TYPE_PORT_WRITE:
|
||||
out->u.result = gpio_cmsdk_port_write(
|
||||
&GPIO0_CMSDK_DEV_S,
|
||||
args->u.gpio_write.pin_num_or_mask,
|
||||
args->u.gpio_write.value);
|
||||
break;
|
||||
case TFM_GPIO_SERVICE_TYPE_PORT_READ:
|
||||
out->u.gpio_read_result.result =
|
||||
gpio_cmsdk_port_read(&GPIO0_CMSDK_DEV_S,
|
||||
args->u.gpio_read.pin_num_or_mask,
|
||||
&out->u.gpio_read_result.data);
|
||||
break;
|
||||
default:
|
||||
out->u.result = GPIO_CMSDK_ERR_INVALID_ARG;
|
||||
break;
|
||||
}
|
||||
|
||||
in_vec++;
|
||||
out_vec++;
|
||||
|
||||
return TFM_PLATFORM_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request,
|
||||
psa_invec *in_vec,
|
||||
psa_outvec *out_vec)
|
||||
{
|
||||
switch (request) {
|
||||
case TFM_PLATFORM_IOCTL_PIN_SERVICE:
|
||||
return musca_b1_pin_service(in_vec, out_vec);
|
||||
case TFM_PLATFORM_IOCTL_GPIO_SERVICE:
|
||||
return tfm_platform_hal_gpio_service(in_vec, out_vec);
|
||||
default:
|
||||
return TFM_PLATFORM_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "../../../partition/region_defs.h"
|
||||
#include "../../partition/region_defs.h"
|
||||
#include "../cmsis_nvic.h"
|
||||
|
||||
#if !defined(MBED_ROM_START)
|
|
@ -22,7 +22,7 @@
|
|||
/* Linker script to configure memory regions. */
|
||||
/* This file will be run trough the pre-processor. */
|
||||
|
||||
#include "../../../partition/region_defs.h"
|
||||
#include "../../partition/region_defs.h"
|
||||
#include "../cmsis_nvic.h"
|
||||
|
||||
/* Stack size is 1K for Mbed-OS */
|
|
@ -24,7 +24,7 @@
|
|||
#ifndef MBED_CMSIS_NVIC_H
|
||||
#define MBED_CMSIS_NVIC_H
|
||||
|
||||
#include "../../partition/region_defs.h"
|
||||
#include "../partition/region_defs.h"
|
||||
|
||||
#define NVIC_NUM_VECTORS (16 + 128)
|
||||
/** Location of vectors to move in RAM */
|
|
@ -29,52 +29,7 @@
|
|||
* This is a default device configuration file with all peripherals enabled.
|
||||
*/
|
||||
|
||||
#if defined(TARGET_MUSCA_B1_S)
|
||||
|
||||
/* ARM SCC */
|
||||
#define MUSCA_B1_SCC_S
|
||||
#define MUSCA_B1_SCC_DEV MUSCA_B1_SCC_DEV_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
|
||||
#define MPC_EFLASH0_S
|
||||
#define MPC_EFLASH1_S
|
||||
|
||||
/* 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
|
||||
|
||||
/* Cadence QSPI Flash Controller */
|
||||
#define QSPI_IP6514E_S
|
||||
|
||||
/* MT25QL Flash memory library */
|
||||
#define MT25QL_S
|
||||
|
||||
/* GPIO */
|
||||
#define GPIO0_CMSDK_S
|
||||
#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S
|
||||
|
||||
#endif // defined(TARGET_MUSCA_B1_S)
|
||||
|
||||
|
||||
#if defined(TARGET_MUSCA_B1_NS)
|
||||
/*ARM UART Controller PL011*/
|
||||
|
||||
#define UART0_PL011_NS
|
||||
|
@ -133,6 +88,5 @@
|
|||
#define USEC_REPORTED_BITS (32 - USEC_REPORTED_SHIFT)
|
||||
|
||||
#define UART_DEFAULT_BAUD_RATE 9600U
|
||||
#endif // TARGET_MUSCA_B1_NS
|
||||
|
||||
#endif /* __ARM_LTD_DEVICE_CFG_H__ */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue