Import Mbed OS hard-float snapshot

This commit is contained in:
Beslan
2026-06-01 20:15:04 +03:00
commit d3738e2f89
16278 changed files with 10628036 additions and 0 deletions

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.

View File

@@ -0,0 +1,108 @@
# ARM TrustZone True Number Generator
This software product contains the following open source components:
* ARM TrustZone TRNG driver.
* ARM TrustZone TRNG integration test.
* Characterization reference code.
Containing:
* READM.md (this file)
* Software and test build system:
build.props
proj.ext.cfg
TRNG_test.c
shared/
host/
* Software Integrator's Manual (trustzone_true_random_number_generator_software_integrators_manual_101049_0000_00_en.pdf)
ARM TrustZone TRNG supports 32-bit systems.
The `.mbedignore` file allows the driver to be used as it is for TRNG implementation in mbed OS. That file will make it work under 800-90B TRNG mode.
## License
This software is provided under the Apache-2.0 license. Contributions to this project are accepted under the same license.
## Release details
This release contains the ARM TrustZone TRNG software.
### Prerequisites:
* To be run on an Ubuntu 14.04 LTS system host for building.
* gcc version 4.7.3 or arm-ds5 compiler are in your PATH.
* If using Linux as a host on the H/W, configure the KERNEL_DIR environment variable to point to your Linux (s).
* The target is running Linux kernel 4.4 or FreeRTOS.
Download the software bundle from https://github.com/ARM-software/TZ-TRNG.
### Build procedure
**Step 1**: Open a terminal on the Ubuntu system, and use 'cd <path>' to go to the folder where you unpacked the software bundle from the ARM github url.
**Step 2**: Define environment variables, depending on what the hw system target is running:
* For a target hw system running FreeRTOS:
```bash
export KERNEL_DIR=/path/to/freertos
```
or
* For a target hw system running linux:
```bash
export KERNEL_DIR=/path/to/linux
```
**Step 3**: Build all the binaries (common for FreeRTOS and Linux):
```bash
cd /path/to/tztrng
make -C host/src/tztrng_lib/ clean
make -C host/src/tztrng_lib/
make -C host/src/tests/tztrng_test/ clean
make -C host/src/tests/tztrng_test/
```
The tztrng library is located in:
```bash
host/lib/libcc_tztrng.a
```
The integration test executable is located in the following path:
- When compiling with gcc: host/bin/tztrng_test.
- When compiling with armcc: host/lib/libtztrng_test.a.
**Step 4**: Deploy:
* For a target hw system running linux:
Copy host/bin/tztrng_test to the target linux file system and exeute:
```bash
./tztrng_test
```
* For a target hw system running FreeRTOS:
```bash
cp host/lib/libcc_tztrng.a /path/to/your/library/folder
cp host/lib/libtztrng_test.a /path/to/your/library/folder
cp host/src/tests/tztrng_test/tztrng_test.h /path/to/includes
```
## Validation
1. Tests run
See "Step 4: Deploy" above.
1. Known issues
None
1. Planned enhancements
None

View File

@@ -0,0 +1,34 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, All Rights Reserved *
* SPDX-License-Identifier: Apache-2.0 *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT *
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* *
* See the License for the specific language governing permissions and *
* limitations under the License. *
******************************************************************************/
#ifndef _CC_CONFIG_FETRNG_H
#define _CC_CONFIG_FETRNG_H
/*
* This file should be updated according to the characterization process.
*
* sample count for each ring oscillator
* - for unallowed rosc, sample count = 0
*/
#define CC_CONFIG_SAMPLE_CNT_ROSC_1 0
#define CC_CONFIG_SAMPLE_CNT_ROSC_2 150
#define CC_CONFIG_SAMPLE_CNT_ROSC_3 458
#define CC_CONFIG_SAMPLE_CNT_ROSC_4 750
#endif

View File

@@ -0,0 +1,33 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, All Rights Reserved *
* SPDX-License-Identifier: Apache-2.0 *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT *
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* *
* See the License for the specific language governing permissions and *
* limitations under the License. *
******************************************************************************/
#ifndef _CC_CONFIG_TRNG90B_H
#define _CC_CONFIG_TRNG90B_H
/*
This file should be updated according to the characterization process.
*/
/* sample count for each ring oscillator */
/* for unallowed rosc, sample count = 0 */
#define CC_CONFIG_SAMPLE_CNT_ROSC_1 200
#define CC_CONFIG_SAMPLE_CNT_ROSC_2 200
#define CC_CONFIG_SAMPLE_CNT_ROSC_3 300
#define CC_CONFIG_SAMPLE_CNT_ROSC_4 100
#endif

View File

@@ -0,0 +1,41 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, All Rights Reserved *
* SPDX-License-Identifier: Apache-2.0 *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT *
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* *
* See the License for the specific language governing permissions and *
* limitations under the License. *
******************************************************************************/
#ifndef _TZTRNG_H_
#define _TZTRNG_H_
#include <stdint.h>
/*******************************************************************************/
/**
* @brief The CC_TrngGetSource reads random source of needed size from TRNG.
*
* @param[in] rngRegBase - TRNG base address, given by the system.
* @param[out] *outAddr - The pointer to the buffer address for TRNG data output,
* prepared by the caller.
* @param[out] *outLen - The pointer to size of TRNG returned data.
* @param[in] reqBits - The request size of entropy in bits.
*
* @return uint32_t - On success 0 is returned, on failure, check CC_Error_t codes
*
*/
uint32_t CC_TrngGetSource(unsigned long rngRegBase, /* in */
uint8_t *outAddr, /* out */
size_t *outLen, /* out */
size_t reqBits); /* in */
#endif

View File

@@ -0,0 +1,249 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, All Rights Reserved *
* SPDX-License-Identifier: Apache-2.0 *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT *
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* *
* See the License for the specific language governing permissions and *
* limitations under the License. *
******************************************************************************/
#ifndef _TZTRNG_DEFS_H_
#define _TZTRNG_DEFS_H_
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "dx_reg_base_host.h"
#include "dx_rng.h"
#if (CC_CONFIG_TRNG_MODE == 1)
#include "config_trng90b.h"
#elif (CC_CONFIG_TRNG_MODE == 0)
#include "config_fetrng.h"
#else
#error "invalid VECT definition in Makefile"
#endif
#define CC_OK 0
#define CC_UNUSED_PARAM(prm) ((void)prm)
#define CC_MAX_UINT32_VAL (0xFFFFFFFF)
#define LLF_RND_NUM_OF_ROSCS 4
#define TRNG_EHR_SIZE 6
/* TRNG Error definitions */
#define TRNG_MAX_CRNGT_ERRORS (12)
#define TRNG_MAX_VN_ERRORS (50)
extern unsigned long gCcRegBase;
typedef uint32_t CCError_t;
typedef uint32_t CCBool_t;
typedef enum {
CC_FALSE = 0,
CC_TRUE = 1
} CCBool;
/*
Requirements:
- Required entropy = 384 bits
Default values for Zynq FPGA:
- entropy per bit = 0.5
*/
/* amount of bytes for the required entropy bits = ROUND_UP(ROUND_UP(((required entropy bits)/(entropy per bit)), 1024), (EHR width in bytes)) / 8
(multiple of the window size 1024 bits and multiple of the EHR width 192 bits) */
#define CC_CONFIG_TRNG90B_AMOUNT_OF_BYTES 144 /* ROUND_UP(ROUND_UP((384/0.5), 1024), 192) / 8 = 144 */
/*** NIST SP 800-90B (2nd Draft) 4.4.1 ***/
/* C = ROUND_UP(1+(-log(W)/H)), W = 2^(-40), H=(entropy per bit) */
#define CC_CONFIG_TRNG90B_REPETITION_COUNTER_CUTOFF 81 /* ROUND_UP(1+(40/0.5)) = 81 */
/*** NIST SP 800-90B (2nd Draft) 4.4.2 ***/
/* C =CRITBINOM(W, power(2,(-H)),1-a), W = 1024, a = 2^(-40), H=(entropy per bit) */
#define CC_CONFIG_TRNG90B_ADAPTIVE_PROPORTION_CUTOFF 823 /* =CRITBINOM(1024, power(2,(-0.5)),1-2^(-40)) */
/*** For Startup Tests ***/
/* amount of bytes for the startup test = 528 (at least 4096 bits (NIST SP 800-90B (2nd Draft) 4.3.12) = 22 EHRs = 4224 bits) */
#define CC_CONFIG_TRNG90B_AMOUNT_OF_BYTES_STARTUP 528
/* Definitions of temp buffer for DMA */
#define CC_RND_WORK_BUFFER_SIZE_WORDS CC_CONFIG_TRNG90B_AMOUNT_OF_BYTES_STARTUP/4 /* the maximum possible usage of stack memory in words */
/* The CRYS Random Generator Parameters structure CCRndParams_t -
structure containing the user given Parameters */
typedef struct CCRndParams_t
{
/* allowed ring oscillator lengths: bits 0,1,2,3 */
uint32_t RoscsAllowed;
/* sampling interval: count of ring oscillator cycles between
consecutive bits sampling */
uint32_t SubSamplingRatio;
uint32_t SubSamplingRatio1;
uint32_t SubSamplingRatio2;
uint32_t SubSamplingRatio3;
uint32_t SubSamplingRatio4;
} CCRndParams_t;
/*! RND state structure. Includes internal data that needs to be saved between boots by the user.*/
typedef struct
{
/* State flag (see definition of StateFlag above), containing bit-fields, defining:
- b'0: instantiation steps: 0 - not done, 1 - done;
- 2b'9,8: working or testing mode: 0 - working, 1 - KAT DRBG test, 2 -
KAT TRNG test;
b'16: flag defining is Previous random valid or not:
0 - not valid, 1 - valid */
/*! State flag used internally in the code.*/
uint32_t StateFlag;
/* Trng processing flag - indicates which ROSC lengths are:
- allowed (bits 0-3);
- total started (bits 8-11);
- processed (bits 16-19);
- started, but not processed (bits24-27) */
/*! TRNG process state used internally in the code */
uint32_t TrngProcesState;
} CCRndState_t;
/* Register Offset macro */
#define CC_REG_OFFSET(unit_name, reg_name) \
(DX_ ## reg_name ## _REG_OFFSET)
/*!
* Read TRNG memory-mapped-IO register.
*
* \param regOffset The offset of the ARM TRNG register to read
* \return uint32_t Return the value of the given register
*/
#define CC_HAL_READ_REGISTER(regOffset) \
(*((volatile uint32_t *)(gCcRegBase + (regOffset))))
/*!
* Write TRNG memory-mapped-IO register.
* \note This macro must be modified to make the operation synchronous, i.e. the write operation must complete,
* and the new value must be written to the register before the macro returns. The mechanisms required to
* achieve this are architecture-dependent (e.g., the memory barrier in ARM architecture).
*
* \param regOffset The offset of the ARM TRNG register to write
* \param val The value to write
*/
#define CC_HAL_WRITE_REGISTER(regOffset, val) \
(*((volatile uint32_t *)(gCcRegBase + (regOffset))) = (val))
#define LLF_RND_HW_TRNG_EHR_WIDTH_IN_WORDS 6
#define LLF_RND_HW_TRNG_EHR_WIDTH_IN_BYTES (LLF_RND_HW_TRNG_EHR_WIDTH_IN_WORDS * sizeof(uint32_t))
#define LLF_RND_HW_DMA_EHR_SAMPLES_NUM_ON_TRNG90B_MODE 22UL
#define LLF_RND_HW_DEBUG_CONTROL_VALUE_ON_FE_MODE 0x00000000
/* ring oscillator offsets and numbers */
#define LLF_RND_HW_TRNG_ROSC0_BIT 0x1
#define LLF_RND_HW_TRNG_ROSC1_BIT 0x2
#define LLF_RND_HW_TRNG_ROSC2_BIT 0x4
#define LLF_RND_HW_TRNG_ROSC3_BIT 0x8
#define LLF_RND_HW_TRNG_ROSC0_NUM 0x0
#define LLF_RND_HW_TRNG_ROSC1_NUM 0x1
#define LLF_RND_HW_TRNG_ROSC2_NUM 0x2
#define LLF_RND_HW_TRNG_ROSC3_NUM 0x3
#define LLF_RND_HW_RND_SRC_ENABLE_VAL 1UL
#define LLF_RND_HW_RND_SRC_DISABLE_VAL 0UL
#define LLF_RND_HW_TRNG_WITH_DMA_CONFIG_VAL 0x4
#define LLF_RNG_INT_MASK_ON_TRNG90B_MODE 0xFFFFFFC5
#define LLF_RNG_INT_MASK_ON_FETRNG_MODE 0xFFFFFFEC
#define LLF_RND_HW_DMA_EHR_SAMPLES_NUM_ON_FE_MODE 2UL /*for both AES128 and AES256*/
/* Logging macros */
#define TRNG_LOG(format, ...) \
fprintf(stderr, "tztrng:%s: " format , __func__, ##__VA_ARGS__)
#ifdef DEBUG
#define TRNG_LOG_DEBUG(format, ...) TRNG_LOG(format, ##__VA_ARGS__)
#else
#define TRNG_LOG_DEBUG(format, ...) do {} while (0)
#endif
#ifdef TZTRNG_EHR_DUMP
#define TRNG_EHR_DUMP(format, ...) \
fprintf(stderr, format, ##__VA_ARGS__)
#else
#define TRNG_EHR_DUMP(format, ...) do {} while (0)
#endif
#define CC_ERROR_BASE 0x00F00000UL
#define CC_ERROR_LAYER_RANGE 0x00010000UL
#define CC_ERROR_MODULE_RANGE 0x00000100UL
#define CC_LAYER_ERROR_IDX 0x00UL
#define LLF_LAYER_ERROR_IDX 0x01UL
#define GENERIC_ERROR_IDX 0x05UL
#define RND_ERROR_IDX 0x0CUL
#define CC_RND_MODULE_ERROR_BASE (CC_ERROR_BASE + \
(CC_ERROR_LAYER_RANGE * CC_LAYER_ERROR_IDX) + \
(CC_ERROR_MODULE_RANGE * RND_ERROR_IDX ) )
/*! Low level RND module error base address - 0x00F10C00. */
#define LLF_RND_MODULE_ERROR_BASE (CC_ERROR_BASE + \
(CC_ERROR_LAYER_RANGE * LLF_LAYER_ERROR_IDX) + \
(CC_ERROR_MODULE_RANGE * RND_ERROR_IDX ) )
#define LLF_RND_HW_DEBUG_CONTROL_VALUE_ON_TRNG90B_MODE 0x0000000A /* bypass Von-Neumann balancer and autocorrelation test */
#define LLF_RND_HW_VERSION_NOT_CORRECT_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x0UL)
#define LLF_RND_CPRNG_TEST_FAIL_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x1UL)
#define LLF_RND_CRNGT_TEST_FAIL_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x2UL)
#define LLF_RND_STATE_PTR_INVALID_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x3UL)
#define LLF_RND_AES_256_NOT_SUPPORTED_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x4UL)
#define LLF_RND_TRNG_TIME_LIMIT_EXCEEDED_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x20UL)
#define LLF_RND_TRNG_ENTR_ESTIM_SIZE_EXCEED_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x21UL)
#define LLF_RND_TRNG_PREVIOUS_PARAMS_NOT_MATCH_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x30UL)
#define LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x31UL)
#define LLF_RND_TRNG_GENERATION_NOT_COMPLETED_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x32UL)
#define LLF_RND_TRNG_LOW_ENTROPY_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x33UL)
#define LLF_RND_TRNG_NULL_ENTROPY_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x34UL)
#define LLF_RND_TRNG_ILLEGAL_PTR_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x35UL)
#define LLF_RND_TRNG_REPETITION_COUNTER_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x36UL)
#define LLF_RND_TRNG_ADAPTION_PROPORTION_ERROR (LLF_RND_MODULE_ERROR_BASE + 0x37UL)
#define CC_RND_CPRNG_TEST_FAIL_ERROR (CC_RND_MODULE_ERROR_BASE + 0x2UL)
#define CC_RND_TRNG_KAT_NOT_SUPPORTED_ERROR (CC_RND_MODULE_ERROR_BASE + 0x34UL)
void LLF_RND_TurnOffTrng(void);
CCError_t LLF_RND_GetFastestRosc( CCRndParams_t *trngParams_ptr, uint32_t *rosc_ptr/*in/out*/);
CCError_t LLF_RND_GetRoscSampleCnt( uint32_t rosc, CCRndParams_t *pTrngParams);
uint32_t LLF_RND_TRNG_RoscMaskToNum(uint32_t mask);
#define CC_RND_NOT_INSTANTIATED 0UL
#define CC_RND_INSTANTIATED 1UL
#define CC_RND_INSTANTRESEED_AUTOCORR_ERRORS 2UL
#define CC_RND_INSTANTRESEED_TIME_EXCEED 4UL
#define CC_RND_INSTANTRESEED_LESS_ENTROPY 8UL
CCError_t LLF_RND_RunTrngStartupTest(
CCRndState_t *rndState_ptr, /*in/out*/
CCRndParams_t *trngParams_ptr, /*out*/
uint32_t *rndWorkBuff_ptr); /*in*/
CCError_t LLF_RND_GetTrngSource(
CCRndState_t *rndState_ptr, /*in/out*/
CCRndParams_t *trngParams_ptr, /*in/out*/
CCBool_t isContinued, /*in*/
uint32_t **sourceOut_ptr_ptr,/*out*/
uint32_t *sourceOutSize_ptr, /*in/out*/
uint32_t *rndWorkBuff_ptr); /*in*/
#endif

View File

@@ -0,0 +1,26 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, All Rights Reserved *
* SPDX-License-Identifier: Apache-2.0 *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT *
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* *
* See the License for the specific language governing permissions and *
* limitations under the License. *
******************************************************************************/
#ifndef _TZTRNG_PAL_H_
#define _TZTRNG_PAL_H_
#include <stdint.h>
uint32_t CC_HalWaitInterrupt(void);
void tztrng_memcpy(uint8_t *dst, uint8_t *src, size_t size);
void tztrng_memset(uint8_t *dst, uint8_t value, size_t size);
#endif

View File

@@ -0,0 +1,22 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, 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. *
******************************************************************************/
#include "tztrng_defs.h"
#include "tztrng_pal.h"

View File

@@ -0,0 +1,83 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, 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. *
******************************************************************************/
#include "tztrng_defs.h"
#include "tztrng_pal.h"
CCError_t LLF_RND_GetRoscSampleCnt(uint32_t rosc, CCRndParams_t *pTrngParams)
{
switch (rosc) {
case 0x1:
pTrngParams->SubSamplingRatio = pTrngParams->SubSamplingRatio1;
break;
case 0x2:
pTrngParams->SubSamplingRatio = pTrngParams->SubSamplingRatio2;
break;
case 0x4:
pTrngParams->SubSamplingRatio = pTrngParams->SubSamplingRatio3;
break;
case 0x8:
pTrngParams->SubSamplingRatio = pTrngParams->SubSamplingRatio4;
break;
default:
return LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR;
}
return CC_OK;
}
uint32_t LLF_RND_TRNG_RoscMaskToNum(uint32_t mask)
{
return (mask == LLF_RND_HW_TRNG_ROSC3_BIT) ? LLF_RND_HW_TRNG_ROSC3_NUM :
(mask == LLF_RND_HW_TRNG_ROSC2_BIT) ? LLF_RND_HW_TRNG_ROSC2_NUM :
(mask == LLF_RND_HW_TRNG_ROSC1_BIT) ? LLF_RND_HW_TRNG_ROSC1_NUM :
LLF_RND_HW_TRNG_ROSC0_NUM;
}
/**
* The function gets next allowed rosc
*
* @author reuvenl (9/12/2012)
*
* @param trngParams_ptr - a pointer to params structure.
* @param rosc_ptr - a pointer to previous rosc /in/, and
* to next rosc /out/.
* @param isNext - defines is increment of rosc ID needed or not.
* if isNext = TRUE - the function shifts rosc by one bit; Then
* the function checks is this rosc allowed, if yes - updates
* the rosc, else repeats previous steps. If no roscs allowed -
* returns an error.
*
* @return CCError_t
*/
CCError_t LLF_RND_GetFastestRosc(
CCRndParams_t *trngParams_ptr,
uint32_t *rosc_ptr /*in/out*/)
{
/* setting rosc */
do {
if (*rosc_ptr & trngParams_ptr->RoscsAllowed) {
return CC_OK;
} else {
*rosc_ptr <<= 1;
}
} while (*rosc_ptr <= 0x08);
return LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR;
}

View File

@@ -0,0 +1,166 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, 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. *
******************************************************************************/
#include "tztrng_defs.h"
#include "tztrng_pal.h"
#define LLF_RND_TRNG90B_MAX_BYTES ( LLF_RND_HW_DMA_EHR_SAMPLES_NUM_ON_TRNG90B_MODE * LLF_RND_HW_TRNG_EHR_WIDTH_IN_BYTES)
#define CC_CONFIG_TRNG90B_ADAPTIVE_PROPORTION_WINDOW_SIZE 1024 /* binary noise source */
#define UINT8_SIZE_IN_BITS 8
#define UINT32_SIZE_IN_BITS (sizeof(uint32_t) * UINT8_SIZE_IN_BITS)
uint32_t getBitsFromUint32Array(uint32_t arrayBitsOffset, uint32_t numOfBits, uint32_t* arr)
{
uint32_t res = 0;
uint32_t byteOffset = arrayBitsOffset / UINT32_SIZE_IN_BITS;
uint32_t bitOffset = arrayBitsOffset % UINT32_SIZE_IN_BITS;
if (numOfBits > UINT32_SIZE_IN_BITS) {
return 0;
}
res = arr[byteOffset] >> bitOffset;
/* (UINT32_SIZE_IN_BITS - bitOffset) bits were taken from the first dword. */
if (UINT32_SIZE_IN_BITS - bitOffset > numOfBits)
/* we copied more bits than required. zero the extra bits. */
{
res &= (0xFFFFFFFF >> (UINT32_SIZE_IN_BITS - numOfBits));
} else if (UINT32_SIZE_IN_BITS - bitOffset < numOfBits)
/* we copied less bits than required. copy the next bits from the next dword. */
{
numOfBits -= UINT32_SIZE_IN_BITS - bitOffset;
res |= (arr[byteOffset + 1] & (0xFFFFFFFF >> (UINT32_SIZE_IN_BITS - numOfBits))) << (UINT32_SIZE_IN_BITS - bitOffset);
}
return res;
}
/*
implementation of Repetition Counter Test (NIST SP 800-90B (2nd Draft) 4.4.1)
C = the cutoff value at which the Repetition Count Test fails
*/
CCError_t LLF_RND_RepetitionCounterTest(uint32_t* pData, uint32_t sizeInBytes, uint32_t C)
{
uint32_t bitOffset=0;
uint32_t newSample = 0;
uint32_t A = 0; /* the most recently seen sample value */
uint32_t B = 0; /* the number of consecutive times that the value A has been seen */
uint32_t bitsPerSample = 1; /* always use single bit per sample for repetition counter test */
if (pData == NULL || sizeInBytes == 0 || LLF_RND_TRNG90B_MAX_BYTES < sizeInBytes) {
return LLF_RND_TRNG_REPETITION_COUNTER_ERROR;
}
/* the repetition count test is performed as follows: */
for (bitOffset = 0; bitOffset <= (sizeInBytes * UINT8_SIZE_IN_BITS) - bitsPerSample; bitOffset += bitsPerSample) {
newSample = getBitsFromUint32Array(bitOffset, bitsPerSample, (uint32_t*)pData);
/* 1. Let A be the current sample value. */
/* 2. Initialize the counter B to 1. */
if (bitOffset == 0) {
A = newSample;
B = 1;
}
/* 3. If the next sample value is A, increment B by one. */
else if (A == newSample) {
++B;
/* If B is equal to C, return an error. */
if (B == C) {
return LLF_RND_TRNG_REPETITION_COUNTER_ERROR;
}
} else {
/* Let A be the next sample value. */
A = newSample;
/* Initialize the counter B to 1. */
B = 1;
/* Repeat Step 3. */
}
}
return CC_OK;
}
/*
implementation of Adaptive Proportion Test (NIST SP 800-90B (2nd Draft) 4.4.2)
N = the total number of samples that must be observed in one run of the test, also known as the "window size" of the test
C = the cutoff value above which the test should fail
*/
static CCError_t LLF_RND_AdaptiveProportionTest(uint32_t* pData, uint32_t sizeInBytes, uint32_t C, uint32_t W)
{
uint32_t bitOffset=0;
uint32_t currentSample = 0;
uint32_t A = 0; /* the sample value currently being counted */
uint32_t B = 0; /* the current number of times that A has been seen in the S samples examined so far */
uint32_t i = 0; /* the counter for the number of samples examined in the current window */
uint32_t bitsPerSample = 1; /* binary source */
if (pData == NULL || sizeInBytes == 0 || LLF_RND_TRNG90B_MAX_BYTES < sizeInBytes || W == 0 || C == 0) {
return LLF_RND_TRNG_ADAPTION_PROPORTION_ERROR;
}
/* The test is performed as follows: */
for (bitOffset = 0; bitOffset <= (sizeInBytes * UINT8_SIZE_IN_BITS) - bitsPerSample; bitOffset += bitsPerSample) {
currentSample = getBitsFromUint32Array(bitOffset, bitsPerSample, (uint32_t*)pData);
/* 1. Let A be the current sample value. */
/* 2. Initialize the counter B to 1 */
if ((bitOffset == 0) || (i == W)) {
A = currentSample;
B = 1;
i = 0;
}
/* 3. For i = 1 to W-1 */
else {
/* If the next sample is equal to A, increment B by 1. */
if (A == currentSample) {
++B;
}
}
/* 4. If B > C, return error. */
if (i == W - 1) {
if (B > C) {
return LLF_RND_TRNG_ADAPTION_PROPORTION_ERROR;
}
}
++i;
/* 5. Go to Step 1. */
}
return CC_OK;
}
/*
implementation of Continuous Testing (NIST SP 800-90B 6.5.1.2)
*/
CCError_t runContinuousTesting(uint32_t* pData, uint32_t sizeInBytes)
{
CCError_t error = CC_OK;
uint32_t repC = CC_CONFIG_TRNG90B_REPETITION_COUNTER_CUTOFF;
uint32_t adpW = CC_CONFIG_TRNG90B_ADAPTIVE_PROPORTION_WINDOW_SIZE;
uint32_t adpC = CC_CONFIG_TRNG90B_ADAPTIVE_PROPORTION_CUTOFF;
error = LLF_RND_RepetitionCounterTest(pData, sizeInBytes, repC);
if (error != CC_OK) {
return error;
}
error = LLF_RND_AdaptiveProportionTest(pData, sizeInBytes, adpC, adpW);
if (error != CC_OK) {
return error;
}
return CC_OK;
}

View File

@@ -0,0 +1,386 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, 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. *
******************************************************************************/
#include "tztrng_defs.h"
#include "tztrng_pal.h"
static CCError_t startTrngHW(
CCRndState_t *rndState_ptr,
CCRndParams_t *trngParams_ptr,
CCBool_t isRestart,
uint32_t *roscsToStart_ptr,
CCBool_t isStartup);
extern CCError_t runContinuousTesting(uint32_t* pData, uint32_t sizeInBytes);
/************************************************************************************/
/**
* The function checks that parameters, loaded in the TRNG HW
* are match to parameters, required by trngParams_ptr structures.
*
* @author reuvenl (6/25/2012)
*
* @param trngParams_ptr
*
* @return CCError_t
*/
static CCError_t LLF_RND_TRNG_CheckHwParams(CCRndParams_t *trngParams_ptr)
{
uint32_t temp;
CCBool_t isTrue = CC_TRUE;
/* check Debug control - masked TRNG tests according to mode */
temp = CC_HAL_READ_REGISTER(CC_REG_OFFSET(RNG, TRNG_DEBUG_CONTROL));
isTrue &= (temp == LLF_RND_HW_DEBUG_CONTROL_VALUE_ON_TRNG90B_MODE);
/* check samplesCount */
temp = CC_HAL_READ_REGISTER(CC_REG_OFFSET(RNG,SAMPLE_CNT1));
isTrue &= (temp == trngParams_ptr->SubSamplingRatio);
/* if any parameters are not match return an Error */
if (isTrue == CC_FALSE)
return LLF_RND_TRNG_PREVIOUS_PARAMS_NOT_MATCH_ERROR;
else
return CC_OK;
}
static int32_t readEhrData(uint32_t *sample,
CCRndState_t *rndState_ptr,
CCRndParams_t *trngParams_ptr,
uint32_t *roscsToStart_ptr)
{
uint32_t i;
CCError_t err = CC_OK;
err = startTrngHW(rndState_ptr, trngParams_ptr, CC_FALSE, roscsToStart_ptr, CC_FALSE);
if (err) {
TRNG_LOG_DEBUG("startTrngHW() failed..\n");
return err;
}
/* Read 1 EHR of random bits */
if (CC_HalWaitInterrupt()) {
TRNG_LOG_DEBUG("CC_HalWaitInterrupt() failed..\n");
LLF_RND_TurnOffTrng();
return (-1);
}
/* Read EHR into tmp buffer */
for (i = 0; i < TRNG_EHR_SIZE; i++) {
uint32_t ehr = CC_HAL_READ_REGISTER(DX_EHR_DATA_0_REG_OFFSET + (i * sizeof(uint32_t)));
TRNG_EHR_DUMP("EHR[%i][0x%x]\n", i, ehrp);
sample[i] = ehr;
}
return CC_OK;
}
static CCError_t readMultipleEHR(uint32_t inSize, uint8_t *ramAddr,
CCRndState_t *rndState_ptr,
CCRndParams_t *trngParams_ptr,
uint32_t *roscsToStart_ptr)
{
uint32_t noise_samples[TRNG_EHR_SIZE];
CCError_t err = CC_OK;
uint32_t read_size = TRNG_EHR_SIZE * sizeof(uint32_t);
while (inSize) {
LLF_RND_TurnOffTrng();
err = readEhrData(noise_samples, rndState_ptr, trngParams_ptr, roscsToStart_ptr);
if (err != CC_OK)
return err;
/* Copy the needed amount of bytes to the result buffer */
tztrng_memcpy(ramAddr, (uint8_t *)noise_samples, read_size);
inSize -= read_size;
ramAddr += read_size;
}
return CC_OK;
}
static CCError_t startTrngHW(
CCRndState_t *rndState_ptr,
CCRndParams_t *trngParams_ptr,
CCBool_t isRestart,
uint32_t *roscsToStart_ptr,
CCBool_t isStartup)
{
/* LOCAL DECLARATIONS */
CCError_t error = CC_OK;
uint32_t tmpSamplCnt = 0;
uint32_t roscNum = 0;
CC_UNUSED_PARAM(isStartup);
/* FUNCTION LOGIC */
/* Check pointers */
if ((rndState_ptr == NULL) || (trngParams_ptr == NULL) ||
(roscsToStart_ptr == NULL))
return LLF_RND_TRNG_ILLEGAL_PTR_ERROR;
/*--------------------------------------------------------------*/
/* 1. If full restart, get semaphore and set initial ROSCs */
/*--------------------------------------------------------------*/
if (isRestart) {
/* set ROSC to 1 (fastest) */
*roscsToStart_ptr = 1UL;
/* init rndState flags to zero */
rndState_ptr->TrngProcesState = 0;
}
if (*roscsToStart_ptr == 0)
return LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR;
/* TRNG90B mode */
/* Get fastest allowed ROSC */
error = LLF_RND_GetFastestRosc(
trngParams_ptr,
roscsToStart_ptr /*in/out*/);
if (error)
return error;
error = LLF_RND_GetRoscSampleCnt(*roscsToStart_ptr, trngParams_ptr);
if (error)
return error;
roscNum = LLF_RND_TRNG_RoscMaskToNum(*roscsToStart_ptr);
/*--------------------------------------------------------------*/
/* 2. Restart the TRNG and set parameters */
/*--------------------------------------------------------------*/
/* in order to verify that the reset has completed the sample count need to be verified */
do {
/* set sampling ratio (rng_clocks) between consequtive bits */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, SAMPLE_CNT1), trngParams_ptr->SubSamplingRatio);
/* read the sampling ratio */
tmpSamplCnt = CC_HAL_READ_REGISTER(CC_REG_OFFSET(RNG, SAMPLE_CNT1));
} while (tmpSamplCnt != trngParams_ptr->SubSamplingRatio);
/* disable the RND source for setting new parameters in HW */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RND_SOURCE_ENABLE), LLF_RND_HW_RND_SRC_DISABLE_VAL);
/* set TRNG_CONFIG to choose SOP_SEL = 1 - i.e. EHR output */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, TRNG_CONFIG), roscNum);
/* Debug Control register: set to 0 - no bypasses */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, TRNG_DEBUG_CONTROL), LLF_RND_HW_DEBUG_CONTROL_VALUE_ON_TRNG90B_MODE);
/* set interrupt mask */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_IMR), LLF_RNG_INT_MASK_ON_TRNG90B_MODE);
/* clear RNG interrupts !!TBD */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_ICR), 0xFFFFFFFF);
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RND_SOURCE_ENABLE), LLF_RND_HW_RND_SRC_ENABLE_VAL);
/* set indication about current started ROSCs: */
/*new started*/
rndState_ptr->TrngProcesState = (rndState_ptr->TrngProcesState & 0x00ffffff) | (*roscsToStart_ptr << 24);
/*total started*/
rndState_ptr->TrngProcesState |= (*roscsToStart_ptr << 8);
/* end of function */
return error;
}
static CCError_t getTrngSource(
CCRndState_t *rndState_ptr, /*in/out*/
CCRndParams_t *trngParams_ptr, /*in/out*/
CCBool_t isContinued, /*in*/
uint32_t **sourceOut_ptr_ptr, /*out*/
uint32_t *sourceOutSize_ptr,/*in/out*/
uint32_t *rndWorkBuff_ptr, /*in*/
CCBool_t isStartup) /*in*/
{
/* LOCAL DECLARATIONS */
/* The return error identifier */
CCError_t error = 0, descrError = 0;
int32_t i;
uint32_t roscToStart;
uint32_t *ramAddr;
const uint32_t trng90bRequiredBytes = (isStartup == CC_FALSE ? CC_CONFIG_TRNG90B_AMOUNT_OF_BYTES : CC_CONFIG_TRNG90B_AMOUNT_OF_BYTES_STARTUP);
/* FUNCTION LOGIC */
/* ............... local initializations .............................. */
/* -------------------------------------------------------------------- */
/* initializing the Error to O.K */
error = CC_OK;
/* Set source RAM address with offset 8 bytes from sourceOut address in
order to remain empty bytes for CC operations */
*sourceOut_ptr_ptr = rndWorkBuff_ptr;
ramAddr = *sourceOut_ptr_ptr;
/* init to 0 for FE mode */
*sourceOutSize_ptr = 0;
/* If not continued mode, set TRNG parameters and restart TRNG */
/*--------------------------------------------------------------*/
if (isContinued == CC_FALSE) {
/* Full restart TRNG */
error = startTrngHW(
rndState_ptr,
trngParams_ptr,
CC_TRUE/*isRestart*/,
&roscToStart,
isStartup);
/*Note: in case of error the TRNG HW is still not started*/
if (error)
goto End;
}
/* On continued mode check HW TRNG */
else {
/* check TRNG parameters */
error = LLF_RND_TRNG_CheckHwParams(trngParams_ptr);
if (error != CC_OK)
goto End;
/* previously started ROSCs */
roscToStart = (rndState_ptr->TrngProcesState & 0xff000000) >> 24;
}
/*====================================================*/
/*====================================================*/
/* Processing after previous start */
/*====================================================*/
/*====================================================*/
/*====================================================*/
/* TRNG90b mode processing: start Roscs sequentionally - *
* from fast to slow Rosc */
/*====================================================*/
for (i = 0; i < LLF_RND_NUM_OF_ROSCS; ++i) {
*sourceOutSize_ptr = trng90bRequiredBytes;
descrError = readMultipleEHR(*sourceOutSize_ptr, (uint8_t *)ramAddr,
rndState_ptr,
trngParams_ptr,
&roscToStart);
if (descrError == CC_OK) {
error = runContinuousTesting(ramAddr, *sourceOutSize_ptr);
if (error == CC_OK) {
break;
}
*sourceOutSize_ptr = 0;
}
else {
/* Note: Priority to SW error */
error = descrError;
}
/* update total processed ROSCs */
rndState_ptr->TrngProcesState |= ((rndState_ptr->TrngProcesState >> 8) & 0x00FF0000);
/*clean started & not processed*/
rndState_ptr->TrngProcesState &= 0x00FFFFFF;
/* case of erors or watchdog exceed - try next rosc */
/* if no remain roscs to start, return error */
if (roscToStart == 0x8) {
error = LLF_RND_TRNG_GENERATION_NOT_COMPLETED_ERROR;
break;
} else {
/* Call StartTrng, with next ROSC */
roscToStart <<= 1;
TRNG_LOG_DEBUG("process with next rosc[%d]\n",(int) roscToStart);
error = startTrngHW(
rndState_ptr,
trngParams_ptr,
CC_FALSE/*isRestart*/,
&roscToStart,
isStartup);
if (error != CC_OK)
goto End;
}
}
/* ................. end of function ..................................... */
/* ----------------------------------------------------------------------- */
End:
/* turn the RNG off */
LLF_RND_TurnOffTrng();
return error;
} /* END of getTrngSource */
/****************************************************************************************/
/***************************** Public Functions ******************************/
/****************************************************************************************/
CCError_t LLF_RND_StartTrngHW(
CCRndState_t *rndState_ptr,
CCRndParams_t *trngParams_ptr,
CCBool_t isRestart,
uint32_t *roscsToStart_ptr)
{
CCError_t error = CC_OK;
error = startTrngHW(rndState_ptr, trngParams_ptr, isRestart, roscsToStart_ptr, CC_FALSE/*isStartup*/);
return error;
}
CCError_t LLF_RND_GetTrngSource(
CCRndState_t *rndState_ptr, /*in/out*/
CCRndParams_t *trngParams_ptr, /*in/out*/
CCBool_t isContinued, /*in*/
uint32_t **sourceOut_ptr_ptr,/*out*/
uint32_t *sourceOutSize_ptr, /*in/out*/
uint32_t *rndWorkBuff_ptr) /*in*/
{
CCError_t error = CC_OK;
error = getTrngSource(rndState_ptr, trngParams_ptr, isContinued,
sourceOut_ptr_ptr, sourceOutSize_ptr, rndWorkBuff_ptr, CC_FALSE/*isStartup*/);
return error;
}
CCError_t LLF_RND_RunTrngStartupTest(
CCRndState_t *rndState_ptr,
CCRndParams_t *trngParams_ptr,
uint32_t *rndWorkBuff_ptr)
{
CCError_t error = CC_OK;
uint32_t *pSourceOut;
uint32_t sourceOutSize;
error = getTrngSource(rndState_ptr, trngParams_ptr, CC_FALSE/*isContinued*/,
&pSourceOut, &sourceOutSize, rndWorkBuff_ptr, CC_TRUE/* isStartup*/);
return error;
}

View File

@@ -0,0 +1,118 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, 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. *
******************************************************************************/
#include "tztrng_defs.h"
#include "tztrng_pal.h"
unsigned long gCcRegBase = 0;
static CCError_t RNG_PLAT_SetUserRngParameters(CCRndParams_t *pTrngParams)
{
CCError_t error = CC_OK;
/* Set TRNG parameters */
pTrngParams->SubSamplingRatio1 = CC_CONFIG_SAMPLE_CNT_ROSC_1;
pTrngParams->SubSamplingRatio2 = CC_CONFIG_SAMPLE_CNT_ROSC_2;
pTrngParams->SubSamplingRatio3 = CC_CONFIG_SAMPLE_CNT_ROSC_3;
pTrngParams->SubSamplingRatio4 = CC_CONFIG_SAMPLE_CNT_ROSC_4;
/* Allowed ROSCs lengths b'0-3. If bit value 1 - appropriate ROSC is allowed. */
pTrngParams->RoscsAllowed = (((pTrngParams->SubSamplingRatio1 > 0) ? 0x1 : 0x0) |
((pTrngParams->SubSamplingRatio2 > 0) ? 0x2 : 0x0) |
((pTrngParams->SubSamplingRatio3 > 0) ? 0x4 : 0x0) |
((pTrngParams->SubSamplingRatio4 > 0) ? 0x8 : 0x0));
pTrngParams->SubSamplingRatio = 0;
if (0 == pTrngParams->RoscsAllowed) {
TRNG_LOG_DEBUG("No ROSC allowed!!\n");
return LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR;
}
return error;
}
uint32_t CC_TrngGetSource(unsigned long rngRegBase, uint8_t *outAddr, size_t *outLen, size_t reqBits)
{
CCError_t Err = CC_OK;
uint32_t rndWorkBuff[CC_RND_WORK_BUFFER_SIZE_WORDS];
CCRndParams_t rndParams;
CCRndState_t rndState = {0};
uint32_t *rndSrc_ptr;
uint32_t sourceOutSizeBytes = 0;
uint32_t requireBytes = (reqBits % 8) ? (reqBits / 8 + 1) : (reqBits / 8);
if (NULL == outAddr || NULL == outLen) {
TRNG_LOG_DEBUG("NULL pointer!!\n");
return LLF_RND_TRNG_ILLEGAL_PTR_ERROR;
}
/* zeroe the rnd buff */
tztrng_memset((uint8_t *)rndWorkBuff, 0, sizeof(rndWorkBuff));
tztrng_memset((uint8_t *)&rndParams, 0, sizeof(CCRndParams_t));
gCcRegBase = rngRegBase;
if (gCcRegBase == 0) {
TRNG_LOG_DEBUG("register base not initialized\n");
return LLF_RND_TRNG_ILLEGAL_PTR_ERROR;
}
/* Get parameters and set them in the RND structures */
Err = RNG_PLAT_SetUserRngParameters(&rndParams);
if (Err != CC_OK)
return Err;
Err = LLF_RND_RunTrngStartupTest(&rndState, &rndParams, rndWorkBuff);
if (Err != CC_OK)
return Err;
*outLen = requireBytes;
while (requireBytes > 0) {
/* Get TRNG Source */
Err = LLF_RND_GetTrngSource(
&rndState,
&rndParams,
0,
&rndSrc_ptr,
&sourceOutSizeBytes,
rndWorkBuff);
if (Err) {
TRNG_LOG_DEBUG("LLF_RND_GetTrngSource failed, err[0x%X]\n", (unsigned int)Err);
/* memset 0 to outAddr for security concern */
tztrng_memset(outAddr, 0, *outLen);
*outLen = 0;
return Err;
}
/* try to reduce the memcpy */
if (requireBytes < sourceOutSizeBytes) {
tztrng_memcpy(outAddr, (uint8_t *)rndSrc_ptr, requireBytes);
requireBytes = 0;
} else {
tztrng_memcpy(outAddr, (uint8_t *)rndSrc_ptr, sourceOutSizeBytes);
requireBytes -= sourceOutSizeBytes;
}
outAddr += sourceOutSizeBytes;
}
/* Clear the rndWorkBuff to not leave entropy on the stack */
tztrng_memset((uint8_t *)rndWorkBuff, 0, sizeof(rndWorkBuff));
return Err;
}

View File

@@ -0,0 +1,99 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, 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. *
******************************************************************************/
#include "tztrng_defs.h"
uint32_t CC_HalWaitInterrupt(void)
{
uint32_t isr = 0;
uint32_t crngterr = 0;
uint32_t abort = 0;
#ifdef CHECK_VN_AC_ERR
uint32_t vnerr = 0;
#endif
/* Polling ISR value */
do {
isr = CC_HAL_READ_REGISTER(DX_RNG_ISR_REG_OFFSET);
if (isr & 0x1 << DX_RNG_ISR_EHR_VALID_BIT_SHIFT) {
return 0;
}
if (isr & 0x1 << DX_RNG_ISR_CRNGT_ERR_BIT_SHIFT) {
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_ICR), 0x1 << DX_RNG_ISR_CRNGT_ERR_BIT_SHIFT);
crngterr++;
TRNG_LOG_DEBUG("CRNGT error detected[%d]\n", (int)crngterr);
if (crngterr >= TRNG_MAX_CRNGT_ERRORS)
abort = 1;
}
#ifdef CHECK_VN_AC_ERR
if (isr & 0x1 << DX_RNG_ISR_VN_ERR_BIT_SHIFT) {
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_ICR), 0x1 << DX_RNG_ISR_VN_ERR_BIT_SHIFT);
vnerr++;
TRNG_LOG_DEBUG("VN error detected[%d]\n", vnerr);
if (vnerr >= TRNG_MAX_VN_ERRORS)
abort = 1;
}
if (isr & 0x1 << DX_RNG_ISR_AUTOCORR_ERR_BIT_SHIFT) {
TRNG_LOG_DEBUG("AUTOCORR error detected\n");
abort = 1;
}
#endif
} while (!abort);
TRNG_LOG_DEBUG("abort leave..\n");
return LLF_RND_CRNGT_TEST_FAIL_ERROR;
}
/************************************************************************************/
/**
* @brief The LLF_RND_TurnOffTrng stops the hardware random bits collection
* closes RND clocks and releases HW semaphore.
*
* @return CCError_t - On success CC_OK is returned, on failure a
* value MODULE_* as defined in ...
*/
void LLF_RND_TurnOffTrng(void)
{
/* disable the RND source */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG,RND_SOURCE_ENABLE), LLF_RND_HW_RND_SRC_DISABLE_VAL);
/* clear RNG interrupts */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_ICR), 0xFFFFFFFF);
return;
}
void tztrng_memcpy(uint8_t *dst, uint8_t *src, size_t size)
{
size_t i;
for(i = 0; i < size; i++)
dst[i] = src[i];
}
void tztrng_memset(uint8_t *dst, uint8_t value, size_t size)
{
size_t i;
for(i = 0; i < size; i++)
dst[i] = value;
}

View File

@@ -0,0 +1,101 @@
#!/usr/bin/env python
"""
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.
"""
"""
This script removes the files inside the TZ-TRNG driver that are unused by
Mbed OS.
The TZ-TRNG driver is an open-source driver (Apache 2.0) available here:
https://github.com/ARM-software/TZ-TRNG
The driver is used in Mbed OS in 800-90B TRNG mode.
It removes Makefiles, PDF, test files and FE-TRNG C files (the other TRNG mode
not used).
After the script is executed, this driver can be succesfully integrated and
compiled in a Mbed OS project and the CC_TrngGetSource function can be called,
for example in a Mbed OS HAL implementation for a new target.
This script needs to be executed at the root of the TZ-TRNG directory.
The .git folder and .gitignore file are not deleted by this script and should be
deleted manually.
"""
import os
import sys
# Files that this script will delete, if one of this files do not exist, the
# script will exit and do nothing. If all files of a directory have been
# deleted, then the directory will also be deleted.
FILES_TO_DELETE = ["TRNG_test.c",
"trustzone_trng_characterization_application_note_100685_0000_06_en.pdf",
"host/src/tests/tztrng_test/tztrng_test.c",
"host/src/tests/tztrng_test/Makefile",
"host/src/tests/tztrng_test/pal/tztrng_test_pal_api.h",
"host/src/tests/tztrng_test/pal/linux/tztrng_test_pal.c",
"host/src/tests/tztrng_test/pal/linux/tztrng_test_pal.h",
"host/src/tests/tztrng_test/pal/freertos/tztrng_test_pal.c",
"host/src/tests/tztrng_test/pal/freertos/tztrng_test_pal.h",
"host/src/tests/tztrng_test/tztrng_test.h",
"host/src/tests/tztrng_test/tztrng_test_arm.c",
"host/src/tztrng_lib/Makefile",
"host/src/tztrng_lib/llf_rnd_fetrng.c",
"host/Makefile.defs",
"host/Makefile.rules",
"host/Makefile.pal",
"host/Makefile.freertos",
"host/proj.cfg",
"build.props",
"proj.ext.cfg",
"trustzone_trng_software_integrators_manual_101049_0000_00_en.pdf"]
def show_help_exit():
print("mbed-os.py")
print("---------------------------------------------------------------")
print("This script removes the files inside the TZ-TRNG driver that")
print("are unused by Mbed OS. It needs to be executed at the root of")
print("the TZ-TRNG driver directory.")
print("---------------------------------------------------------------")
print("usage: ./mbed-os.py")
exit(1)
def main():
# Check if the help flag has been entered
if len(sys.argv) > 1:
option = sys.argv[1]
if option == "-h" or option == "--help":
show_help_exit()
# Check if all files exist
for file_to_delete in FILES_TO_DELETE:
if not os.path.exists(file_to_delete):
print("Error: file %s does not exist." % file_to_delete)
exit(2)
# Delete all the files and the the empty directories
for file_to_delete in FILES_TO_DELETE:
dir_path = os.path.dirname(file_to_delete)
os.remove(file_to_delete)
# Check if the directory containing the file we just deleted has become
# empty and delete it if it is the case
# If dir_path is empty the file to delete is at the root
if dir_path != "" and os.listdir(dir_path) == []:
os.rmdir(dir_path)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,251 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, All Rights Reserved *
* SPDX-License-Identifier: Apache-2.0 *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT *
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* *
* See the License for the specific language governing permissions and *
* limitations under the License. *
******************************************************************************/
#ifndef __DX_ZYNQ_ENV_H__
#define __DX_ZYNQ_ENV_H__
// --------------------------------------
// BLOCK: ENV_REGS
// --------------------------------------
#define DX_ENV_PKA_DEBUG_MODE_REG_OFFSET 0x024UL
#define DX_ENV_PKA_DEBUG_MODE_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_PKA_DEBUG_MODE_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_SCAN_MODE_REG_OFFSET 0x030UL
#define DX_ENV_SCAN_MODE_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_SCAN_MODE_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_ALLOW_SCAN_REG_OFFSET 0x034UL
#define DX_ENV_CC_ALLOW_SCAN_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_ALLOW_SCAN_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_LOWER_MONITOR_ADDR_REG_ADDR 0x060UL
#define DX_ENV_CC_LOWER_MONITOR_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_LOWER_MONITOR_ADDR_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CC_UPPER_MONITOR_ADDR_REG_ADDR 0x070UL
#define DX_ENV_CC_UPPER_MONITOR_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_UPPER_MONITOR_ADDR_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CC_HOST_INT_REG_OFFSET 0x0A0UL
#define DX_ENV_CC_HOST_INT_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_HOST_INT_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_RST_N_REG_OFFSET 0x0A8UL
#define DX_ENV_CC_RST_N_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_RST_N_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_RST_OVERRIDE_REG_OFFSET 0x0ACUL
#define DX_ENV_RST_OVERRIDE_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_RST_OVERRIDE_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_POR_N_ADDR_REG_OFFSET 0x0E0UL
#define DX_ENV_CC_POR_N_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_POR_N_ADDR_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_BM_LOWER_BOUND_ADDR_REG_OFFSET 0x0F0UL
#define DX_ENV_CC_BM_LOWER_BOUND_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_BM_LOWER_BOUND_ADDR_VALUE_BIT_SIZE 0x14UL
#define DX_ENV_CC_BM_UPPER_BOUND_ADDR_REG_OFFSET 0x0F4UL
#define DX_ENV_CC_BM_UPPER_BOUND_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_BM_UPPER_BOUND_ADDR_VALUE_BIT_SIZE 0x14UL
#define DX_ENV_CC_BM_ENB_ADDR_REG_OFFSET 0x0F8UL
#define DX_ENV_CC_BM_ENB_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_BM_ENB_ADDR_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_COLD_RST_REG_OFFSET 0x0FCUL
#define DX_ENV_CC_COLD_RST_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_COLD_RST_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_BM_ERR_ACK_ADDR_REG_OFFSET 0x100UL
#define DX_ENV_CC_BM_ERR_ACK_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_BM_ERR_ACK_ADDR_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_BM_CC_ERR_ADDR_REG_OFFSET 0x104UL
#define DX_ENV_BM_CC_ERR_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_BM_CC_ERR_ADDR_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_DUMMY_ADDR_REG_OFFSET 0x108UL
#define DX_ENV_DUMMY_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_DUMMY_ADDR_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_COUNTER_CLR_REG_OFFSET 0x118UL
#define DX_ENV_COUNTER_CLR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_COUNTER_CLR_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_COUNTER_RD_REG_OFFSET 0x11CUL
#define DX_ENV_COUNTER_RD_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_COUNTER_RD_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CC_SECOND_BM_LOWER_BOUND_ADDR_REG_OFFSET 0x120UL
#define DX_ENV_CC_SECOND_BM_LOWER_BOUND_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_SECOND_BM_LOWER_BOUND_ADDR_VALUE_BIT_SIZE 0x14UL
#define DX_ENV_CC_SECOND_BM_UPPER_BOUND_ADDR_REG_OFFSET 0x124UL
#define DX_ENV_CC_SECOND_BM_UPPER_BOUND_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_SECOND_BM_UPPER_BOUND_ADDR_VALUE_BIT_SIZE 0x14UL
#define DX_ENV_CC_SECOND_BM_ENB_ADDR_REG_OFFSET 0x128UL
#define DX_ENV_CC_SECOND_BM_ENB_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_SECOND_BM_ENB_ADDR_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_SECOND_BM_ERR_ACK_ADDR_REG_OFFSET 0x12CUL
#define DX_ENV_CC_SECOND_BM_ERR_ACK_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_SECOND_BM_ERR_ACK_ADDR_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_SECOND_BM_CC_ERR_ADDR_REG_OFFSET 0x130UL
#define DX_ENV_SECOND_BM_CC_ERR_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_SECOND_BM_CC_ERR_ADDR_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_RNG_DEBUG_ENABLE_REG_OFFSET 0x430UL
#define DX_ENV_RNG_DEBUG_ENABLE_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_RNG_DEBUG_ENABLE_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_WARM_BOOT_REG_OFFSET 0x434UL
#define DX_ENV_CC_WARM_BOOT_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_WARM_BOOT_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CC_LCS_REG_OFFSET 0x43CUL
#define DX_ENV_CC_LCS_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_LCS_VALUE_BIT_SIZE 0x8UL
#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_REG_OFFSET 0x440UL
#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_CM_BIT_SHIFT 0x0UL
#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_CM_BIT_SIZE 0x1UL
#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_DM_BIT_SHIFT 0x1UL
#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_DM_BIT_SIZE 0x1UL
#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_SECURE_BIT_SHIFT 0x2UL
#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_SECURE_BIT_SIZE 0x1UL
#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_RMA_BIT_SHIFT 0x3UL
#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_RMA_BIT_SIZE 0x1UL
#define DX_ENV_DCU_EN_REG_OFFSET 0x444UL
#define DX_ENV_DCU_EN_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_DCU_EN_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CC_LCS_IS_VALID_REG_OFFSET 0x448UL
#define DX_ENV_CC_LCS_IS_VALID_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CC_LCS_IS_VALID_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_CRYPTOKEY_0_REG_OFFSET 0x458UL
#define DX_ENV_CRYPTOKEY_0_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CRYPTOKEY_0_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CRYPTOKEY_1_REG_OFFSET 0x45CUL
#define DX_ENV_CRYPTOKEY_1_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CRYPTOKEY_1_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CRYPTOKEY_2_REG_OFFSET 0x460UL
#define DX_ENV_CRYPTOKEY_2_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CRYPTOKEY_2_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CRYPTOKEY_3_REG_OFFSET 0x464UL
#define DX_ENV_CRYPTOKEY_3_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CRYPTOKEY_3_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CRYPTOKEY_4_REG_OFFSET 0x468UL
#define DX_ENV_CRYPTOKEY_4_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CRYPTOKEY_4_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CRYPTOKEY_5_REG_OFFSET 0x46CUL
#define DX_ENV_CRYPTOKEY_5_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CRYPTOKEY_5_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CRYPTOKEY_6_REG_OFFSET 0x470UL
#define DX_ENV_CRYPTOKEY_6_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CRYPTOKEY_6_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_CRYPTOKEY_7_REG_OFFSET 0x474UL
#define DX_ENV_CRYPTOKEY_7_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_CRYPTOKEY_7_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_POWER_DOWN_REG_OFFSET 0x478UL
#define DX_ENV_POWER_DOWN_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_POWER_DOWN_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_ROM_BANK_REG_OFFSET 0x47CUL
#define DX_ENV_ROM_BANK_BIT_SHIFT 0x0UL
#define DX_ENV_ROM_BANK_BIT_SIZE 0x1UL
#define DX_ENV_OTF_SECURE_BOOT_DONE_REG_OFFSET 0x480UL
#define DX_ENV_OTF_SECURE_BOOT_DONE_BIT_SHIFT 0x0UL
#define DX_ENV_OTF_SECURE_BOOT_DONE_BIT_SIZE 0x1UL
#define DX_ENV_DCU_H_EN_REG_OFFSET 0x484UL
#define DX_ENV_DCU_H_EN_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_DCU_H_EN_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_VERSION_REG_OFFSET 0x488UL
#define DX_ENV_VERSION_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_VERSION_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_ROSC_WRITE_REG_OFFSET 0x48CUL
#define DX_ENV_ROSC_WRITE_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_ROSC_WRITE_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_ROSC_ADDR_REG_OFFSET 0x490UL
#define DX_ENV_ROSC_ADDR_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_ROSC_ADDR_VALUE_BIT_SIZE 0x8UL
#define DX_ENV_RESET_SESSION_KEY_REG_OFFSET 0x494UL
#define DX_ENV_RESET_SESSION_KEY_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_RESET_SESSION_KEY_VALUE_BIT_SIZE 0x2UL
#define DX_ENV_SESSION_KEY_0_REG_OFFSET 0x4A0UL
#define DX_ENV_SESSION_KEY_0_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_SESSION_KEY_0_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_SESSION_KEY_1_REG_OFFSET 0x4A4UL
#define DX_ENV_SESSION_KEY_1_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_SESSION_KEY_1_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_SESSION_KEY_2_REG_OFFSET 0x4A8UL
#define DX_ENV_SESSION_KEY_2_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_SESSION_KEY_2_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_SESSION_KEY_3_REG_OFFSET 0x4ACUL
#define DX_ENV_SESSION_KEY_3_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_SESSION_KEY_3_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_SESSION_KEY_VALID_REG_OFFSET 0x4B0UL
#define DX_ENV_SESSION_KEY_VALID_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_SESSION_KEY_VALID_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_DEBUG_EN_REG_OFFSET 0x4B4UL
#define DX_ENV_DEBUG_EN_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_DEBUG_EN_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_SPIDEN_REG_OFFSET 0x4D0UL
#define DX_ENV_SPIDEN_BIT_SHIFT 0x0UL
#define DX_ENV_SPIDEN_BIT_SIZE 0x1UL
#define DX_ENV_AO_CCP_LCS_IS_SD_REG_OFFSET 0x4D4UL
#define DX_ENV_AO_CCP_LCS_IS_SD_BIT_SHIFT 0x0UL
#define DX_ENV_AO_CCP_LCS_IS_SD_BIT_SIZE 0x1UL
#define DX_ENV_AXIM_USER_PARAMS_REG_OFFSET 0x600UL
#define DX_ENV_AXIM_ARUSER_PARAMS_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_AXIM_ARUSER_PARAMS_VALUE_BIT_SIZE 0x5UL
#define DX_ENV_AXIM_AWUSER_PARAMS_VALUE_BIT_SHIFT 0x5UL
#define DX_ENV_AXIM_AWUSER_PARAMS_VALUE_BIT_SIZE 0x5UL
#define DX_ENV_SECURITY_MODE_OVERRIDE_REG_OFFSET 0x604UL
#define DX_ENV_AWPROT_NS_BIT_SHIFT 0x0UL
#define DX_ENV_AWPROT_NS_BIT_SIZE 0x1UL
#define DX_ENV_AWPROT_NS_OVRD_BIT_SHIFT 0x1UL
#define DX_ENV_AWPROT_NS_OVRD_BIT_SIZE 0x1UL
#define DX_ENV_ARPROT_NS_BIT_SHIFT 0x2UL
#define DX_ENV_ARPROT_NS_BIT_SIZE 0x1UL
#define DX_ENV_ARPROT_NS_OVRD_BIT_SHIFT 0x3UL
#define DX_ENV_ARPROT_NS_OVRD_BIT_SIZE 0x1UL
#define DX_ENV_AO_CC_KPLT_0_REG_OFFSET 0x620UL
#define DX_ENV_AO_CC_KPLT_0_BIT_SHIFT 0x0UL
#define DX_ENV_AO_CC_KPLT_0_BIT_SIZE 0x20UL
#define DX_ENV_AO_CC_KPLT_1_REG_OFFSET 0x624UL
#define DX_ENV_AO_CC_KPLT_1_BIT_SHIFT 0x0UL
#define DX_ENV_AO_CC_KPLT_1_BIT_SIZE 0x20UL
#define DX_ENV_AO_CC_KPLT_2_REG_OFFSET 0x628UL
#define DX_ENV_AO_CC_KPLT_2_BIT_SHIFT 0x0UL
#define DX_ENV_AO_CC_KPLT_2_BIT_SIZE 0x20UL
#define DX_ENV_AO_CC_KPLT_3_REG_OFFSET 0x62CUL
#define DX_ENV_AO_CC_KPLT_3_BIT_SHIFT 0x0UL
#define DX_ENV_AO_CC_KPLT_3_BIT_SIZE 0x20UL
#define DX_ENV_AO_CC_KCST_0_REG_OFFSET 0x630UL
#define DX_ENV_AO_CC_KCST_0_BIT_SHIFT 0x0UL
#define DX_ENV_AO_CC_KCST_0_BIT_SIZE 0x20UL
#define DX_ENV_AO_CC_KCST_1_REG_OFFSET 0x634UL
#define DX_ENV_AO_CC_KCST_1_BIT_SHIFT 0x0UL
#define DX_ENV_AO_CC_KCST_1_BIT_SIZE 0x20UL
#define DX_ENV_AO_CC_KCST_2_REG_OFFSET 0x638UL
#define DX_ENV_AO_CC_KCST_2_BIT_SHIFT 0x0UL
#define DX_ENV_AO_CC_KCST_2_BIT_SIZE 0x20UL
#define DX_ENV_AO_CC_KCST_3_REG_OFFSET 0x63CUL
#define DX_ENV_AO_CC_KCST_3_BIT_SHIFT 0x0UL
#define DX_ENV_AO_CC_KCST_3_BIT_SIZE 0x20UL
// --------------------------------------
// BLOCK: ENV_CC_MEMORIES
// --------------------------------------
#define DX_ENV_FUSE_READY_REG_OFFSET 0x414UL
#define DX_ENV_FUSE_READY_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_FUSE_READY_VALUE_BIT_SIZE 0x1UL
//#define DX_ENV_FUSES_RAM_REG_OFFSET 0x800UL //Not connected in RAM controller
//#define DX_ENV_FUSES_RAM_VALUE_BIT_SHIFT 0x0UL
//#define DX_ENV_FUSES_RAM_VALUE_BIT_SIZE 0x20UL
#define DX_ENV_PERF_RAM_MASTER_REG_OFFSET 0x500UL
#define DX_ENV_PERF_RAM_MASTER_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_PERF_RAM_MASTER_VALUE_BIT_SIZE 0x1UL
#define DX_ENV_PERF_RAM_ADDR_HIGH4_REG_OFFSET 0x504UL
#define DX_ENV_PERF_RAM_ADDR_HIGH4_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_PERF_RAM_ADDR_HIGH4_VALUE_BIT_SIZE 0x2UL
// --------------------------------------
// BLOCK: ENV_PERF_RAM_BASE
// --------------------------------------
#define DX_ENV_PERF_RAM_BASE_REG_OFFSET 0x000UL
#define DX_ENV_PERF_RAM_BASE_VALUE_BIT_SHIFT 0x0UL
#define DX_ENV_PERF_RAM_BASE_VALUE_BIT_SIZE 0x20UL
#endif //__DX_RNG_H__

View File

@@ -0,0 +1,41 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, All Rights Reserved *
* SPDX-License-Identifier: Apache-2.0 *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT *
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* *
* See the License for the specific language governing permissions and *
* limitations under the License. *
******************************************************************************/
#ifndef __DX_REG_BASE_HOST_H__
#define __DX_REG_BASE_HOST_H__
/*!
@file
@brief This file contains general HW related definitions.
*/
/*! Identify platform: Xilinx Zynq7000 ZC706 */
#define DX_PLAT_ZYNQ7000 1
#define DX_PLAT_ZYNQ7000_ZC706 1
/*! SEP core clock frequency in MHz */
#define DX_SEP_FREQ_MHZ 50
/*! Base address for Sansa Silicon-Secure registers. It must be modified to match the mapping of Sansa Silicon-Secure on the customer's *
* platform.*/
#define DX_BASE_RNG 0x40000000
/*! Base address for FPGA environment registers */
#define DX_BASE_ENV_REGS 0x80008000
#endif /*__DX_REG_BASE_HOST_H__*/

View File

@@ -0,0 +1,112 @@
/******************************************************************************
* Copyright (c) 2017-2017, ARM, All Rights Reserved *
* SPDX-License-Identifier: Apache-2.0 *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT *
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* *
* See the License for the specific language governing permissions and *
* limitations under the License. *
******************************************************************************/
#ifndef __DX_RNG_H__
#define __DX_RNG_H__
// --------------------------------------
// BLOCK: RNG
// --------------------------------------
#define DX_RNG_IMR_REG_OFFSET 0x100UL
#define DX_RNG_IMR_EHR_VALID_INT_MASK_BIT_SHIFT 0x0UL
#define DX_RNG_IMR_EHR_VALID_INT_MASK_BIT_SIZE 0x1UL
#define DX_RNG_IMR_AUTOCORR_ERR_INT_MASK_BIT_SHIFT 0x1UL
#define DX_RNG_IMR_AUTOCORR_ERR_INT_MASK_BIT_SIZE 0x1UL
#define DX_RNG_IMR_CRNGT_ERR_INT_MASK_BIT_SHIFT 0x2UL
#define DX_RNG_IMR_CRNGT_ERR_INT_MASK_BIT_SIZE 0x1UL
#define DX_RNG_IMR_VN_ERR_INT_MASK_BIT_SHIFT 0x3UL
#define DX_RNG_IMR_VN_ERR_INT_MASK_BIT_SIZE 0x1UL
#define DX_RNG_ISR_REG_OFFSET 0x104UL
#define DX_RNG_ISR_EHR_VALID_BIT_SHIFT 0x0UL
#define DX_RNG_ISR_EHR_VALID_BIT_SIZE 0x1UL
#define DX_RNG_ISR_AUTOCORR_ERR_BIT_SHIFT 0x1UL
#define DX_RNG_ISR_AUTOCORR_ERR_BIT_SIZE 0x1UL
#define DX_RNG_ISR_CRNGT_ERR_BIT_SHIFT 0x2UL
#define DX_RNG_ISR_CRNGT_ERR_BIT_SIZE 0x1UL
#define DX_RNG_ISR_VN_ERR_BIT_SHIFT 0x3UL
#define DX_RNG_ISR_VN_ERR_BIT_SIZE 0x1UL
#define DX_RNG_ICR_REG_OFFSET 0x108UL
#define DX_RNG_ICR_EHR_VALID_BIT_SHIFT 0x0UL
#define DX_RNG_ICR_EHR_VALID_BIT_SIZE 0x1UL
#define DX_RNG_ICR_AUTOCORR_ERR_BIT_SHIFT 0x1UL
#define DX_RNG_ICR_AUTOCORR_ERR_BIT_SIZE 0x1UL
#define DX_RNG_ICR_CRNGT_ERR_BIT_SHIFT 0x2UL
#define DX_RNG_ICR_CRNGT_ERR_BIT_SIZE 0x1UL
#define DX_RNG_ICR_VN_ERR_BIT_SHIFT 0x3UL
#define DX_RNG_ICR_VN_ERR_BIT_SIZE 0x1UL
#define DX_TRNG_CONFIG_REG_OFFSET 0x10CUL
#define DX_TRNG_CONFIG_RND_SRC_SEL_BIT_SHIFT 0x0UL
#define DX_TRNG_CONFIG_RND_SRC_SEL_BIT_SIZE 0x2UL
#define DX_TRNG_VALID_REG_OFFSET 0x110UL
#define DX_TRNG_VALID_VALUE_BIT_SHIFT 0x0UL
#define DX_TRNG_VALID_VALUE_BIT_SIZE 0x1UL
#define DX_EHR_DATA_0_REG_OFFSET 0x114UL
#define DX_EHR_DATA_0_VALUE_BIT_SHIFT 0x0UL
#define DX_EHR_DATA_0_VALUE_BIT_SIZE 0x20UL
#define DX_EHR_DATA_1_REG_OFFSET 0x118UL
#define DX_EHR_DATA_1_VALUE_BIT_SHIFT 0x0UL
#define DX_EHR_DATA_1_VALUE_BIT_SIZE 0x20UL
#define DX_EHR_DATA_2_REG_OFFSET 0x11CUL
#define DX_EHR_DATA_2_VALUE_BIT_SHIFT 0x0UL
#define DX_EHR_DATA_2_VALUE_BIT_SIZE 0x20UL
#define DX_EHR_DATA_3_REG_OFFSET 0x120UL
#define DX_EHR_DATA_3_VALUE_BIT_SHIFT 0x0UL
#define DX_EHR_DATA_3_VALUE_BIT_SIZE 0x20UL
#define DX_EHR_DATA_4_REG_OFFSET 0x124UL
#define DX_EHR_DATA_4_VALUE_BIT_SHIFT 0x0UL
#define DX_EHR_DATA_4_VALUE_BIT_SIZE 0x20UL
#define DX_EHR_DATA_5_REG_OFFSET 0x128UL
#define DX_EHR_DATA_5_VALUE_BIT_SHIFT 0x0UL
#define DX_EHR_DATA_5_VALUE_BIT_SIZE 0x20UL
#define DX_RND_SOURCE_ENABLE_REG_OFFSET 0x12CUL
#define DX_RND_SOURCE_ENABLE_VALUE_BIT_SHIFT 0x0UL
#define DX_RND_SOURCE_ENABLE_VALUE_BIT_SIZE 0x1UL
#define DX_SAMPLE_CNT1_REG_OFFSET 0x130UL
#define DX_SAMPLE_CNT1_VALUE_BIT_SHIFT 0x0UL
#define DX_SAMPLE_CNT1_VALUE_BIT_SIZE 0x20UL
#define DX_AUTOCORR_STATISTIC_REG_OFFSET 0x134UL
#define DX_AUTOCORR_STATISTIC_AUTOCORR_TRYS_BIT_SHIFT 0x0UL
#define DX_AUTOCORR_STATISTIC_AUTOCORR_TRYS_BIT_SIZE 0xEUL
#define DX_AUTOCORR_STATISTIC_AUTOCORR_FAILS_BIT_SHIFT 0xEUL
#define DX_AUTOCORR_STATISTIC_AUTOCORR_FAILS_BIT_SIZE 0x8UL
#define DX_TRNG_DEBUG_CONTROL_REG_OFFSET 0x138UL
#define DX_TRNG_DEBUG_CONTROL_VNC_BYPASS_BIT_SHIFT 0x1UL
#define DX_TRNG_DEBUG_CONTROL_VNC_BYPASS_BIT_SIZE 0x1UL
#define DX_TRNG_DEBUG_CONTROL_TRNG_CRNGT_BYPASS_BIT_SHIFT 0x2UL
#define DX_TRNG_DEBUG_CONTROL_TRNG_CRNGT_BYPASS_BIT_SIZE 0x1UL
#define DX_TRNG_DEBUG_CONTROL_AUTO_CORRELATE_BYPASS_BIT_SHIFT 0x3UL
#define DX_TRNG_DEBUG_CONTROL_AUTO_CORRELATE_BYPASS_BIT_SIZE 0x1UL
#define DX_RNG_SW_RESET_REG_OFFSET 0x140UL
#define DX_RNG_SW_RESET_VALUE_BIT_SHIFT 0x0UL
#define DX_RNG_SW_RESET_VALUE_BIT_SIZE 0x1UL
#define DX_RNG_BUSY_REG_OFFSET 0x1B8UL
#define DX_RNG_BUSY_RNG_BUSY_BIT_SHIFT 0x0UL
#define DX_RNG_BUSY_RNG_BUSY_BIT_SIZE 0x1UL
#define DX_RST_BITS_COUNTER_REG_OFFSET 0x1BCUL
#define DX_RST_BITS_COUNTER_VALUE_BIT_SHIFT 0x0UL
#define DX_RST_BITS_COUNTER_VALUE_BIT_SIZE 0x1UL
#define DX_RNG_BIST_CNTR_0_REG_OFFSET 0x1E0UL
#define DX_RNG_BIST_CNTR_0_ROSC_CNTR_VAL_BIT_SHIFT 0x0UL
#define DX_RNG_BIST_CNTR_0_ROSC_CNTR_VAL_BIT_SIZE 0x16UL
#define DX_RNG_BIST_CNTR_1_REG_OFFSET 0x1E4UL
#define DX_RNG_BIST_CNTR_1_ROSC_CNTR_VAL_BIT_SHIFT 0x0UL
#define DX_RNG_BIST_CNTR_1_ROSC_CNTR_VAL_BIT_SIZE 0x16UL
#define DX_RNG_BIST_CNTR_2_REG_OFFSET 0x1E8UL
#define DX_RNG_BIST_CNTR_2_ROSC_CNTR_VAL_BIT_SHIFT 0x0UL
#define DX_RNG_BIST_CNTR_2_ROSC_CNTR_VAL_BIT_SIZE 0x16UL
#endif //__DX_RNG_H__

View File

@@ -0,0 +1,316 @@
/*
* 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.
*/
#include "arm_gpio_drv.h"
#include <stddef.h>
/* GPIO state definitions */
#define ARM_GPIO_INITIALIZED (1 << 0)
#define MAX_PIN_NBR 16
/* GPIO register map structure */
struct arm_gpio_reg_map_t {
volatile uint32_t data; /* Offset: 0x000 (R/W) Data register */
volatile uint32_t dataout; /* Offset: 0x004 (R/W) Data output
* latch register */
volatile uint32_t reserved0[2];
volatile uint32_t outenableset; /* Offset: 0x010 (R/W) Output enable
* set register */
volatile uint32_t outenableclr; /* Offset: 0x014 (R/W) Output enable
* clear register */
volatile uint32_t altfuncset; /* Offset: 0x018 (R/W) Alternate function
* set register */
volatile uint32_t altfuncclr; /* Offset: 0x01C (R/W) Alternate function
* clear register */
volatile uint32_t intenset; /* Offset: 0x020 (R/W) Interrupt enable
* set register */
volatile uint32_t intenclr; /* Offset: 0x024 (R/W) Interrupt enable
* clear register */
volatile uint32_t inttypeset; /* Offset: 0x028 (R/W) Interrupt type
* set register */
volatile uint32_t inttypeclr; /* Offset: 0x02C (R/W) Interrupt type
* clear register */
volatile uint32_t intpolset; /* Offset: 0x030 (R/W) Interrupt polarity
* set register */
volatile uint32_t intpolclr; /* Offset: 0x034 (R/W) Interrupt polarity
* clear register */
union {
volatile uint32_t intstatus; /* Offset: 0x038 (R/ ) Interrupt status
* register */
volatile uint32_t intclear; /* Offset: 0x038 ( /W) Interrupt clear
* register */
}intreg;
volatile uint32_t reserved1[241];
volatile uint32_t lb_masked[256]; /* Offset: 0x400 - 0x7FC (R/W)
* Lower byte masked access register */
volatile uint32_t ub_masked[256]; /* Offset: 0x800 - 0xBFC (R/W)
* Upper byte masked access register */
};
/*
* \brief Configures the pin or port.
*
* \param[in] p_gpio_port GPIO port to configure \ref ahbarm_gpio_reg_map_t
* \param[in] mask Pin bit mask.
* \param[in] flags Pin flags.
*/
static void set_port_config(struct arm_gpio_reg_map_t* p_gpio_port,
uint32_t mask,
uint32_t flags)
{
if(flags & ARM_GPIO_PIN_DISABLE) {
p_gpio_port->altfuncset = mask;
return;
}
if(flags & ARM_GPIO_OUTPUT) {
p_gpio_port->outenableset = mask;
} else if(flags & ARM_GPIO_INPUT) {
p_gpio_port->outenableclr = mask;
}
/* Sets interrupt configuration */
if(flags & ARM_GPIO_IRQ) {
/* Interrupt type: EDGE = 1 - LEVEL = 0 */
if(flags & ARM_GPIO_IRQ_EDGE) {
p_gpio_port->inttypeset = mask;
} else if(flags & ARM_GPIO_IRQ_LEVEL) {
p_gpio_port->inttypeclr = mask;
}
/* Interrupt polarity */
if(flags & ARM_GPIO_IRQ_ACTIVE_LOW) {
p_gpio_port->intpolclr = mask;
} else if(flags & ARM_GPIO_IRQ_ACTIVE_HIGH) {
p_gpio_port->intpolset = mask;
}
}
if(flags & ARM_GPIO_PIN_ENABLE) {
p_gpio_port->altfuncclr = mask;
}
}
void arm_gpio_init(struct arm_gpio_dev_t* dev)
{
struct arm_gpio_reg_map_t* p_gpio_port =
(struct arm_gpio_reg_map_t*)dev->cfg->base;
if(dev->data->state != ARM_GPIO_INITIALIZED) {
/* Disables all pins in this port */
set_port_config(p_gpio_port, DEFAULT_PORT_MASK, ARM_GPIO_PIN_DISABLE);
dev->data->port_mask = DEFAULT_PORT_MASK;
dev->data->state = ARM_GPIO_INITIALIZED;
}
}
enum arm_gpio_error_t arm_gpio_config(struct arm_gpio_dev_t* dev,
enum arm_gpio_access_t access,
uint8_t pin_num,
uint32_t flags)
{
uint32_t pin_mask;
struct arm_gpio_reg_map_t* p_gpio_port =
(struct arm_gpio_reg_map_t*)dev->cfg->base;
if(dev->data->state != ARM_GPIO_INITIALIZED) {
return ARM_GPIO_ERR_PORT_NOT_INIT;
}
if(pin_num >= MAX_PIN_NBR) {
return ARM_GPIO_ERR_INVALID_ARG;
}
switch(access) {
case ARM_GPIO_ACCESS_PIN:
pin_mask = (1UL << pin_num);
set_port_config(p_gpio_port, pin_mask, flags);
break;
case ARM_GPIO_ACCESS_PORT:
set_port_config(p_gpio_port, dev->data->port_mask, flags);
break;
/* default: The default is not defined intentionally to force the
* compiler to check that all the enumeration values are
* covered in the switch.*/
}
return ARM_GPIO_ERR_NONE;
}
enum arm_gpio_error_t arm_gpio_write(struct arm_gpio_dev_t* dev,
enum arm_gpio_access_t access,
uint8_t pin_num,
uint32_t value)
{
struct arm_gpio_reg_map_t* p_gpio_port =
(struct arm_gpio_reg_map_t*)dev->cfg->base;
if(pin_num >= MAX_PIN_NBR) {
return ARM_GPIO_ERR_INVALID_ARG;
}
/* As ARM is a read-modify-write architecture, before set a
* value on a GPIO register it is required to disable the
* interrupts to prevent problems in a multitasking
* environment */
switch(access) {
case ARM_GPIO_ACCESS_PIN:
if(value) {
/* Sets the pin */
p_gpio_port->dataout |= (1UL << pin_num);
} else {
/* Clears the pin */
p_gpio_port->dataout &= ~(1UL << pin_num);
}
break;
case ARM_GPIO_ACCESS_PORT:
if(value) {
/* Sets masked pins */
p_gpio_port->dataout |= dev->data->port_mask;
} else {
/* Clears masked pins */
p_gpio_port->dataout &= ~(dev->data->port_mask);
}
break;
/* default: The default is not defined intentionally to force the
* compiler to check that all the enumeration values are
* covered in the switch. */
}
return ARM_GPIO_ERR_NONE;
}
int32_t arm_gpio_read(struct arm_gpio_dev_t* dev, enum arm_gpio_access_t access,
uint8_t pin_num)
{
uint32_t value;
struct arm_gpio_reg_map_t* p_gpio_port =
(struct arm_gpio_reg_map_t*)dev->cfg->base;
value = p_gpio_port->data;
if(access == ARM_GPIO_ACCESS_PIN) {
if(pin_num >= MAX_PIN_NBR) {
return -1;
}
value = ((value >> pin_num) & 1UL);
} else {
value &= dev->data->port_mask;
}
return (int32_t)value;
}
enum arm_gpio_error_t arm_gpio_set_interrupt(struct arm_gpio_dev_t* dev,
enum arm_gpio_access_t access,
uint8_t pin_num,
enum arm_gpio_irq_status_t status)
{
uint32_t mask = 0;
struct arm_gpio_reg_map_t* p_gpio_port =
(struct arm_gpio_reg_map_t*)dev->cfg->base;
if(dev->data->state != ARM_GPIO_INITIALIZED) {
return ARM_GPIO_ERR_PORT_NOT_INIT;
}
if(pin_num >= MAX_PIN_NBR) {
return ARM_GPIO_ERR_INVALID_ARG;
}
switch(access) {
case ARM_GPIO_ACCESS_PIN:
mask = (1UL << pin_num);
break;
case ARM_GPIO_ACCESS_PORT:
mask = dev->data->port_mask;
break;
/* default: The default is not defined intentionally to force the
* compiler to check that all the enumeration values are
* covered in the switch.*/
}
if(status == ARM_GPIO_IRQ_ENABLE) {
p_gpio_port->intenset = mask;
} else {
p_gpio_port->intenclr = mask;
}
return ARM_GPIO_ERR_NONE;
}
enum arm_gpio_error_t arm_gpio_get_irq_status(struct arm_gpio_dev_t* dev,
enum arm_gpio_access_t access,
uint8_t pin_num,
uint32_t* status)
{
struct arm_gpio_reg_map_t* p_gpio_port =
(struct arm_gpio_reg_map_t*)dev->cfg->base;
if(dev->data->state != ARM_GPIO_INITIALIZED) {
return ARM_GPIO_ERR_PORT_NOT_INIT;
}
if(pin_num >= MAX_PIN_NBR) {
return ARM_GPIO_ERR_INVALID_ARG;
}
*status = p_gpio_port->intreg.intstatus;
if(access == ARM_GPIO_ACCESS_PIN) {
*status = ((*status >> pin_num) & 1UL);
} else {
*status &= dev->data->port_mask;
}
return ARM_GPIO_ERR_NONE;
}
enum arm_gpio_error_t arm_gpio_clear_interrupt(struct arm_gpio_dev_t* dev,
uint8_t pin_num)
{
struct arm_gpio_reg_map_t* p_gpio_port =
(struct arm_gpio_reg_map_t*)dev->cfg->base;
if(dev->data->state != ARM_GPIO_INITIALIZED) {
return ARM_GPIO_ERR_PORT_NOT_INIT;
}
if(pin_num >= MAX_PIN_NBR) {
return ARM_GPIO_ERR_INVALID_ARG;
}
p_gpio_port->intreg.intstatus = (1UL << pin_num);
return ARM_GPIO_ERR_NONE;
}
void arm_gpio_set_port_mask(struct arm_gpio_dev_t* dev, uint32_t port_mask)
{
dev->data->port_mask = (port_mask & DEFAULT_PORT_MASK);
}
uint32_t arm_gpio_get_port_mask(struct arm_gpio_dev_t* dev)
{
if(dev->data->state != ARM_GPIO_INITIALIZED) {
return 0;
}
return (dev->data->port_mask & DEFAULT_PORT_MASK);
}

View File

@@ -0,0 +1,221 @@
/*
* 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.
*/
/**
* \file arm_gpio_drv.h
* \brief Generic driver for ARM GPIO.
*/
#ifndef __ARM_GPIO_DRV_H__
#define __ARM_GPIO_DRV_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define DEFAULT_PORT_MASK 0xFFFF /* Default port mask */
/* GPIO flags */
#define ARM_GPIO_PIN_DISABLE (1 << 0)
#define ARM_GPIO_PIN_ENABLE (1 << 1)
#define ARM_GPIO_OUTPUT (1 << 2)
#define ARM_GPIO_INPUT (1 << 3)
#define ARM_GPIO_IRQ (1 << 4)
#define ARM_GPIO_IRQ_EDGE (1 << 5)
#define ARM_GPIO_IRQ_LEVEL (1 << 6)
#define ARM_GPIO_IRQ_ACTIVE_LOW (1 << 7)
#define ARM_GPIO_IRQ_ACTIVE_HIGH (1 << 8)
/* ARM GPIO enumeration types */
enum arm_gpio_access_t {
ARM_GPIO_ACCESS_PIN = 0, /*!< Pin access to GPIO */
ARM_GPIO_ACCESS_PORT /*!< Port access to GPIO */
};
enum arm_gpio_irq_status_t {
ARM_GPIO_IRQ_DISABLE = 0, /*!< Disable interruptions */
ARM_GPIO_IRQ_ENABLE /*!< Enable interruptions */
};
enum arm_gpio_error_t {
ARM_GPIO_ERR_NONE = 0, /*!< No error */
ARM_GPIO_ERR_INVALID_ARG, /*!< Error invalid input argument */
ARM_GPIO_ERR_PORT_NOT_INIT /*!< Error GPIO port not initialized */
};
/* ARM GPIO device configuration structure */
struct arm_gpio_dev_cfg_t {
const uint32_t base; /*!< GPIO base address */
};
/* ARM GPIO device data structure */
struct arm_gpio_dev_data_t {
uint32_t state; /*!< Indicates if the gpio driver
is initialized and enabled */
uint32_t port_mask; /*!< Port mask used for any port access */
};
/* ARM GPIO device structure */
struct arm_gpio_dev_t {
const struct arm_gpio_dev_cfg_t* const cfg; /*!< GPIO configuration */
struct arm_gpio_dev_data_t* const data; /*!< GPIO data */
};
/* ARM GPIO pin structure */
struct arm_gpio_pin_t {
uint32_t number; /*!< Pin number */
enum arm_gpio_access_t access_type; /*!< Type of access in the
GPIO block */
};
/**
* \brief Initializes GPIO port.
*
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void arm_gpio_init(struct arm_gpio_dev_t* dev);
/**
* \brief Configurates pin or port.
*
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
* \param[in] access Access type \ref arm_gpio_access_t
* \param[in] pin_num Pin number.
* \param[in] flags Pin flags \ref arm_gpio_flags_t
*
* \return Returns error code as specified in \ref arm_gpio_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_gpio_error_t arm_gpio_config(struct arm_gpio_dev_t* dev,
enum arm_gpio_access_t access,
uint8_t pin_num,
uint32_t flags);
/**
* \brief Writes to output pin or port.
*
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
* \param[in] access Access type \ref arm_gpio_access_t
* \param[in] pin_num Pin number.
* \param[in] value Value(s) to set.
*
* \return Returns error code as specified in \ref arm_gpio_error_t
*
* \note This function doesn't check if dev is NULL.
* \note As ARM is a read-modify-write architecture, before writing a
* value on a GPIO pin it is required to disable the
* interrupts to prevent problems in a multitasking
* environment.
*/
enum arm_gpio_error_t arm_gpio_write(struct arm_gpio_dev_t* dev,
enum arm_gpio_access_t access,
uint8_t pin_num,
uint32_t value);
/**
* \brief Reads the pin or port status.
*
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
* \param[in] access Access type \ref arm_gpio_access_t
* \param[in] pin_num Pin number.
* \param[in] value Value of input pin(s).
*
* \return Returns bit value for Pin access or port value for port access.
* Negative value for error.
* \note This function doesn't check if dev is NULL.
*/
int32_t arm_gpio_read(struct arm_gpio_dev_t* dev, enum arm_gpio_access_t access,
uint8_t pin_num);
/**
* \brief Sets interrupt status for the given pin or port.
*
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
* \param[in] access Access type \ref arm_gpio_access_t
* \param[in] pin_num Pin number.
* \param[in] status Interrupt status \ref arm_gpio_irq_status
*
* \return Returns error code as specified in \ref arm_gpio_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_gpio_error_t arm_gpio_set_interrupt(struct arm_gpio_dev_t* dev,
enum arm_gpio_access_t access,
uint8_t pin_num,
enum arm_gpio_irq_status_t status);
/**
* \brief Gets interrupt status for the given pin or port.
*
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
* \param[in] access Access type \ref arm_gpio_access_t
* \param[in] pin_num Pin number.
* \param[out] status Interrupt status values. If the access is by pin, then
* the status will be 0 or 1.
*
* \return Returns error code as specified in \ref arm_gpio_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_gpio_error_t arm_gpio_get_irq_status(struct arm_gpio_dev_t* dev,
enum arm_gpio_access_t access,
uint8_t pin_num,
uint32_t* status);
/**
* \brief Clears gpio interrupt.
*
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
* \param[in] pin_num Pin number.
*
* \return Returns error code as specified in \ref arm_gpio_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_gpio_error_t arm_gpio_clear_interrupt(struct arm_gpio_dev_t* dev,
uint8_t pin_num);
/**
* \brief Sets gpio mask for port access.
*
* \param[in] dev GPIO port \ref arm_gpio_dev_t
* \param[in] port_mask New port mask to set, only the 16 LSb are taken into
* account
*
* \note This function doesn't check if dev is NULL.
*/
void arm_gpio_set_port_mask(struct arm_gpio_dev_t* dev, uint32_t port_mask);
/**
* \brief Gets gpio mask for port access.
*
* \param[in] dev GPIO port \ref arm_gpio_dev_t
*
* \return Returns the current port mask
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t arm_gpio_get_port_mask(struct arm_gpio_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __ARM_GPIO_DRV_H__ */

View File

@@ -0,0 +1,218 @@
/*
* 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.
*/
#include "arm_mps2_io_drv.h"
/* There is at most 8 LEDs and switches on MPS2 SCC and 2 on FPGA IO */
#define MAX_PIN_NBR_SCC 8
#define MAX_PIN_NBR_FPGAIO 2
/* Mask to 1 the first X bits */
#define MASK(X) ((1 << (X)) - 1)
/* MPS2 IO register map structure */
struct arm_mps2_io_reg_map_t {
union {
volatile uint32_t scc_leds; /* Offset: 0x000 (R/W) Controls the MCC
* user LEDs
* [31:8] : Reserved
* [7:0] : MCC LEDs */
volatile uint32_t fpgaio_leds; /* Offset: 0x000 (R/W) LED connections
* [31:2] : Reserved
* [1:0] : FPGAIO LEDs */
} led_reg;
volatile uint32_t reserved[1];
union {
volatile uint32_t scc_switches; /* Offset: 0x008 (R/ ) Denotes the
* state of the MCC
* user switches
* [31:8] : Reserved
* [7:0] : State of the MCC
* switches */
volatile uint32_t fpgaio_buttons;/* Offset: 0x008 (R/ ) Buttons
* [31:2] : Reserved
* [1:0] : Buttons */
} button_reg;
volatile uint32_t reserved1[16];
volatile uint32_t misc; /* Offset: 0x04C (R/W) Misc control
* [31:7] : Reserved
* [6] : CLCD_BL_CTRL
* [5] : CLCD_RD
* [4] : CLCD_RS
* [3] : CLCD_RESET
* [2] : Reserved
* [1] : SPI_nSS
* [0] : CLCD_CS */
};
void arm_mps2_io_write_leds(struct arm_mps2_io_dev_t* dev,
enum arm_mps2_io_access_t access,
uint8_t pin_num,
uint32_t value)
{
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
/* Mask of involved bits */
uint32_t write_mask = 0;
switch (dev->cfg->type) {
case ARM_MPS2_IO_TYPE_SCC:
if (pin_num >= MAX_PIN_NBR_SCC) {
return;
}
switch (access) {
case ARM_MPS2_IO_ACCESS_PIN:
write_mask = (1UL << pin_num);
break;
case ARM_MPS2_IO_ACCESS_PORT:
write_mask = MASK(MAX_PIN_NBR_SCC);
break;
/*
* default: explicitely not used to force to cover all enumeration
* cases
*/
}
if (value) {
p_mps2_io_port->led_reg.scc_leds |= write_mask;
} else {
p_mps2_io_port->led_reg.scc_leds &= ~write_mask;
}
break;
case ARM_MPS2_IO_TYPE_FPGAIO:
if (pin_num >= MAX_PIN_NBR_FPGAIO) {
return;
}
switch (access) {
case ARM_MPS2_IO_ACCESS_PIN:
write_mask = (1UL << pin_num);
break;
case ARM_MPS2_IO_ACCESS_PORT:
write_mask = MASK(MAX_PIN_NBR_FPGAIO);
break;
/*
* default: explicitely not used to force to cover all enumeration
* cases
*/
}
if (value) {
p_mps2_io_port->led_reg.fpgaio_leds |= write_mask;
} else {
p_mps2_io_port->led_reg.fpgaio_leds &= ~write_mask;
}
break;
/* default: explicitely not used to force to cover all enumeration cases */
}
}
void arm_mps2_io_write_misc(struct arm_mps2_io_dev_t* dev,
enum arm_mps2_io_access_t access,
uint8_t pin_num,
uint32_t value)
{
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
/* The MISC write is for FPGAIO only */
if (dev->cfg->type != ARM_MPS2_IO_TYPE_FPGAIO)
return;
if (value) {
p_mps2_io_port->misc |= (1UL << pin_num);
} else {
p_mps2_io_port->misc &= ~(1UL << pin_num);
}
}
uint32_t arm_mps2_io_read_buttons(struct arm_mps2_io_dev_t* dev,
enum arm_mps2_io_access_t access,
uint8_t pin_num)
{
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
uint32_t value = 0;
switch (dev->cfg->type) {
case ARM_MPS2_IO_TYPE_SCC:
if (pin_num >= MAX_PIN_NBR_SCC) {
return 0;
}
/* Only read significant bits from this register */
value = p_mps2_io_port->button_reg.scc_switches & MASK(MAX_PIN_NBR_SCC);
break;
case ARM_MPS2_IO_TYPE_FPGAIO:
if (pin_num >= MAX_PIN_NBR_FPGAIO) {
return 0;
}
/* Only read significant bits from this register */
value = p_mps2_io_port->button_reg.fpgaio_buttons &
MASK(MAX_PIN_NBR_FPGAIO);
break;
/* default: explicitely not used to force to cover all enumeration cases */
}
if (access == ARM_MPS2_IO_ACCESS_PIN) {
value = ((value >> pin_num) & 1UL);
}
return value;
}
uint32_t arm_mps2_io_read_leds(struct arm_mps2_io_dev_t* dev,
enum arm_mps2_io_access_t access,
uint8_t pin_num)
{
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
uint32_t value = 0;
switch (dev->cfg->type) {
case ARM_MPS2_IO_TYPE_SCC:
if (pin_num >= MAX_PIN_NBR_SCC) {
return 0;
}
/* Only read significant bits from this register */
value = p_mps2_io_port->led_reg.scc_leds & MASK(MAX_PIN_NBR_SCC);
break;
case ARM_MPS2_IO_TYPE_FPGAIO:
if (pin_num >= MAX_PIN_NBR_FPGAIO) {
return 0;
}
/* Only read significant bits from this register */
value = p_mps2_io_port->led_reg.fpgaio_leds & MASK(MAX_PIN_NBR_FPGAIO);
break;
/* default: explicitely not used to force to cover all enumeration cases */
}
if (access == ARM_MPS2_IO_ACCESS_PIN) {
value = ((value >> pin_num) & 1UL);
}
return value;
}

View File

@@ -0,0 +1,117 @@
/*
* 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 arm_mps2_io_drv.h
* \brief Generic driver for ARM MPS2 IO.
*/
#ifndef __ARM_MPS2_IO_DRV_H__
#define __ARM_MPS2_IO_DRV_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ARM MPS2 IO enumeration types */
enum arm_mps2_io_access_t {
ARM_MPS2_IO_ACCESS_PIN = 0, /*!< Pin access to MPS2 IO */
ARM_MPS2_IO_ACCESS_PORT /*!< Port access to MPS2 IO */
};
enum arm_mps2_io_type_t {
ARM_MPS2_IO_TYPE_SCC = 0, /*!< Use the SCC IO device */
ARM_MPS2_IO_TYPE_FPGAIO /*!< Use the FPGA IO device */
};
/* ARM MPS2 IO device configuration structure */
struct arm_mps2_io_dev_cfg_t {
const uint32_t base; /*!< MPS2 IO base address */
const enum arm_mps2_io_type_t type; /*!< SCC or FPGAIO */
};
/* ARM MPS2 IO device structure */
struct arm_mps2_io_dev_t {
const struct arm_mps2_io_dev_cfg_t* const cfg; /*!< MPS2 IO configuration */
};
/**
* \brief Writes to output LEDs.
*
* \param[in] dev MPS2 IO device where to write \ref arm_mps2_io_dev_t
* \param[in] access Access type \ref arm_mps2_io_access_t
* \param[in] pin_num Pin number.
* \param[in] value Value(s) to set.
*
* \note This function doesn't check if dev is NULL.
*/
void arm_mps2_io_write_leds(struct arm_mps2_io_dev_t* dev,
enum arm_mps2_io_access_t access,
uint8_t pin_num,
uint32_t value);
/**
* \brief Writes corresponding pin in FPGA IO MISC register.
*
* \param[in] dev MPS2 IO device where to write \ref arm_mps2_io_dev_t
* \param[in] pin_num Pin number.
* \param[in] value Value to set.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't support port access.
*/
void arm_mps2_io_write_misc(struct arm_mps2_io_dev_t* dev,
enum arm_mps2_io_access_t access,
uint8_t pin_num,
uint32_t value);
/**
* \brief Reads the buttons status.
*
* \param[in] dev MPS2 IO device where to read \ref arm_mps2_io_dev_t
* \param[in] access Access type \ref arm_mps2_io_access_t
* \param[in] pin_num Pin number.
*
* \return Returns bit value for Pin access or port value for port access.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t arm_mps2_io_read_buttons(struct arm_mps2_io_dev_t* dev,
enum arm_mps2_io_access_t access,
uint8_t pin_num);
/**
* \brief Reads the LED status.
*
* \param[in] dev MPS2 IO device where to read \ref arm_mps2_io_dev_t
* \param[in] access Access type \ref arm_mps2_io_access_t
* \param[in] pin_num Pin number.
*
* \return Returns bit value for Pin access or port value for port access.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t arm_mps2_io_read_leds(struct arm_mps2_io_dev_t* dev,
enum arm_mps2_io_access_t access,
uint8_t pin_num);
#ifdef __cplusplus
}
#endif
#endif /* __ARM_MPS2_IO_DRV_H__ */

View File

@@ -0,0 +1,286 @@
/*
* 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.
*/
#include "arm_uart_drv.h"
#include <stddef.h>
/* UART register map structure */
struct _arm_uart_reg_map_t {
volatile uint32_t data; /* Offset: 0x000 (R/W) data register */
volatile uint32_t state; /* Offset: 0x004 (R/W) status register */
volatile uint32_t ctrl; /* Offset: 0x008 (R/W) control register */
union {
volatile uint32_t intrstatus; /* Offset: 0x00c (R/ ) interrupt status
* register */
volatile uint32_t intrclear; /* Offset: 0x00c ( /W) interrupt clear
* register */
}intr_reg;
volatile uint32_t bauddiv; /* Offset: 0x010 (R/W) Baudrate divider
* register */
};
/* CTRL Register */
#define ARM_UART_TX_EN (1ul << 0)
#define ARM_UART_RX_EN (1ul << 1)
#define ARM_UART_TX_INTR_EN (1ul << 2)
#define ARM_UART_RX_INTR_EN (1ul << 3)
/* STATE Register */
#define ARM_UART_TX_BF (1ul << 0)
#define ARM_UART_RX_BF (1ul << 1)
/* INTSTATUS Register */
#define ARM_UART_TX_INTR (1ul << 0)
#define ARM_UART_RX_INTR (1ul << 1)
/* UART state definitions */
#define ARM_UART_INITIALIZED (1ul << 0)
enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
uint32_t system_clk)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(system_clk == 0) {
return ARM_UART_ERR_INVALID_ARG;
}
/* Sets baudrate and system clock */
dev->data->system_clk = system_clk;
dev->data->baudrate = dev->cfg->default_baudrate;
/* Sets baudrate */
p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate);
/* Enables receiver and transmitter */
p_uart->ctrl = ARM_UART_RX_EN | ARM_UART_TX_EN;
dev->data->state = ARM_UART_INITIALIZED;
return ARM_UART_ERR_NONE;
}
enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
uint32_t baudrate)
{
uint32_t bauddiv;
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(baudrate == 0) {
return ARM_UART_ERR_INVALID_BAUD;
}
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
return ARM_UART_ERR_NOT_INIT;
}
/* Sets baudrate */
bauddiv = (dev->data->system_clk / baudrate);
dev->data->baudrate = baudrate;
/* Minimum bauddiv value */
if(bauddiv < 16) {
return ARM_UART_ERR_INVALID_BAUD;
}
p_uart->bauddiv = bauddiv;
return ARM_UART_ERR_NONE;
}
uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev)
{
return dev->data->baudrate;
}
enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
uint32_t system_clk)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(system_clk == 0) {
return ARM_UART_ERR_INVALID_ARG;
}
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
return ARM_UART_ERR_NOT_INIT;
}
/* Sets system clock */
dev->data->system_clk = system_clk;
/* Updates baudrate divider */
p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate);
/* Enables receiver and transmitter */
return ARM_UART_ERR_NONE;
}
enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(!(p_uart->state & ARM_UART_RX_BF)) {
return ARM_UART_ERR_NOT_READY;
}
/* Reads data */
*byte = (uint8_t)p_uart->data;
return ARM_UART_ERR_NONE;
}
enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(p_uart->state & ARM_UART_TX_BF) {
return ARM_UART_ERR_NOT_READY;
}
/* Sends data */
p_uart->data = byte;
return ARM_UART_ERR_NONE;
}
enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
return ARM_UART_ERR_NOT_INIT;
}
p_uart->ctrl |= ARM_UART_TX_INTR_EN;
return ARM_UART_ERR_NONE;
}
void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(dev->data->state & ARM_UART_INITIALIZED ) {
p_uart->ctrl &= ~ARM_UART_TX_INTR_EN;
}
}
uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
return 0;
}
return !(p_uart->state & ARM_UART_TX_BF);
}
enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
return ARM_UART_ERR_NOT_INIT;
}
p_uart->ctrl |= ARM_UART_RX_INTR_EN;
return ARM_UART_ERR_NONE;
}
void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(dev->data->state & ARM_UART_INITIALIZED) {
p_uart->ctrl &= ~ARM_UART_RX_INTR_EN;
}
}
uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
return 0;
}
return (p_uart->state & ARM_UART_RX_BF);
}
void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
enum arm_uart_irq_t irq)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
if(dev->data->state & ARM_UART_INITIALIZED) {
/* Clears pending interrupts */
switch(irq) {
case ARM_UART_IRQ_RX:
p_uart->intr_reg.intrclear = ARM_UART_RX_INTR;
break;
case ARM_UART_IRQ_TX:
p_uart->intr_reg.intrclear = ARM_UART_TX_INTR;
break;
case ARM_UART_IRQ_COMBINED:
p_uart->intr_reg.intrclear = (ARM_UART_RX_INTR | ARM_UART_TX_INTR);
break;
case ARM_UART_IRQ_NONE:
break;
/* default: not defined to force all cases to be handled */
}
}
}
enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev)
{
struct _arm_uart_reg_map_t* p_uart =
(struct _arm_uart_reg_map_t*)dev->cfg->base;
enum arm_uart_irq_t intrstatus = ARM_UART_IRQ_NONE;
if(dev->data->state & ARM_UART_INITIALIZED) {
switch(p_uart->intr_reg.intrstatus) {
case ARM_UART_TX_INTR:
intrstatus = ARM_UART_IRQ_TX;
break;
case ARM_UART_RX_INTR:
intrstatus = ARM_UART_IRQ_RX;
break;
case ARM_UART_TX_INTR | ARM_UART_RX_INTR:
intrstatus = ARM_UART_IRQ_COMBINED;
break;
default:
break;
}
}
return intrstatus;
}

View File

@@ -0,0 +1,230 @@
/*
* 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.
*/
/**
* \file arm_uart_drv.h
* \brief Generic driver for ARM UART.
*/
#ifndef __ARM_UART_DRV_H__
#define __ARM_UART_DRV_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ARM UART device configuration structure */
struct arm_uart_dev_cfg_t {
const uint32_t base; /*!< UART base address */
const uint32_t default_baudrate; /*!< Default baudrate */
};
/* ARM UART device data structure */
struct arm_uart_dev_data_t {
uint32_t state; /*!< Indicates if the uart driver
is initialized and enabled */
uint32_t system_clk; /*!< System clock */
uint32_t baudrate; /*!< Baudrate */
};
/* ARM UART device structure */
struct arm_uart_dev_t {
const struct arm_uart_dev_cfg_t* const cfg; /*!< UART configuration */
struct arm_uart_dev_data_t* const data; /*!< UART data */
};
/* ARM UART enumeration types */
enum arm_uart_error_t {
ARM_UART_ERR_NONE = 0, /*!< No error */
ARM_UART_ERR_INVALID_ARG, /*!< Error invalid input argument */
ARM_UART_ERR_INVALID_BAUD, /*!< Invalid baudrate */
ARM_UART_ERR_NOT_INIT, /*!< Error UART not initialized */
ARM_UART_ERR_NOT_READY, /*!< Error UART not ready */
};
enum arm_uart_irq_t {
ARM_UART_IRQ_RX, /*!< RX interrupt source */
ARM_UART_IRQ_TX, /*!< TX interrupt source */
ARM_UART_IRQ_COMBINED, /*!< RX-TX combined interrupt source */
ARM_UART_IRQ_NONE = 0xFF /*!< RX-TX combined interrupt source */
};
/**
* \brief Initializes UART. It uses the default baudrate to configure
* the peripheral at this point.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
* \param[in] system_clk System clock used by the device.
*
* \return Returns error code as specified in \ref arm_uart_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
uint32_t system_clk);
/**
* \brief Sets the UART baudrate.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
* \param[in] baudrate New baudrate.
*
* \return Returns error code as specified in \ref arm_uart_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
uint32_t baudrate);
/**
* \brief Gets the UART baudrate.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
*
* \return Returns the UART baudrate.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev);
/**
* \brief Sets system clock.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
* \param[in] system_clk System clock used by the device.
*
* \return Returns error code as specified in \ref arm_uart_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
uint32_t system_clk);
/**
* \brief Reads one byte from UART dev.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
* \param[in] byte Pointer to byte.
*
* \return Returns error code as specified in \ref arm_uart_error_t
*
* \note For better performance, this function doesn't check if dev and byte
* pointer are NULL, and if the driver is initialized.
*/
enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte);
/**
* \brief Writes a byte to UART dev.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
* \param[in] byte Byte to write.
*
* \return Returns error code as specified in \ref arm_uart_error_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte);
/**
* \brief Enables TX interrupt.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
*
* \return Returns error code as specified in \ref arm_uart_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev);
/**
* \brief Disables TX interrupt.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev);
/**
* \brief Verifies if Tx is ready to send more data.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
*
* \return 1 if TX is ready, 0 otherwise.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev);
/**
* \brief Enables RX interrupt.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
*
* \return Returns error code as specified in \ref arm_uart_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev);
/**
* \brief Disables RX interrupt
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev);
/**
* \brief Verifies if Rx has data.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
*
* \return 1 if RX has data, 0 otherwise.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev);
/**
* \brief Clears UART interrupt.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
* \param[in] irq IRQ source to clean \ref arm_uart_irq_t
*
* \note This function doesn't check if dev is NULL.
*/
void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
enum arm_uart_irq_t irq);
/**
* \brief Returns UART interrupt status.
*
* \param[in] dev UART device struct \ref arm_uart_dev_t
*
* \return IRQ status \ref arm_uart_irq_t
*
* \note This function doesn't check if dev is NULL.
*/
enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __ARM_UART_DRV_H__ */

View File

@@ -0,0 +1,590 @@
/*
* 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.
*/
/**
* \file dualtimer_cmsdk_drv.c
* \brief Generic driver for CMSDK Dualtimers.
*/
#include "dualtimer_cmsdk_drv.h"
/** Dualtimer state definition */
#define DUALTIMER_CMSDK_INITIALIZED (1u)
/** Dual timer control register bit indexes */
#define CTRL_REG_ONE_SHOT_INDEX (0u)
#define CTRL_REG_SIZE_INDEX (1u)
#define CTRL_REG_PRESCALE_INDEX (3u)
#define CTRL_REG_IRQ_EN_INDEX (5u)
#define CTRL_REG_MODE_INDEX (6u)
#define CTRL_REG_TIMER_EN_INDEX (7u)
/** Dual timer interrupt registers bit indexes */
#define XRIS_REG_RAW_IRQ_INDEX (0u)
#define XMIS_REG_MASKED_IRQ_INDEX (0u)
#define XINTCLR_REG_CLEAR_IRQ_INDEX (0u)
/** Misc definition */
#define TWO_BITS_WIDTH (2u)
/** Bit handling macros */
#define ATOMIC_SET_BIT(WORD, BIT_INDEX) (WORD = (1u << BIT_INDEX))
#define ATOMIC_CLR_BIT(WORD, BIT_INDEX) (WORD = ~(1u << BIT_INDEX))
#define SET_BIT(WORD, BIT_INDEX) (WORD |= (1u << BIT_INDEX))
#define CLR_BIT(WORD, BIT_INDEX) (WORD &= ~(1u << BIT_INDEX))
#define GET_BIT(WORD, BIT_INDEX) (bool)((WORD & (1u << BIT_INDEX)))
/** Generate a flexible width left shifted bit-mask */
#define BIT_MASK(BIT_INDEX, WIDTH)\
(((1u << (WIDTH)) - 1u) << (BIT_INDEX - WIDTH + 1u))
/** Set N number of bits defined by width at index position in a register */
#define SET_NBITS(WORD, BIT_INDEX, WIDTH, DATA)\
(WORD |= (DATA << (BIT_INDEX - WIDTH + 1u))\
& BIT_MASK(BIT_INDEX, WIDTH))
/** Get N number of bits defined by width at index position in a register */
#define GET_NBITS(WORD, BIT_INDEX, WIDTH)\
((WORD & BIT_MASK(BIT_INDEX, WIDTH))\
>> (BIT_INDEX - WIDTH + 1u))
/** Map the registers for dualtimer device */
#define DUALTIMER_REG_MAP(DEVICE)\
((struct dualtimer_cmsdk_reg_map_t*)((DEVICE)->cfg->base))
/** DualTimer register map structure */
struct dualtimer_cmsdk_reg_map_t {
volatile uint32_t timer1load; /** Offset: 0x000 (R/W) Timer 1 Load */
volatile uint32_t timer1value; /** Offset: 0x004 (R/ ) Timer 1 Counter
* Current Value */
volatile uint32_t timer1ctrl; /** Offset: 0x008 (R/W) Timer 1 Control */
volatile uint32_t timer1intclr; /** Offset: 0x00C ( /W) Timer 1 Interrupt
* Clear */
volatile uint32_t timer1ris; /** Offset: 0x010 (R/ ) Timer 1 Raw
* Interrupt Status */
volatile uint32_t timer1mis; /** Offset: 0x014 (R/ ) Timer 1 Masked
* Interrupt Status */
volatile uint32_t timer1bgload; /** Offset: 0x018 (R/W) Background Load
* Register */
volatile uint32_t reserved0;
volatile uint32_t timer2load; /** Offset: 0x020 (R/W) Timer 2 Load */
volatile uint32_t timer2value; /** Offset: 0x024 (R/ ) Timer 2 Counter
* Current Value */
volatile uint32_t timer2ctrl; /** Offset: 0x028 (R/W) Timer 2 Control */
volatile uint32_t timer2intclr; /** Offset: 0x02C ( /W) Timer 2 Interrupt
* Clear */
volatile uint32_t timer2ris; /** Offset: 0x030 (R/ ) Timer 2 Raw
* Interrupt Status */
volatile uint32_t timer2mis; /** Offset: 0x034 (R/ ) Timer 2 Masked
* Interrupt Status */
volatile uint32_t timer2bgload; /** Offset: 0x038 (R/W) Background Load
* Register */
volatile uint32_t reserved1[945];
volatile uint32_t itcr; /** Offset: 0xF00 (R/W) Integration Test
* Control Register */
volatile uint32_t itop; /** Offset: 0xF04 ( /W) Integration Test
* Output Set
* Register */
};
static void dualtimer_cmsdk_defaults(const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_disable_both_timers(dev);
dualtimer_cmsdk_clear_interrupt_timer1(dev);
dualtimer_cmsdk_clear_interrupt_timer2(dev);
dualtimer_cmsdk_set_oneshot_count_both_timers(dev,
DUALTIMER_CMSDK_WRAPPING);
dualtimer_cmsdk_set_size_both_timers(dev, DUALTIMER_CMSDK_SIZE_16BIT);
dualtimer_cmsdk_set_prescale_both_timers(dev,
DUALTIMER_CMSDK_CLOCK_DIV1);
dualtimer_cmsdk_enable_interrupt_both_timers(dev);
dualtimer_cmsdk_set_mode_both_timers(dev, DUALTIMER_CMSDK_FREE_RUNNING);
dualtimer_cmsdk_set_reload_both_timers(dev,
DUALTIMER_CMSDK_DEF_16BIT_RELOAD);
}
/** Init */
void dualtimer_cmsdk_init(const struct dualtimer_cmsdk_dev_t* dev)
{
if (DUALTIMER_CMSDK_INITIALIZED != dev->data->is_initialized) {
dualtimer_cmsdk_defaults(dev);
dev->data->is_initialized = 1;
}
}
bool dualtimer_cmsdk_is_initialized(const struct dualtimer_cmsdk_dev_t* dev)
{
return(bool)dev->data->is_initialized;
}
void dualtimer_cmsdk_free(const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_disable_both_timers(dev);
dev->data->is_initialized = 0;
}
/** Enable - Disable */
void dualtimer_cmsdk_enable_timer1(const struct dualtimer_cmsdk_dev_t* dev)
{
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_TIMER_EN_INDEX);
}
void dualtimer_cmsdk_enable_timer2(const struct dualtimer_cmsdk_dev_t* dev)
{
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_TIMER_EN_INDEX);
}
void dualtimer_cmsdk_enable_both_timers(const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_enable_timer1(dev);
dualtimer_cmsdk_enable_timer2(dev);
}
void dualtimer_cmsdk_disable_timer1(const struct dualtimer_cmsdk_dev_t* dev)
{
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_TIMER_EN_INDEX);
}
void dualtimer_cmsdk_disable_timer2(const struct dualtimer_cmsdk_dev_t* dev)
{
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_TIMER_EN_INDEX);
}
void dualtimer_cmsdk_disable_both_timers(
const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_disable_timer1(dev);
dualtimer_cmsdk_disable_timer2(dev);
}
/** Interrupts */
void dualtimer_cmsdk_enable_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_IRQ_EN_INDEX);
}
void dualtimer_cmsdk_enable_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_IRQ_EN_INDEX);
}
void dualtimer_cmsdk_enable_interrupt_both_timers(
const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_enable_interrupt_timer1(dev);
dualtimer_cmsdk_enable_interrupt_timer2(dev);
}
void dualtimer_cmsdk_disable_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_IRQ_EN_INDEX);
}
void dualtimer_cmsdk_disable_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_IRQ_EN_INDEX);
}
void dualtimer_cmsdk_disable_interrupt_both_timers(
const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_disable_interrupt_timer1(dev);
dualtimer_cmsdk_disable_interrupt_timer2(dev);
}
void dualtimer_cmsdk_clear_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
ATOMIC_SET_BIT(DUALTIMER_REG_MAP(dev)->timer1intclr,
XINTCLR_REG_CLEAR_IRQ_INDEX);
}
void dualtimer_cmsdk_clear_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
ATOMIC_SET_BIT(DUALTIMER_REG_MAP(dev)->timer2intclr,
XINTCLR_REG_CLEAR_IRQ_INDEX);
}
/** One Shot */
void dualtimer_cmsdk_set_oneshot_count_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode)
{
if (DUALTIMER_CMSDK_ONE_SHOT == mode) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_ONE_SHOT_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_ONE_SHOT_INDEX);
}
}
void dualtimer_cmsdk_set_oneshot_count_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode)
{
if (DUALTIMER_CMSDK_ONE_SHOT == mode) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_ONE_SHOT_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_ONE_SHOT_INDEX);
}
}
void dualtimer_cmsdk_set_oneshot_count_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode)
{
dualtimer_cmsdk_set_oneshot_count_timer1(dev, mode);
dualtimer_cmsdk_set_oneshot_count_timer2(dev, mode);
}
/** Timer Size */
void dualtimer_cmsdk_set_size_timer1(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size)
{
if (DUALTIMER_CMSDK_SIZE_32BIT == bit_size) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_SIZE_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_SIZE_INDEX);
}
}
void dualtimer_cmsdk_set_size_timer2(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size)
{
if (DUALTIMER_CMSDK_SIZE_32BIT == bit_size) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_SIZE_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_SIZE_INDEX);
}
}
void dualtimer_cmsdk_set_size_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size)
{
dualtimer_cmsdk_set_size_timer1(dev, bit_size);
dualtimer_cmsdk_set_size_timer2(dev, bit_size);
}
enum dualtimer_cmsdk_size_t dualtimer_cmsdk_get_size_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
if(GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_SIZE_INDEX)) {
return DUALTIMER_CMSDK_SIZE_32BIT;
}
return DUALTIMER_CMSDK_SIZE_16BIT;
}
enum dualtimer_cmsdk_size_t dualtimer_cmsdk_get_size_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
if(GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_SIZE_INDEX)) {
return DUALTIMER_CMSDK_SIZE_32BIT;
}
return DUALTIMER_CMSDK_SIZE_16BIT;
}
/** Timer Prescale */
void dualtimer_cmsdk_set_prescale_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale)
{
SET_NBITS(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_PRESCALE_INDEX,
TWO_BITS_WIDTH, prescale);
}
void dualtimer_cmsdk_set_prescale_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale)
{
SET_NBITS(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_PRESCALE_INDEX,
TWO_BITS_WIDTH, prescale);
}
void dualtimer_cmsdk_set_prescale_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale)
{
dualtimer_cmsdk_set_prescale_timer1(dev, prescale);
dualtimer_cmsdk_set_prescale_timer2(dev, prescale);
}
enum dualtimer_cmsdk_prescale_t dualtimer_cmsdk_get_prescale_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (enum dualtimer_cmsdk_prescale_t)\
GET_NBITS(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_PRESCALE_INDEX,
TWO_BITS_WIDTH);
}
enum dualtimer_cmsdk_prescale_t dualtimer_cmsdk_get_prescale_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (enum dualtimer_cmsdk_prescale_t)\
GET_NBITS(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_PRESCALE_INDEX,
TWO_BITS_WIDTH);
}
/** Timer Mode */
void dualtimer_cmsdk_set_mode_timer1(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode)
{
if (DUALTIMER_CMSDK_PERIODIC == mode) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_MODE_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_MODE_INDEX);
}
}
void dualtimer_cmsdk_set_mode_timer2(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode)
{
if (DUALTIMER_CMSDK_PERIODIC == mode) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_MODE_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_MODE_INDEX);
}
}
void dualtimer_cmsdk_set_mode_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode)
{
dualtimer_cmsdk_set_mode_timer1(dev, mode);
dualtimer_cmsdk_set_mode_timer2(dev, mode);
}
enum dualtimer_cmsdk_mode_t dualtimer_cmsdk_get_mode_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (enum dualtimer_cmsdk_mode_t)\
GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_MODE_INDEX);
}
enum dualtimer_cmsdk_mode_t dualtimer_cmsdk_get_mode_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (enum dualtimer_cmsdk_mode_t)\
GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_MODE_INDEX);
}
/** Reload-Background reload */
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
const uint32_t rel_size = dualtimer_cmsdk_get_size_timer1(dev);
if (DUALTIMER_CMSDK_SIZE_16BIT == rel_size && UINT16_MAX <= reload) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
DUALTIMER_REG_MAP(dev)->timer1load = reload;
return DUALTIMER_CMSDK_ERR_NONE;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
const uint32_t rel_size = dualtimer_cmsdk_get_size_timer2(dev);
if (DUALTIMER_CMSDK_SIZE_16BIT == rel_size && UINT16_MAX <= reload) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
DUALTIMER_REG_MAP(dev)->timer2load = reload;
return DUALTIMER_CMSDK_ERR_NONE;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
uint32_t ret = 0;
ret +=(uint32_t)dualtimer_cmsdk_set_reload_timer2(dev, reload);
ret +=(uint32_t)dualtimer_cmsdk_set_reload_timer2(dev, reload);
if (ret) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
return DUALTIMER_CMSDK_ERR_NONE;
}
uint32_t dualtimer_cmsdk_get_reload_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer1load;
}
uint32_t dualtimer_cmsdk_get_reload_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer2load;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
const uint32_t rel_size = dualtimer_cmsdk_get_size_timer1(dev);
if (DUALTIMER_CMSDK_SIZE_16BIT == rel_size && UINT16_MAX <= reload) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
DUALTIMER_REG_MAP(dev)->timer1bgload = reload;
return DUALTIMER_CMSDK_ERR_NONE;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
const uint32_t rel_size = dualtimer_cmsdk_get_size_timer2(dev);
if (DUALTIMER_CMSDK_SIZE_16BIT == rel_size && UINT16_MAX <= reload) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
DUALTIMER_REG_MAP(dev)->timer2bgload = reload;
return DUALTIMER_CMSDK_ERR_NONE;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
uint32_t ret = 0;
ret +=(uint32_t)dualtimer_cmsdk_set_bgreload_timer1(dev, reload);
ret +=(uint32_t)dualtimer_cmsdk_set_bgreload_timer2(dev, reload);
if (ret) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
return DUALTIMER_CMSDK_ERR_NONE;
}
uint32_t dualtimer_cmsdk_get_bgreload_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer1bgload;
}
uint32_t dualtimer_cmsdk_get_bgreload_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer2bgload;
}
/** Current timer value */
uint32_t dualtimer_cmsdk_get_current_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer1value;
}
uint32_t dualtimer_cmsdk_get_current_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer2value;
}
/** Status check methods */
bool dualtimer_cmsdk_is_enabled_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl,
CTRL_REG_TIMER_EN_INDEX);
}
bool dualtimer_cmsdk_is_enabled_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl,
CTRL_REG_TIMER_EN_INDEX);
}
bool dualtimer_cmsdk_is_interrupt_enabled_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl,
CTRL_REG_IRQ_EN_INDEX);
}
bool dualtimer_cmsdk_is_interrupt_enabled_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl,
CTRL_REG_IRQ_EN_INDEX);
}
bool dualtimer_cmsdk_is_interrupt_active_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer1mis,
XMIS_REG_MASKED_IRQ_INDEX);
}
bool dualtimer_cmsdk_is_interrupt_active_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer2mis,
XMIS_REG_MASKED_IRQ_INDEX);
}
bool dualtimer_cmsdk_is_raw_interrupt_active_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ris,
XRIS_REG_RAW_IRQ_INDEX);
}
bool dualtimer_cmsdk_is_raw_interrupt_active_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ris,
XRIS_REG_RAW_IRQ_INDEX);
}
uint32_t dualtimer_cmsdk_get_elapsed_value_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->timer1load - register_map->timer1value;
}
uint32_t dualtimer_cmsdk_get_elapsed_value_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->timer2load - register_map->timer2value;
}
void dualtimer_cmsdk_reset_timer1(const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->timer1value = register_map->timer1load;
}
void dualtimer_cmsdk_reset_timer2(const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->timer2value = register_map->timer2load;
}
void dualtimer_cmsdk_reset_both_timers(const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->timer1value = register_map->timer1load;
register_map->timer2value = register_map->timer2load;
}

View File

@@ -0,0 +1,888 @@
/*
* 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.
*/
/**
* \file dualtimer_cmsdk_drv.h
* \brief Generic driver for ARM CMSDK Dualtimers.
*/
#ifndef __DUALTIMER_CMSDK_DRV_H__
#define __DUALTIMER_CMSDK_DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Dualtimer default reload value */
#define DUALTIMER_CMSDK_DEF_32BIT_RELOAD UINT32_MAX
#define DUALTIMER_CMSDK_DEF_16BIT_RELOAD UINT16_MAX
/* Dualtimer device configuration structure */
struct dualtimer_cmsdk_dev_cfg_t {
const uint32_t base; /*!< Dualtimer base address */
};
/* Dualtimer device data structure */
struct dualtimer_cmsdk_dev_data_t {
uint32_t is_initialized; /*!< Indicates if the timer is initialized */
};
/* Dualtimer device structure */
struct dualtimer_cmsdk_dev_t {
const struct dualtimer_cmsdk_dev_cfg_t* const cfg; /*!< Dualtimer
configuration */
struct dualtimer_cmsdk_dev_data_t* const data; /*!< Dualtimer data */
};
/* Dualtimer enumeration types */
enum dualtimer_cmsdk_error_t {
DUALTIMER_CMSDK_ERR_NONE = 0u, /*!< No error */
DUALTIMER_CMSDK_ERR_NOT_INIT, /*!< Error dualtimer is not initialized */
DUALTIMER_CMSDK_ERR_NOT_ENABLE, /*!< Error timer is not enabled */
DUALTIMER_CMSDK_ERR_OVERFLOW
};
enum dualtimer_cmsdk_size_t {
DUALTIMER_CMSDK_SIZE_16BIT = 0u, /*!< Timer is set as 16 Bit */
DUALTIMER_CMSDK_SIZE_32BIT = 1u /*!< Timer is set as 32 Bit */
};
enum dualtimer_cmsdk_prescale_t {
DUALTIMER_CMSDK_CLOCK_DIV1 = 0u, /*!< Timer pre-scale is clock/1 */
DUALTIMER_CMSDK_CLOCK_DIV16 = 1u, /*!< Timer pre-scale is clock/16 */
DUALTIMER_CMSDK_CLOCK_DIV256 = 2u, /*!< Timer pre-scale is clock/256 */
};
enum dualtimer_cmsdk_oneshot_t {
DUALTIMER_CMSDK_WRAPPING = 0u, /*!< Timer wraps around */
DUALTIMER_CMSDK_ONE_SHOT = 1u /*!< Timer will halt when reaching 0 */
};
enum dualtimer_cmsdk_mode_t {
DUALTIMER_CMSDK_FREE_RUNNING = 0u, /*!< Timer counts from UINT32_MAX */
DUALTIMER_CMSDK_PERIODIC = 1u /*!< Timer counts from load value */
};
/**
* \brief Initializes a dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note Init should be called prior to any other process.
*/
void dualtimer_cmsdk_init(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Frees up a dualtimer hardware, so it could be reinitalized.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note Init should be called prior to any other process.
*/
void dualtimer_cmsdk_free(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables single timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_enable_timer1(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables single timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_enable_timer2(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables both timer 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_enable_both_timers(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_timer2(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables both timers 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_both_timers(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Sets one shot count for timer 1 included in dualtimer hardware.
*
* When timer reaches zero if one-shot is set it will wait there until user
* does one of the following:
* - Write a new value to load register.
* - Clear one shot setting the timers to WRAPPING mode.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] mode enum dualtimer_cmsdk_oneshot_t WRAPPING/ONE_SHOT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_oneshot_count_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode);
/**
* \brief Sets one shot count for timer 2 included in dualtimer hardware.
*
* When timer reaches zero if one-shot is set it will wait there until user
* does one of the following:
* - Write a new value to load register.
* - Clear one shot setting the timers to WRAPPING mode.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] mode enum dualtimer_cmsdk_oneshot_t WRAPING/ONE_SHOT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_oneshot_count_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode);
/**
* \brief Sets one shot count for timers 1&2 included in dualtimer hardware.
*
* When timer reaches zero if one-shot is set it will wait there until user
* does one of the following:
* - Write a new value to load register.
* - Clear one shot setting the timers to WRAPPING mode.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] mode enum dualtimer_cmsdk_oneshot_t WRAPING/ONE_SHOT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_oneshot_count_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode);
/**
* \brief Sets the size of timer 1 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] bit_size enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_size_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size);
/**
* \brief Sets the size of timer 2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] bit_size enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_size_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size);
/**
* \brief Sets the size of timers 1&2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] bit_size enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_size_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size);
/**
* \brief Gets the size of timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_size_t dualtimer_cmsdk_get_size_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the size of timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_size_t dualtimer_cmsdk_get_size_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Sets the clock divider for timer 1 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_prescale_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale);
/**
* \brief Sets the clock divider for timer 2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_prescale_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale);
/**
* \brief Sets the clock divider for timers 1&2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_prescale_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale);
/**
* \brief Gets the current set prescale value for timer 1.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_prescale_t dualtimer_cmsdk_get_prescale_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the current set prescale value for timer 2.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_prescale_t dualtimer_cmsdk_get_prescale_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Sets the run mode for timer1 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_mode_timer1(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode);
/**
* \brief Sets the run mode for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_mode_timer2(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode);
/**
* \brief Sets the run mode for timers 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_mode_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode);
/**
* \brief Gets the run mode for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_mode_t dualtimer_cmsdk_get_mode_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the run mode for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_mode_t dualtimer_cmsdk_get_mode_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables the interrupt for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function only enables the hardware irq, use NVIC for handler setup.
*/
void dualtimer_cmsdk_enable_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables the interrupt for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function only enables the hardware irq, use NVIC for handler setup.
*/
void dualtimer_cmsdk_enable_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables the interrupt for timer 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function only enables the hardware irq, use NVIC for handler setup.
*/
void dualtimer_cmsdk_enable_interrupt_both_timers(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables the interrupt for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables the interrupt for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables the interrupt for timers 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_interrupt_both_timers(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Clears the interrupt for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_clear_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Clears the interrupt for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_clear_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Set the reload value for timer 1 included in dualtimer hardware.
*
* Writing to the reload register while timer is active will reset the
* current value register to the reload value
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Set the reload value for timer 2 included in dualtimer hardware.
*
* Writing to the reload register while timer is active will reset the
* current value register to the reload value
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Set the reload value for timers 1&2 included in dualtimer hardware.
*
* Writing to the reload register while timer is active will reset the
* current value register to the reload value
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Gets the reload value for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Reload value of timer 1
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_reload_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the reload value for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Reload value of timer 2
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_reload_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Set the background-reload value for timer 1 of dualtimer hw.
*
* Unlike normal reload, writing to this register will not affect current
* value of timer, and the change become effective after the timer counts to zero
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Set the background-reload value for timers 2 of dualtimer hw.
*
* Unlike normal reload, writing to this register will not affect current
* value of timer, and the change become effective after the timer counts to zero
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Set the background-reload value for timers 1&2 of dualtimer hw.
*
* Unlike normal reload, writing to this register will not affect current
* value of timer, and the change become effective after the timer counts to zero
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Gets the background-reload value for timer 1 of dualtimer hw.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Reload value of timer 1
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_bgreload_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the background-reload value for timer 2 of dualtimer hw.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Reload value of timer 2
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_bgreload_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the current value for timer 1 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Copy of current value of timer.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_current_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the current value for timer 2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Copy of current value of timer.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_current_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if timer 1 included in dualtimer hardware, is enabled.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 1 is enabled.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_enabled_timer1(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if timer 2 included in dualtimer hardware, is enabled.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 2 is enabled.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_enabled_timer2(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if timer 1 included in dualtimer hardware, has the irq enabled.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 1 irq is enabled.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_interrupt_enabled_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if timer 2 included in dualtimer hardware, has the irq enabled.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 2 irq is enabled.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_interrupt_enabled_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks the masked interrupt status of timer 1 included in dualtimer hw.
*
* This function is checking against the masked interrupt register which is the
* output of timerx enabled AND timerX raw interrupt.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 1's masked irq is active
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_interrupt_active_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks the masked interrupt status of timer 1 included in dualtimer hw.
*
* This function is checking against the masked interrupt register which is the
* output of timerx enabled AND timerX raw interrupt.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 2's masked irq is active
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_interrupt_active_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks the raw interrupt status of timer 1 included in dualtimer hw.
*
* This function is checking for the raw interrupt produced when timer reaches 0
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 1's masked irq is active
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_raw_interrupt_active_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks the raw interrupt status of timer 1 included in dualtimer hw.
*
* This function is checking for the raw interrupt produced when timer reaches 0
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 2's masked irq is active
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_raw_interrupt_active_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if dualtimer hardware has been initialized.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if dualtimer has been initialized.
*
* \note This function doesn't check if dev is NULL.
*/
bool dualtimer_cmsdk_is_initialized(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Reads the number of ticks elapsed in the current cycle of timer 1.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return Get elapsed number of ticks since last reload was set.
* Elapsed = (Reload value - Current value)
*/
uint32_t dualtimer_cmsdk_get_elapsed_value_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Reads the number of ticks elapsed in the current cycle of timer 2.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return Get elapsed number of ticks since last reload was set.
* Elapsed = (Reload value - Current value)
*/
uint32_t dualtimer_cmsdk_get_elapsed_value_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Resets the timer 1 count value to the reload value.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_reset_timer1(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Resets the timer 2 count value to the reload value.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_reset_timer2(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Resets both timers' count values to their reload values.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_reset_both_timers(const struct dualtimer_cmsdk_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __DUALTIMER_CMSDK_DRV_H__ */

View File

@@ -0,0 +1,226 @@
/*
* 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 rtc_pl031_drv.c
* \brief Implementation of the PL031 Real Time Clock (RTC) native driver.
*
* \note PL031 device specific definitions based on
* real_time_clock_pl031_r1p3_technical_reference_manual.pdf
* which is available from http://infocenter.arm.com.
*/
#include <stddef.h>
#include "rtc_pl031_drv.h"
/**
* \brief Structure to access the memory mapped registers of the PL031.
*/
struct rtc_pl031_dev_reg_map_t {
volatile uint32_t rtcdr; /*!< Data Register */
volatile uint32_t rtcmr; /*!< Match Register */
volatile uint32_t rtclr; /*!< Load Register */
volatile uint32_t rtccr; /*!< Control Register */
volatile uint32_t rtcimsc;
/*!< Interrupt Mask Set or Clear Register */
volatile uint32_t rtcris; /*!< Raw Interrupt Status Register */
volatile uint32_t rtcmis; /*!< Masked Interrupt Status Register */
volatile uint32_t rtcicr; /*!< Interrupt Clear Register */
volatile uint32_t reserved[1008]; /*!< Reserved from Offset 0x20-0xFDC */
volatile uint32_t rtcperiphid0; /*!< Peripheral ID0 Register */
volatile uint32_t rtcperiphid1; /*!< Peripheral ID1 Register */
volatile uint32_t rtcperiphid2; /*!< Peripheral ID2 Register */
volatile uint32_t rtcperiphid3; /*!< Peripheral ID3 Register */
volatile uint32_t rtcpcellid0; /*!< Primary Cell ID0 Register */
volatile uint32_t rtcpcellid1; /*!< Primary Cell ID1 Register */
volatile uint32_t rtcpcellid2; /*!< Primary Cell ID2 Register */
volatile uint32_t rtcpcellid3; /*!< Primary Cell ID3 Register */
};
/* RTC Control Register */
#define RTC_PL031_RTCCR_ENABLE_POS 0x0U
#define RTC_PL031_RTCCR_ENABLE_MSK (0x1U << RTC_PL031_RTCCR_ENABLE_POS)
/* RTC Interrupt Mask Set or Clear Register */
#define RTC_PL031_RTCIMSC_SET_CLEAR_POS 0x0U
#define RTC_PL031_RTCIMSC_SET_CLEAR_MSK (0x1U << \
RTC_PL031_RTCIMSC_SET_CLEAR_POS)
/* RTC RAW Interrupt Status Register */
#define RTC_PL031_RTCRIS_STATUS_POS 0x0U
#define RTC_PL031_RTCRIS_STATUS_MSK (0x1U << RTC_PL031_RTCRIS_STATUS_POS)
/* RTC Masked Interrupt Status Register */
#define RTC_PL031_RTCMIS_STATUS_POS 0x0U
#define RTC_PL031_RTCMIS_STATUS_MSK (0x1U << RTC_PL031_RTCMIS_STATUS_POS)
/* RTC Interrupt Clear Register */
#define RTC_PL031_RTCICR_CLEAR_POS 0x0U
#define RTC_PL031_RTCICR_CLEAR_MSK (0x1U << RTC_PL031_RTCICR_CLEAR_POS)
bool rtc_pl031_init(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcmr = 0U;
p_rtc->rtcicr = RTC_PL031_RTCICR_CLEAR_MSK;
return true;
}
bool rtc_pl031_dev_enable(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtccr = RTC_PL031_RTCCR_ENABLE_MSK;
return true;
}
bool rtc_pl031_dev_disable(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtccr = 0U;
return true;
}
bool rtc_pl031_read_current_time(struct rtc_pl031_dev_t* dev, uint32_t *seconds)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL || seconds == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
*seconds = (uint32_t)p_rtc->rtcdr;
return true;
}
bool rtc_pl031_write_current_time(struct rtc_pl031_dev_t* dev, uint32_t seconds)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtclr = (uint32_t)seconds;
return true;
}
bool rtc_pl031_enable_interrupt(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcimsc = 0U;
return true;
}
bool rtc_pl031_disable_interrupt(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcimsc = RTC_PL031_RTCIMSC_SET_CLEAR_MSK;
return true;
}
bool rtc_pl031_is_interrupt_masked(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc =
(struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
if (p_rtc->rtcimsc & RTC_PL031_RTCIMSC_SET_CLEAR_MSK){
return true;
} else {
return false;
}
}
bool rtc_pl031_is_raw_interrupt_pending(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc =
(struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
if (p_rtc->rtcris & RTC_PL031_RTCRIS_STATUS_MSK) {
return true;
} else {
return false;
}
}
bool rtc_pl031_is_masked_interrupt_pending(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc =
(struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
if (p_rtc->rtcmis & RTC_PL031_RTCMIS_STATUS_MSK) {
return true;
} else {
return false;
}
}
bool rtc_pl031_write_match_value(struct rtc_pl031_dev_t* dev, uint32_t seconds)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcmr = (uint32_t)seconds;
return true;
}
bool rtc_pl031_clear_interrupt(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcicr = RTC_PL031_RTCICR_CLEAR_MSK;
return true;
}

View File

@@ -0,0 +1,180 @@
/*
* 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 rtc_pl031_drv.h
* \brief Declarations for the PL031 Real Time Clock (RTC) native driver.
*/
#ifndef __RTC_PL031_DRV_H__
#define __RTC_PL031_DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief RTC PL031 device configuration structure.
*/
struct rtc_pl031_dev_cfg_t {
const uintptr_t base; /*!< RTC PL031 base address */
};
/**
* \brief RTC PL031 device structure.
*/
struct rtc_pl031_dev_t {
const struct rtc_pl031_dev_cfg_t* const cfg;
/*!< RTC driver configuration */
};
/**
* \brief Initializes the RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_init(struct rtc_pl031_dev_t* dev);
/**
* \brief Enables RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_dev_enable(struct rtc_pl031_dev_t* dev);
/**
* \brief Disables RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_dev_disable(struct rtc_pl031_dev_t* dev);
/**
* \brief Reads current time from RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
* \param[out] seconds Current time in seconds.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_read_current_time(struct rtc_pl031_dev_t* dev,
uint32_t *seconds);
/**
* \brief Writes current time to RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
* \param[in] seconds Current time to be set in seconds.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_write_current_time(struct rtc_pl031_dev_t* dev,
uint32_t seconds);
/**
* \brief Clears interrupt mask of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_enable_interrupt(struct rtc_pl031_dev_t* dev);
/**
* \brief Sets interrupt mask of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_disable_interrupt(struct rtc_pl031_dev_t* dev);
/**
* \brief Check if RTC PL031 interrupt is masked.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that RTC PL031 interrupt is masked.
*
* \note This function does not check if dev is NULL.
*/
bool rtc_pl031_is_interrupt_masked(struct rtc_pl031_dev_t* dev);
/**
* \brief Gets raw interrupt pending status of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that RTC PL031 raw interrupt
* status is pending.
*
* \note This function does not check if dev is NULL.
*/
bool rtc_pl031_is_raw_interrupt_pending(struct rtc_pl031_dev_t* dev);
/**
* \brief Gets masked interrupt pending status of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that RTC PL031 masked interrupt
* status is pending.
*
* \note This function does not check if dev is NULL.
*/
bool rtc_pl031_is_masked_interrupt_pending(struct rtc_pl031_dev_t* dev);
/**
* \brief Writes match value to RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
* \param[in] seconds Match value to be set in seconds.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_write_match_value(struct rtc_pl031_dev_t* dev, uint32_t seconds);
/**
* \brief Clear interrupt status bit of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_clear_interrupt(struct rtc_pl031_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __RTC_PL031_DRV_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,544 @@
/*
* Copyright (c) 2016-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.
*/
/**
* \file smsc9220_drv.h
* \brief Generic driver for SMSC9220 Ethernet controller
*/
#ifndef __SMSC9220_ETH_H__
#define __SMSC9220_ETH_H__
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** SMSC9220 device configuration structure */
struct smsc9220_eth_dev_cfg_t {
const uint32_t base; /*!< SMSC9220 base address */
};
/** SMSC9220 device data structure */
struct smsc9220_eth_dev_data_t {
uint32_t state; /*!< Indicates if the SMSC9220 driver
is initialized and enabled */
void (*wait_ms) (uint32_t);/*!< function pointer to system's millisec delay
function, will be used for delays */
uint32_t ongoing_packet_length;/*!< size in bytes of the packet
is being sent */
uint32_t ongoing_packet_length_sent; /*!< size in bytes of the packet
has been sent */
uint32_t current_rx_size_words; /*!< Data length in words,
currently is being read */
};
/** SMSC9220 device structure */
struct smsc9220_eth_dev_t {
const struct smsc9220_eth_dev_cfg_t* const cfg; /*!< configuration */
struct smsc9220_eth_dev_data_t* const data; /*!< data */
};
/**
* \brief Error code definitions
*
*/
enum smsc9220_error_t{
SMSC9220_ERROR_NONE = 0U, /*!< no error */
SMSC9220_ERROR_TIMEOUT = 1U, /*!< timeout */
SMSC9220_ERROR_BUSY = 2U, /*!< no error */
SMSC9220_ERROR_PARAM = 3U, /*!< invalid parameter */
SMSC9220_ERROR_INTERNAL = 4U /*!< internal error */
};
/**
* \brief Interrupt source definitions
*
*/
enum smsc9220_interrupt_source {
SMSC9220_INTERRUPT_GPIO0 = 0U,
SMSC9220_INTERRUPT_GPIO1 = 1U,
SMSC9220_INTERRUPT_GPIO2 = 2U,
SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL = 3U,
SMSC9220_INTERRUPT_RX_STATUS_FIFO_FULL = 4U,
/* 5 Reserved according to Datasheet */
SMSC9220_INTERRUPT_RX_DROPPED_FRAME = 6U,
SMSC9220_INTERRUPT_TX_STATUS_FIFO_LEVEL = 7U,
SMSC9220_INTERRUPT_TX_STATUS_FIFO_FULL = 8U,
SMSC9220_INTERRUPT_TX_DATA_FIFO_AVAILABLE = 9U,
SMSC9220_INTERRUPT_TX_DATA_FIFO_OVERRUN = 10U,
/* 11, 12 Reserved according to Datasheet */
SMSC9220_INTERRUPT_TX_ERROR = 13U,
SMSC9220_INTERRUPT_RX_ERROR = 14U,
SMSC9220_INTERRUPT_RX_WATCHDOG_TIMEOUT = 15U,
SMSC9220_INTERRUPT_TX_STATUS_OVERFLOW = 16U,
SMSC9220_INTERRUPT_TX_POWER_MANAGEMENT = 17U,
SMSC9220_INTERRUPT_PHY = 18U,
SMSC9220_INTERRUPT_GP_TIMER = 19U,
SMSC9220_INTERRUPT_RX_DMA = 20U,
SMSC9220_INTERRUPT_TX_IOC = 21U,
/* 22 Reserved according to Datasheet*/
SMSC9220_INTERRUPT_RX_DROPPED_FRAME_HALF = 23U,
SMSC9220_INTERRUPT_RX_STOPPED = 24U,
SMSC9220_INTERRUPT_TX_STOPPED = 25U,
/* 26 - 30 Reserved according to Datasheet*/
SMSC9220_INTERRUPT_SW = 31U
};
/**
* \brief MAC register offset definitions
*
*/
enum smsc9220_mac_reg_offsets_t{
SMSC9220_MAC_REG_OFFSET_CR = 0x1U,
SMSC9220_MAC_REG_OFFSET_ADDRH = 0x2U,
SMSC9220_MAC_REG_OFFSET_ADDRL = 0x3U,
SMSC9220_MAC_REG_OFFSET_HASHH = 0x4U,
SMSC9220_MAC_REG_OFFSET_HASHL = 0x5U,
SMSC9220_MAC_REG_OFFSET_MII_ACC = 0x6U,
SMSC9220_MAC_REG_OFFSET_MII_DATA = 0x7U,
SMSC9220_MAC_REG_OFFSET_FLOW = 0x8U,
SMSC9220_MAC_REG_OFFSET_VLAN1 = 0x9U,
SMSC9220_MAC_REG_OFFSET_VLAN2 = 0xAU,
SMSC9220_MAC_REG_OFFSET_WUFF = 0xBU,
SMSC9220_MAC_REG_OFFSET_WUCSR = 0xCU,
SMSC9220_MAC_REG_OFFSET_COE_CR = 0xDU
};
/**
* \brief PHY register offset definitions
*
*/
enum phy_reg_offsets_t{
SMSC9220_PHY_REG_OFFSET_BCTRL = 0U,
SMSC9220_PHY_REG_OFFSET_BSTATUS = 1U,
SMSC9220_PHY_REG_OFFSET_ID1 = 2U,
SMSC9220_PHY_REG_OFFSET_ID2 = 3U,
SMSC9220_PHY_REG_OFFSET_ANEG_ADV = 4U,
SMSC9220_PHY_REG_OFFSET_ANEG_LPA = 5U,
SMSC9220_PHY_REG_OFFSET_ANEG_EXP = 6U,
SMSC9220_PHY_REG_OFFSET_MCONTROL = 17U,
SMSC9220_PHY_REG_OFFSET_MSTATUS = 18U,
SMSC9220_PHY_REG_OFFSET_CSINDICATE = 27U,
SMSC9220_PHY_REG_OFFSET_INTSRC = 29U,
SMSC9220_PHY_REG_OFFSET_INTMASK = 30U,
SMSC9220_PHY_REG_OFFSET_CS = 31U
};
/* Bit definitions for PHY Basic Status Register */
#define PHY_REG_BSTATUS_EXTENDED_CAPABILITIES_INDEX 0U
#define PHY_REG_BSTATUS_JABBER_DETECT_INDEX 1U
#define PHY_REG_BSTATUS_LINK_STATUS_INDEX 2U
#define PHY_REG_BSTATUS_AUTO_NEG_ABILITY_INDEX 3U
#define PHY_REG_BSTATUS_REMOTE_FAULT_INDEX 4U
#define PHY_REG_BSTATUS_AUTO_NEG_COMPLETE_INDEX 5U
#define PHY_REG_BSTATUS_10BASE_T_HALF_DUPLEX_INDEX 11U
#define PHY_REG_BSTATUS_10BASE_T_FULL_DUPLEX_INDEX 12U
#define PHY_REG_BSTATUS_100BASE_TX_HALF_DUPLEX_INDEX 13U
#define PHY_REG_BSTATUS_100BASE_TX_FULL_DUPLEX_INDEX 14U
#define PHY_REG_BSTATUS_100BASE_T4_INDEX 15U
/**
* \brief FIFO Level Interrupt bit definitions
*
*/
enum smsc9220_fifo_level_irq_pos_t{
SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS = 0U,
SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS = 16U,
SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS = 24U
};
/**
* \brief FIFO Level Interrupt limits
*
*/
#define SMSC9220_FIFO_LEVEL_IRQ_MASK 0xFFU
#define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN 0U
#define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX SMSC9220_FIFO_LEVEL_IRQ_MASK
/**
* \brief Initializes SMSC9220 Ethernet controller to a known default state:
* - device ID is checked
* - global interrupt is enabled, but all irq sources are disabled
* - all capabilities are advertised
* - 10Mbps able
* - 10Mbps with full duplex
* - 100Mbps Tx able
* - 100Mbps with full duplex
* - Symmetric Pause
* - Asymmetric Pause
* - Establish link enabled
* - Rx enabled
* - Tx enabled
* Init should be called prior to any other process and
* it's the caller's responsibility to follow proper call order.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] wait_ms_function function pointer to a millisec delay function
* for proper timing of some processes
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_init(const struct smsc9220_eth_dev_t* dev,
void(* wait_ms_function)(uint32_t));
/**
* \brief Reads the MAC register.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] regoffset Register offset
* \param[in, out] data Pointer to register will be read
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_mac_regread(
const struct smsc9220_eth_dev_t* dev,
enum smsc9220_mac_reg_offsets_t regoffset,
uint32_t *data);
/**
* \brief Writes the MAC register.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] regoffset Register offset
* \param[in] data Register value to write
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_mac_regwrite(
const struct smsc9220_eth_dev_t* dev,
enum smsc9220_mac_reg_offsets_t regoffset,
uint32_t data);
/**
* \brief Reads the PHY register.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] regoffset Register offset
* \param[out] data Register value is read
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_phy_regread(
const struct smsc9220_eth_dev_t* dev,
enum phy_reg_offsets_t,
uint32_t *data);
/**
* \brief Writes the PHY register.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] regoffset Register offset
* \param[in] data Register value to write
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_phy_regwrite(
const struct smsc9220_eth_dev_t* dev,
enum phy_reg_offsets_t,
uint32_t data);
/**
* \brief Reads the Ethernet Controller's ID.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
* \return ID number
*/
uint32_t smsc9220_read_id(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Initiates a soft reset, returns failure or success.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_soft_reset(
const struct smsc9220_eth_dev_t* dev);
/**
* \brief Sets the Maximum Transmission Unit by Tx fifo size.
* Note: The MTU will be smaller by 512 bytes,
* whis is used by the status.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] val Size of the fifo in kbytes
* \ref HW_CFG_REG_TX_FIFO_SIZE_MIN
* \ref HW_CFG_REG_TX_FIFO_SIZE_MAX
*/
void smsc9220_set_txfifo(const struct smsc9220_eth_dev_t* dev,
uint32_t val);
/**
* \brief Sets the FIFO level interrupt for a given source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] irq_level_pos Bit position of the FIFO to set
* \ref smsc9220_fifo_level_irq_pos_t
* \param[in] level Level of the FIFO, when the FIFO used space is greater
* than this value, corresponding interrupt will be generated.
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_set_fifo_level_irq(
const struct smsc9220_eth_dev_t* dev,
enum smsc9220_fifo_level_irq_pos_t irq_level_pos,
uint32_t level);
/**
* \brief Waits for EEPROM to be ready to use.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_wait_eeprom(
const struct smsc9220_eth_dev_t* dev);
/**
* \brief Initializes irqs by clearing and disabling all interrupt sources
* and enable interrupts. Since all interrupt sources are disabled,
* interrupt won't be triggered, until interrupt sources won't be
* enabled by \ref smsc9220_enable_interrupt
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_init_irqs(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Checks PHY ID registers.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_check_phy(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Resets PHY.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_reset_phy(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Advertises all speeds and pauses capabilities.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_advertise_cap(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Enables transmission.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_enable_xmit(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Disables transmission.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_disable_xmit(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Enables MAC Transmitter.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_enable_mac_xmit(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Disables MAC Transmitter.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_disable_mac_xmit(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Enables receiving.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_enable_mac_recv(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Disables receiving.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_disable_mac_recv(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Enables the given interrupt source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] source Enum of the interrupt source.
*/
void smsc9220_enable_interrupt(const struct smsc9220_eth_dev_t* dev,
enum smsc9220_interrupt_source source);
/**
* \brief Disables the given interrupt source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] source Enum of the interrupt source.
*/
void smsc9220_disable_interrupt(const struct smsc9220_eth_dev_t* dev,
enum smsc9220_interrupt_source source);
/**
* \brief Disables all interrupt sources.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_disable_all_interrupts(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Clears the given interrupt source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] source Enum of the interrupt source.
*/
void smsc9220_clear_interrupt(const struct smsc9220_eth_dev_t* dev,
enum smsc9220_interrupt_source source);
/**
* \brief Clears all interrupt sources.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_clear_all_interrupts(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Gets the status of the given interrupt source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] source Enum of the interrupt source.
*
* \return non-zero if the given interrupt source is triggered, zero otherwise
*/
int smsc9220_get_interrupt(const struct smsc9220_eth_dev_t* dev,
enum smsc9220_interrupt_source source);
/**
* \brief Establishes link
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_establish_link(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Reads the Ethernet Controller's MAC address from its EEPROM.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in,out] mac array will include the read MAC address in
* 6 bytes hexadecimal format.
* It should be allocated by the caller to 6 bytes.
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_read_mac_address(
const struct smsc9220_eth_dev_t* dev, char *mac);
/**
* \brief Check device ID.
*
* \return error code /ref smsc9220_error_t
*/
int smsc9220_check_id(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Gets the data size of the Tx buffer, aka Maximum Trasmission Unit
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
* \return Fifo data size in bytes
*/
uint32_t smsc9220_get_tx_data_fifo_size(const struct
smsc9220_eth_dev_t* dev);
/**
* \brief Sends data from the given buffer as an Ethernet packet.
* The full packet length must be specified at the beginning
* of a new packet transmission.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] total_payload_length Length of the ethernet payload.
* Should be equal to the sum of passed buffers within a packet.
* \param[in] is_new_packet Should be set to true if the input buffer has to
* be sent as the start of a new packet or as a full packet.
* \param[in] data Pointer to the data buffer to be sent.
* \param[in] current_size Size of the data in bytes.
*
* \return error code /ref smsc9220_error_t
*/
enum smsc9220_error_t smsc9220_send_by_chunks(
const struct smsc9220_eth_dev_t* dev,
uint32_t total_payload_length,
bool is_new_packet,
const char *data, uint32_t current_size);
/**
* \brief Reads an incoming Ethernet packet into the given buffer.
* Stops reading at packet border.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in,out] data Pointer to a pre-allocated input buffer.
* Allocating sufficient memory space is the caller's
* responsibility, which is typically done by calling
* \ref smsc9220_peek_next_packet_size.
* \param[in] dlen Length of the allocated data in bytes.
*
* \return Number of bytes read from the Rx FIFO into the given buffer.
*/
uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev,
char *data, uint32_t dlen);
/**
* \brief Get the used space of Rx fifo in bytes.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
* \return Data received and waiting for read in bytes
*/
uint32_t smsc9220_get_rxfifo_data_used_space(const struct
smsc9220_eth_dev_t* dev);
/**
* \brief Gets the size of next unread packet in Rx buffer, using the peak
* register, which is not destructive so can be read asynchronously.
* Warning: In case of heavy receiving loads, this register may not
* be in perfect sync.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
* \return Size of the next packet in bytes, read from the Rx Peek register.
*/
uint32_t smsc9220_peek_next_packet_size(const struct
smsc9220_eth_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __SMSC9220_ETH_H__ */

View File

@@ -0,0 +1,870 @@
/*
* 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.
*/
#include "spi_pl022_drv.h"
/******************************************************************************
* PL022 device specific definitions based on DDI0194H_ssp_pl022_trm.pdf which
* is available from infocenter.arm.com.
*
* This version of driver aims at necessary functionality for MPS2 board only
*****************************************************************************/
/* Structure for the SSP Primary Cell device registers */
struct spi_pl022_dev_reg_map_t {
volatile uint32_t sspcr0; /* Control register 0 */
volatile uint32_t sspcr1; /* Control register 1 */
volatile uint32_t sspdr; /* Data register */
volatile uint32_t sspsr; /* Status register */
volatile uint32_t sspcpsr; /* Clock prescale register */
volatile uint32_t sspimsc; /* Interrupt mask set or clear register */
volatile uint32_t sspris; /* Raw interrupt status register */
volatile uint32_t sspmis; /* Masked interrupt status register */
volatile uint32_t sspicr; /* Interrupt clear register */
volatile uint32_t sspdmacr; /* DMA control register */
volatile uint32_t reserved[1006];/* Reserved from Base+0x28-0xFE0 */
volatile uint32_t sspperiphid0; /* Peripheral id register 0 */
volatile uint32_t sspperiphid1; /* Peripheral id register 1 */
volatile uint32_t sspperiphid2; /* Peripheral id register 2 */
volatile uint32_t sspperiphid3; /* Peripheral id register 3 */
volatile uint32_t ssppcellid0; /* Primary cell id register 0 */
volatile uint32_t ssppcellid1; /* Primary cell id register 1 */
volatile uint32_t ssppcellid2; /* Primary cell id register 2 */
volatile uint32_t ssppcellid3; /* Primary cell id register 3 */
};
/*--- SSP Control Register 0 ---*/
/* Data Size Select {0x3=4 ... 0xF=16} */
#define SPI_PL022_SSPCR0_DSS_POS 0
#define SPI_PL022_SSPCR0_DSS_MSK 0xF
/* Frame format */
#define SPI_PL022_SSPCR0_FRF_POS 4
#define SPI_PL022_SSPCR0_FRF_MSK (0x3ul<<SPI_PL022_SSPCR0_FRF_POS)
#define SPI_PL022_SSPCR0_FRF_MOT_SPI 0x0
#define SPI_PL022_SSPCR0_FRF_TI_SS 0x1
#define SPI_PL022_SSPCR0_FRF_MICROWIRE 0x2
#define SPI_PL022_SSPCR0_FRF_RES 0x3
/* Clock polarity applicable to Motorola SPI format only */
#define SPI_PL022_SSPCR0_SPO_POS 6
#define SPI_PL022_SSPCR0_SPO_MSK (0x1ul<<SPI_PL022_SSPCR0_SPO_POS)
/* Clock phase applicable to Motorola SPI format only */
#define SPI_PL022_SSPCR0_SPH_POS 7
#define SPI_PL022_SSPCR0_SPH_MSK (0x1ul<<SPI_PL022_SSPCR0_SPH_POS)
/* Serial clock rate */
#define SPI_PL022_SSPCR0_SCR_POS 8
#define SPI_PL022_SSPCR0_SCR_MSK (0xFFul<<SPI_PL022_SSPCR0_SCR_POS)
/*--- SSP Control Register 1 ---*/
/* Loopback mode*/
#define SPI_PL022_SSPCR1_LBM_POS 0
#define SPI_PL022_SSPCR1_LBM_MSK (0x1ul<<SPI_PL022_SSPCR1_LBM_POS)
/* Syncrhonous serial port enable*/
#define SPI_PL022_SSPCR1_SSE_POS 1
#define SPI_PL022_SSPCR1_SSE_MSK (0x1ul<<SPI_PL022_SSPCR1_SSE_POS)
/* Master or Slave select */
#define SPI_PL022_SSPCR1_MS_POS 2
#define SPI_PL022_SSPCR1_MS_MSK (0x1ul<<SPI_PL022_SSPCR1_MS_POS)
/* Slave mode output disable */
#define SPI_PL022_SSPCR1_SOD_POS 3
#define SPI_PL022_SSPCR1_SOD_MSK (0x1ul<<SPI_PL022_SSPCR1_SOD_POS)
/*--- Clock PreScale Register ---*/
/* Divisor */
#define SPI_PL022_SSPCPSR_CPSDVSR_POS 0
#define SPI_PL022_SSPCPSR_CPSDVSR_MSK (0xFFul<<SPI_PL022_SSPCPSR_CPSDVSR_POS)
#define SPI_PL022_INVALID_SSPCPSR_VALUE 0
#define SPI_PL022_MIN_SSPCPSR_VALUE 2
#define SPI_PL022_MAX_SSPCPSR_VALUE 254
#define SPI_PL022_MAX_SCR_VALUE 255
/*--- Interrupt Mask Set or Clear Register --- */
/* Receive Overrun Interrupt Mask */
#define SPI_PL022_SSPIMSC_RORIM_POS 0
#define SPI_PL022_SSPIMSC_RORIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RORIM_POS)
/* Receive Timeout Interrupt Mask */
#define SPI_PL022_SSPIMSC_RTIM_POS 1
#define SPI_PL022_SSPIMSC_RTIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RTIM_POS)
/* Receive FIFO Interrupt Mask */
#define SPI_PL022_SSPIMSC_RXIM_POS 2
#define SPI_PL022_SSPIMSC_RXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RXIM_POS)
/* Transmit FIFO Interrupt Mask */
#define SPI_PL022_SSPIMSC_TXIM_POS 3
#define SPI_PL022_SSPIMSC_TXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_TXIM_POS)
/*--- Interrupt Mask Set or Clear Register ---*/
/* Receive Overrun Interrupt Mask */
#define SPI_PL022_SSPIMSC_RORIM_POS 0
#define SPI_PL022_SSPIMSC_RORIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RORIM_POS)
/* Receive Timeout Interrupt Mask */
#define SPI_PL022_SSPIMSC_RTIM_POS 1
#define SPI_PL022_SSPIMSC_RTIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RTIM_POS)
/* Receive FIFO Interrupt Mask */
#define SPI_PL022_SSPIMSC_RXIM_POS 2
#define SPI_PL022_SSPIMSC_RXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RXIM_POS)
/* Transmit FIFO Interrupt Mask */
#define SPI_PL022_SSPIMSC_TXIM_POS 3
#define SPI_PL022_SSPIMSC_TXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_TXIM_POS)
#define SPI_PL022_SSPIMSC_VALID_MSK \
((0x1ul<<(SPI_PL022_SSPIMSC_TXIM_POS+1))-1)
/*--- Raw Interrupt Status Register ---*/
/* SSPRORINTR */
#define SPI_PL022_SSPRIS_RORRIS_POS 0
#define SPI_PL022_SSPRIS_RORRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RORRIS_POS)
/* SSPRTINTR */
#define SPI_PL022_SSPRIS_RTRIS_POS 1
#define SPI_PL022_SSPRIS_RTRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RTRIS_POS)
/* SSPRXINTR */
#define SPI_PL022_SSPRIS_RXRIS_POS 2
#define SPI_PL022_SSPRIS_RXRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RXRIS_POS)
/* SSPTXINTR */
#define SPI_PL022_SSPRIS_TXRIS_POS 3
#define SPI_PL022_SSPRIS_TXRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_TXRIS_POS)
#define SPI_PL022_SSPRIS_VALID_MSK \
((0x1ul<<(SPI_PL022_SSPRIS_TXRIS_POS+1))-1)
/*--- Masked Interrupt Status Register ---*/
/* SSPRORINTR */
#define SPI_PL022_SSPMIS_RORMIS_POS 0
#define SPI_PL022_SSPMIS_RORMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RORMIS_POS)
/* SSPRTINTR */
#define SPI_PL022_SSPMIS_RTMIS_POS 1
#define SPI_PL022_SSPMIS_RTMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RTMIS_POS)
/* SSPRXINTR */
#define SPI_PL022_SSPMIS_RXMIS_POS 2
#define SPI_PL022_SSPMIS_RXMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RXMIS_POS)
/* SSPTXINTR */
#define SPI_PL022_SSPMIS_TXMIS_POS 3
#define SPI_PL022_SSPMIS_TXMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_TXMIS_POS)
#define SPI_PL022_SSPMIS_VALID_MSK \
((0x1ul<<(SPI_PL022_SSPMIS_TXMIS_POS+1))-1)
/*--- Interrupt Clear Register --- */
/* SSPRORINTR Clear */
#define SPI_PL022_SSPICR_RORIC_POS 0
#define SPI_PL022_SSPICR_RORIC_MSK (0x1ul<<SPI_PL022_SSPICR_RORIC_POS)
/* SSPRTINTR Clear */
#define SPI_PL022_SSPICR_RTIC_POS 1
#define SPI_PL022_SSPICR_RTIC_MSK (0x1ul<<SPI_PL022_SSPICR_RTIC_POS)
#define SPI_PL022_SSPICR_VALID_MSK ((0x1ul<<(SPI_PL022_SSPICR_RTIC_POS+1))-1)
/*--- DMA Control Register --- */
/* Receive DMA Enable */
#define SPI_PL022_SSPDMACR_RXDMAE_POS 0
#define SPI_PL022_SSPDMACR_RXDMAE_MSK (0x1ul<<SPI_PL022_SSPDMACR_RXDMAE_POS)
/* Transmit DMA Enable */
#define SPI_PL022_SSPDMACR_TXDMAE_POS 1
#define SPI_PL022_SSPDMACR_TXDMAE_MSK (0x1ul<<SPI_PL022_SSPDMACR_TXDMAE_POS)
#define SPI_PL022_SSPDMACR_VALID_MSK ((0x1ul<<(SPI_PL022_SSPDMACR_TXDMAE_POS+1))-1)
/*--- Peripheral Identification Registers ---*/
#define SPI_PL022_SSPPERIPH_ID_OFFSET (0xFE0ul)
/* Part Number 0 */
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_POS 0
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_SIZE 8
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_MSK \
(0xFFul<<SPI_PL022_SSPPERIPH_ID0_PARTNO_0_POS)
/* Part Number 1 */
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_POS 0
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_SIZE 0
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_MSK \
(0xFul<<SPI_PL022_SSPPERIPH_ID1_PARTNO_1_POS)
/* Designer 0 */
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS 4
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_SIZE 4
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_MSK \
(0xFul<<SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS)
/* Designer 1 */
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_POS 0
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_SIZE 4
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_MSK \
(0xFul<<SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_POS)
/* Revision */
#define SPI_PL022_SSPPERIPH_ID2_REVISION_POS 4
#define SPI_PL022_SSPPERIPH_ID2_REVISION_SIZE 4
#define SPI_PL022_SSPPERIPH_ID2_REVIISON_MSK \
(0xFul<<SPI_PL022_SSPPERIPH_ID2_REVISION_POS)
/* Config */
#define SPI_PL022_SSPPERIPH_ID3_CONFIG_POS 0
#define SPI_PL022_SSPPERIPH_ID3_CONFIG_MSK \
(0xFFul<<SPI_PL022_SSPPERIPH_ID3_CONFIG_POS)
/*--- PrimeCell Identification Registers ---*/
#define SPI_PL022_SSPPCELL_ID_OFFSET (0xFF0ul)
#define SPI_PL022_SSPPCELL_ID0_POS 0
#define SPI_PL022_SSPPCELL_ID0_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID0_POS)
#define SPI_PL022_SSPPCELL_ID1_POS 0
#define SPI_PL022_SSPPCELL_ID1_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID1_POS)
#define SPI_PL022_SSPPCELL_ID2_POS 0
#define SPI_PL022_SSPPCELL_ID2_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID2_POS)
#define SPI_PL022_SSPPCELL_ID3_POS 0
#define SPI_PL022_SSPPCELL_ID3_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID3_POS)
/* ARM SPI PL022 state definitions */
#define SPI_PL022_INITIALIZED (1 << 0)
#define WORD_1BYTE_MASK (0xFFul)
#define WORD_2BYTES_MASK (0xFFFFul)
/************************* PL022 TEST Definitions ******************************/
#define SPI_PL022_TEST_REG_BASE (0x80ul)
struct spi_pl022_dev_test_reg_map_t {
volatile uint32_t ssptcr; /* Test Control register */
volatile uint32_t sspitip; /* Integration test input register */
volatile uint32_t sspitop; /* Integration test output register */
volatile uint32_t ssptdr; /* Test data register */
};
/* Test control register */
#define SPI_PL022_SSPTCR_ITEN_POS 0
#define SPI_PL022_SSPTCR_ITEN_MSK (0x1ul<<SPI_PL022_SSPTCR_ITEN_POS)
#define SPI_PL022_SSPTCR_TESTFIFO_POS 1
#define SPI_PL022_SSPTCR_TESTFIFO_MSK (0x1ul<<SPI_PL022_SSPTCR_TESTFIFO_POS)
/* Integration test input register */
#define SPI_PL022_SSPITIP_RXD_POS 0
#define SPI_PL022_SSPITIP_RXD_MSK (0x1ul<<SPI_PL022_SSPITIP_RXD_POS)
#define SPI_PL022_SSPITIP_FSSIN_POS 1
#define SPI_PL022_SSPITIP_FSSIN_MSK (0x1ul<<SPI_PL022_SSPITIP_FSSIN_POS)
#define SPI_PL022_SSPITIP_CLKIN_POS 2
#define SPI_PL022_SSPITIP_CLKIN_MSK (0x1ul<<SPI_PL022_SSPITIP_CLKIN_POS)
#define SPI_PL022_SSPITIP_RXDMACLR_POS 3
#define SPI_PL022_SSPITIP_RXDMACLR_MSK (0x1ul<<SPI_PL022_SSPITIP_RXDMACLR_POS)
#define SPI_PL022_SSPITIP_TXDMACLR_POS 4
#define SPI_PL022_SSPITIP_TXDMACLR_MSK (0x1ul<<SPI_PL022_SSPITIP_TXDMACLR_POS)
/* Integration test output register */
#define SPI_PL022_SSPITOP_RXDMABREQ_POS 10
#define SPI_PL022_SSPITOP_RXDMABREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_RXDMABREQ_POS)
#define SPI_PL022_SSPITOP_RXDMASREQ_POS 11
#define SPI_PL022_SSPITOP_RXDMASREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_RXDMASREQ_POS)
#define SPI_PL022_SSPITOP_TXDMABREQ_POS 12
#define SPI_PL022_SSPITOP_TXDMABREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_TXDMABREQ_POS)
#define SPI_PL022_SSPITOP_TXDMASREQ_POS 13
#define SPI_PL022_SSPITOP_TXDMASREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_TXDMASREQ_POS)
/************************* PL022 Definitions End ******************************/
/*
* \brief Calculates clock prescale divisor and sets serial clock rate
* for the SPI PL022 device.
*
* \param[in] ctrl_cfg SPI control configuration \ref spi_pl022_ctrl_cfg_t
* \param[in] sys_clk System clock.
* \param[in/out] cr0 Pointer to PL022 control register 0
* \ref spi_pl022_dev_reg_map_t
*
* \return Value of the SSPCPSR register \ref spi_pl022_dev_reg_map_t
*
* \note This function doesn't check if sys_clk or ctrl_cfg->bit_rate is 0
*/
static uint32_t spi_calc_clock_rate(
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg,
uint32_t sys_clk, volatile uint32_t *cr0)
{
uint32_t clkps_dvsr; /* clock prescale divisor */
uint32_t scr; /* serial clock rate */
for(clkps_dvsr = SPI_PL022_MIN_SSPCPSR_VALUE;
clkps_dvsr <= SPI_PL022_MAX_SSPCPSR_VALUE; clkps_dvsr += 2) {
/* Calculate clock rate based on the new clock prescale divisor */
scr = (sys_clk / (clkps_dvsr * ctrl_cfg->bit_rate)) - 1;
/* Checks if it can be supported by the divider */
if (scr <= SPI_PL022_MAX_SCR_VALUE) {
*cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK;
*cr0 |= (scr << SPI_PL022_SSPCR0_SCR_POS);
return clkps_dvsr;
}
}
/* no good value was found */
*cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK;
return SPI_PL022_INVALID_SSPCPSR_VALUE;
}
void spi_pl022_dev_enable(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK;
}
void spi_pl022_dev_disable(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK;
}
uint32_t spi_pl022_get_status(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
return p_spi->sspsr;
}
/*
* \brief Configures the SPI PL022 device.
*
* \param[in] spi_dev Pointer to SPI memory map \ref spi_pl022_dev_reg_map_t
* \param[in] ctrl_cfg SPI control configuration \ref spi_pl022_ctrl_cfg_t
* \param[in] sys_clk System clock.
*
* \return Error code from \ref spi_pl022_error_t
*/
static enum spi_pl022_error_t spi_set_configuration(
struct spi_pl022_dev_reg_map_t* spi_dev,
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg,
uint32_t sys_clk)
{
uint32_t tmp_cr0, tmp_cr1;
uint32_t clk_dvsr;
if(!sys_clk || !ctrl_cfg->bit_rate) {
return SPI_PL022_ERR_INVALID_ARGS;
}
/* Word size */
tmp_cr0 = ((ctrl_cfg->word_size -1) << SPI_PL022_SSPCR0_DSS_POS)
& SPI_PL022_SSPCR0_DSS_MSK;
/* Frame format is stored in the least 2 bits*/
switch(ctrl_cfg->frame_format & 0x3ul)
{
case SPI_PL022_CFG_FRF_MOT:
tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MOT_SPI << SPI_PL022_SSPCR0_FRF_POS)
& SPI_PL022_SSPCR0_FRF_MSK;
/* Add motorola phase & polarity */
tmp_cr0 |= (SPI_PL022_SSPCR0_SPO_MSK & SPI_PL022_SSPCR0_SPH_MSK);
break;
case SPI_PL022_CFG_FRF_TI:
tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_TI_SS << SPI_PL022_SSPCR0_FRF_POS)
& SPI_PL022_SSPCR0_FRF_MSK;
break;
case SPI_PL022_CFG_FRF_MICROWIRE:
tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MICROWIRE << SPI_PL022_SSPCR0_FRF_POS)
& SPI_PL022_SSPCR0_FRF_MSK;
break;
default:
return SPI_PL022_ERR_BAD_CONFIG;
/* break; */
}
/* Clock logic */
clk_dvsr = spi_calc_clock_rate(ctrl_cfg, sys_clk, &tmp_cr0);
if (SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) {
return SPI_PL022_ERR_BAD_CONFIG;
}
/* Enable device and set configured mode */
tmp_cr1 = (0x1 << SPI_PL022_SSPCR1_SSE_POS) & SPI_PL022_SSPCR1_SSE_MSK;
tmp_cr1 |= ((ctrl_cfg->spi_mode << SPI_PL022_SSPCR1_MS_POS)
& SPI_PL022_SSPCR1_MS_MSK);
/* Start initialization by disabling the device */
spi_dev->sspcr1 = 0;
/* Set the value received for the configuration */
spi_dev->sspcpsr = clk_dvsr;
spi_dev->sspcr0 = tmp_cr0;
/* Default setup hard coded */
spi_dev->sspimsc = 0;
spi_dev->sspdmacr = 0;
spi_dev->sspicr = (SPI_PL022_SSPICR_RORIC_MSK | SPI_PL022_SSPICR_RTIC_MSK);
spi_dev->sspcr1 = tmp_cr1;
return SPI_PL022_ERR_NONE;
}
enum spi_pl022_error_t spi_pl022_init(struct spi_pl022_dev_t* dev,
uint32_t sys_clk)
{
enum spi_pl022_error_t ret;
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
ret = spi_set_configuration(p_spi, &dev->cfg->default_ctrl_cfg, sys_clk);
if(ret != SPI_PL022_ERR_NONE) {
return ret;
}
dev->data->sys_clk = sys_clk;
/* Initilizes current SPI control configuration */
memcpy(&dev->data->ctrl_cfg, &dev->cfg->default_ctrl_cfg,
sizeof(struct spi_pl022_ctrl_cfg_t));
dev->data->state = SPI_PL022_INITIALIZED;
return ret;
}
enum spi_pl022_error_t spi_pl022_set_ctrl_cfg(struct spi_pl022_dev_t* dev,
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg)
{
enum spi_pl022_error_t ret;
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
if(!(dev->data->state & SPI_PL022_INITIALIZED)) {
return SPI_PL022_ERR_NOT_INIT;
}
if(ctrl_cfg == NULL) {
return SPI_PL022_ERR_INVALID_ARGS;
}
ret = spi_set_configuration(p_spi, ctrl_cfg, dev->data->sys_clk);
if(ret != SPI_PL022_ERR_NONE) {
return ret;
}
/* Updates current SPI control configuration */
memcpy(&dev->data->ctrl_cfg, ctrl_cfg,
sizeof(struct spi_pl022_ctrl_cfg_t));
return SPI_PL022_ERR_NONE;
}
enum spi_pl022_error_t spi_pl022_get_ctrl_cfg(struct spi_pl022_dev_t* dev,
struct spi_pl022_ctrl_cfg_t* ctrl_cfg)
{
if(!(dev->data->state & SPI_PL022_INITIALIZED)) {
return SPI_PL022_ERR_NOT_INIT;
}
if(ctrl_cfg == NULL) {
return SPI_PL022_ERR_INVALID_ARGS;
}
/* Copy current SPI control configuration */
memcpy(ctrl_cfg, &dev->data->ctrl_cfg,
sizeof(struct spi_pl022_ctrl_cfg_t));
return SPI_PL022_ERR_NONE;
}
void spi_pl022_select_mode(struct spi_pl022_dev_t* dev,
enum spi_pl022_mode_select_t mode)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
/* Disable device */
p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK;
/* Set mode */
p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_MS_MSK)
| (mode << SPI_PL022_SSPCR1_MS_POS);
dev->data->ctrl_cfg.spi_mode = mode;
/* Re-enable device */
p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK;
}
void spi_pl022_set_slave_output(struct spi_pl022_dev_t* dev,
enum spi_pl022_slave_output_mode_t mode)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_SOD_MSK)
| (mode << SPI_PL022_SSPCR1_SOD_POS);
}
void spi_pl022_set_loopback_mode(struct spi_pl022_dev_t* dev,
enum spi_pl022_loopback_select_t mode)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_LBM_MSK)
| (mode << SPI_PL022_SSPCR1_LBM_POS);
}
void spi_pl022_enable_interrupt(struct spi_pl022_dev_t* dev,
uint32_t irq_mask)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
p_spi->sspimsc |= (irq_mask & SPI_PL022_SSPIMSC_VALID_MSK);
}
void spi_pl022_disable_interrupt(struct spi_pl022_dev_t* dev,
uint32_t irq_mask)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
p_spi->sspimsc &= ~(irq_mask & SPI_PL022_SSPIMSC_VALID_MSK);
}
uint32_t spi_pl022_get_raw_irq_status(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
return (p_spi->sspris & SPI_PL022_SSPRIS_VALID_MSK);
}
uint32_t spi_pl022_get_masked_irq_status(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
return (p_spi->sspmis & SPI_PL022_SSPMIS_VALID_MSK);
}
void spi_pl022_clear_interrupt(struct spi_pl022_dev_t* dev,
uint32_t irq_mask)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
p_spi->sspicr = (irq_mask & SPI_PL022_SSPICR_VALID_MSK);
}
void spi_pl022_dma_mode_enable(struct spi_pl022_dev_t* dev,
uint32_t dma)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
p_spi->sspdmacr |= (dma & SPI_PL022_SSPDMACR_VALID_MSK);
}
void spi_pl022_dma_mode_disable(struct spi_pl022_dev_t* dev,
uint32_t dma)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
p_spi->sspdmacr &= ~(dma & SPI_PL022_SSPDMACR_VALID_MSK);
}
void spi_pl022_get_periphID(struct spi_pl022_dev_t* dev,
struct spi_pl022_periphid_t* periphid)
{
uint32_t tempid, tempid2;
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
tempid = p_spi->sspperiphid0 & SPI_PL022_SSPPERIPH_ID0_PARTNO_0_MSK;
tempid2 = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_PARTNO_1_MSK)
<< SPI_PL022_SSPPERIPH_ID0_PARTNO_0_SIZE;
periphid->partNumber = tempid | tempid2;
tempid = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_MSK)
>> SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS;
tempid2 = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_MSK)
<< SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_SIZE;
periphid->designerID = tempid | tempid2;
tempid = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_REVIISON_MSK)
>> SPI_PL022_SSPPERIPH_ID2_REVISION_SIZE;
periphid->revision = tempid;
tempid = p_spi->sspperiphid3 & SPI_PL022_SSPPERIPH_ID3_CONFIG_MSK;
periphid->configuration = tempid;
}
void spi_pl022_get_PrimeCell_ID(struct spi_pl022_dev_t* dev,
struct spi_pl022_primecell_id_t* cellid)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
cellid->cellid0 = (uint8_t) p_spi->ssppcellid0;
cellid->cellid1 = (uint8_t) p_spi->ssppcellid1;
cellid->cellid2 = (uint8_t) p_spi->ssppcellid2;
cellid->cellid3 = (uint8_t) p_spi->ssppcellid3;
}
enum spi_pl022_error_t spi_pl022_set_sys_clk(struct spi_pl022_dev_t* dev,
uint32_t sys_clk)
{
uint32_t clk_dvsr;
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
if(!(dev->data->state & SPI_PL022_INITIALIZED)) {
return SPI_PL022_ERR_NOT_INIT;
}
if(!sys_clk) {
return SPI_PL022_ERR_INVALID_ARGS;
}
clk_dvsr = spi_calc_clock_rate(&dev->data->ctrl_cfg, sys_clk, &p_spi->sspcr0);
if(SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) {
return SPI_PL022_ERR_BAD_CONFIG;
}
p_spi->sspcpsr = clk_dvsr;
dev->data->sys_clk = sys_clk;
return SPI_PL022_ERR_NONE;
}
enum spi_pl022_error_t spi_pl022_read(struct spi_pl022_dev_t* dev,
void *rx_ptr)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
if(p_spi->sspsr & SPI_PL022_SSPSR_RNE_MSK) {
if(dev->data->ctrl_cfg.word_size <= 8) {
*(uint8_t*)rx_ptr = p_spi->sspdr & WORD_1BYTE_MASK;
} else {
*(uint16_t*)rx_ptr = p_spi->sspdr & WORD_2BYTES_MASK;
}
return SPI_PL022_ERR_NONE;
}
return SPI_PL022_ERR_NO_RX;
}
uint32_t spi_pl022_slave_read(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
uint32_t data;
if(dev->data->ctrl_cfg.word_size <= 8) {
data = p_spi->sspdr & WORD_1BYTE_MASK;
} else {
data = p_spi->sspdr & WORD_2BYTES_MASK;
}
return data;
}
enum spi_pl022_error_t spi_pl022_write(struct spi_pl022_dev_t* dev,
const enum spi_pl022_mode_select_t mode,
const void *tx_ptr)
{
struct spi_pl022_dev_reg_map_t* p_spi =
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
if(p_spi->sspsr & SPI_PL022_SSPSR_TNF_MSK){
if(dev->data->ctrl_cfg.word_size <= 8) {
p_spi->sspdr = *(const uint8_t*)tx_ptr;
} else {
p_spi->sspdr = *(const uint16_t*)tx_ptr;
}
/* Wait for write to go through */
if (mode == SPI_PL022_MASTER_SELECT) {
while(p_spi->sspsr & SPI_PL022_SSPSR_BSY_MSK) {};
}
return SPI_PL022_ERR_NONE;
}
return SPI_PL022_ERR_NO_TX;
}
enum spi_pl022_error_t spi_pl022_txrx_blocking(struct spi_pl022_dev_t* dev,
const void *tx_ptr,
uint32_t *tx_len_ptr,
void *rx_ptr,
uint32_t *rx_len_ptr)
{
uint32_t i;
enum spi_pl022_error_t retval = SPI_PL022_ERR_NONE;
uint8_t word_size = 1;
uint32_t rx_data, tx_data, total_len;
if(dev->data->ctrl_cfg.word_size > 8) {
word_size = 2;
/* return error if sizes are not word_size aligned */
if ((*tx_len_ptr & 0x1) || (*rx_len_ptr & 0x1)) {
return SPI_PL022_ERR_INVALID_ARGS;
}
}
total_len = (*tx_len_ptr > *rx_len_ptr) ? *tx_len_ptr : *rx_len_ptr;
for(i=0;i<total_len;i+=word_size){
if (i<*tx_len_ptr) {
tx_data = *(const uint16_t*)tx_ptr;
} else {
/* send FF if there is no more valid data to send */
tx_data = 0xFFFF;
}
retval = spi_pl022_write(dev, dev->data->ctrl_cfg.spi_mode, &tx_data);
if(retval != SPI_PL022_ERR_NONE) {
*tx_len_ptr = i;
*rx_len_ptr = i;
break;
}
if(i < *tx_len_ptr) {
tx_ptr = (const uint8_t*)tx_ptr + word_size;
}
retval = spi_pl022_read(dev, &rx_data);
if(retval != SPI_PL022_ERR_NONE) {
/* send went through, align tx_len to the updated tx_ptr */
*tx_len_ptr = i + word_size;
/* don't update rx_len if there is an overflow */
if (i < *rx_len_ptr) {
*rx_len_ptr = i;
}
break;
}
/* do not overflow rx buffer */
if(i<*rx_len_ptr) {
if (word_size == 1) {
*(uint8_t*)rx_ptr = (uint8_t) rx_data;
} else {
*(uint16_t*)rx_ptr = (uint16_t) rx_data;
}
rx_ptr = (uint8_t*)rx_ptr + word_size;
}
}
return retval;
}
/*
* TEST APIs
*/
void spi_pl022_test_fifo_enable(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_test_reg_map_t* p_spi =
(struct spi_pl022_dev_test_reg_map_t*)
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
p_spi->ssptcr |= SPI_PL022_SSPTCR_TESTFIFO_MSK;
}
void spi_pl022_test_fifo_disable(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_test_reg_map_t* p_spi =
(struct spi_pl022_dev_test_reg_map_t*)
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
p_spi->ssptcr &= ~SPI_PL022_SSPTCR_TESTFIFO_MSK;
}
void spi_pl022_integration_test_enable(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_test_reg_map_t* p_spi =
(struct spi_pl022_dev_test_reg_map_t*)
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
p_spi->ssptcr |= SPI_PL022_SSPTCR_ITEN_MSK;
}
void spi_pl022_integration_test_disable(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_test_reg_map_t* p_spi =
(struct spi_pl022_dev_test_reg_map_t*)
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
p_spi->ssptcr &= ~SPI_PL022_SSPTCR_ITEN_MSK;
}
void spi_pl022_write_test_data(struct spi_pl022_dev_t* dev,
void *tx_ptr)
{
struct spi_pl022_dev_test_reg_map_t* p_spi =
(struct spi_pl022_dev_test_reg_map_t*)
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
if(dev->data->ctrl_cfg.word_size <= 8) {
p_spi->ssptdr = *(const uint8_t*)tx_ptr;
} else {
p_spi->ssptdr = *(const uint16_t*)tx_ptr;
}
}
uint32_t spi_pl022_read_test_output_reg(struct spi_pl022_dev_t* dev)
{
struct spi_pl022_dev_test_reg_map_t* p_spi =
(struct spi_pl022_dev_test_reg_map_t*)
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
return p_spi->sspitop;
}

View File

@@ -0,0 +1,501 @@
/*
* 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 spi_pl022_drv.h
* \brief Generic driver for ARM SPI PL022.
*/
#ifndef __SPI_PL022_DRV_H__
#define __SPI_PL022_DRV_H__
#include <stdint.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Frame format */
#define SPI_PL022_CFG_FRF_MOT 0
#define SPI_PL022_CFG_FRF_TI 1
#define SPI_PL022_CFG_FRF_MICROWIRE 2
enum spi_pl022_mode_select_t {
SPI_PL022_MASTER_SELECT = 0,
SPI_PL022_SLAVE_SELECT,
};
enum spi_pl022_slave_output_mode_t {
SPI_PL022_SLAVE_OUTPUT_EN = 0,
SPI_PL022_SLAVE_OUTPUT_DIS,
};
enum spi_pl022_loopback_select_t {
SPI_PL022_LOOPBACK_MODE_DIS = 0,
SPI_PL022_LOOPBACK_MODE_EN,
};
struct spi_pl022_periphid_t {
uint32_t partNumber;
uint32_t designerID;
uint32_t revision;
uint32_t configuration;
};
struct spi_pl022_primecell_id_t {
uint8_t cellid0;
uint8_t cellid1;
uint8_t cellid2;
uint8_t cellid3;
};
/* ARM SPI PL022 device control configuration structure */
struct spi_pl022_ctrl_cfg_t {
enum spi_pl022_mode_select_t spi_mode; /*!< master-slave */
uint8_t frame_format; /*!< frame format bitmap
clock phase [7] polarity [6]
reserved [5:3]
frame_format [1:0] */
uint8_t word_size; /*!< value 4 to 16 */
uint8_t reserved[2]; /*!< to keep 32 bits aligned */
uint32_t bit_rate; /*!< required bit rate */
};
/* ARM SPI PL022 device configuration structure */
struct spi_pl022_dev_cfg_t {
const uint32_t base; /*!< SPI PL022 base address */
const struct spi_pl022_ctrl_cfg_t default_ctrl_cfg; /*!< Default SPI
configuration */
};
/* ARM SPI PL022 device data structure */
struct spi_pl022_dev_data_t {
uint32_t state; /*!< SPI driver state */
uint32_t sys_clk; /*!< System clock frequency */
struct spi_pl022_ctrl_cfg_t ctrl_cfg; /*!< SPI control
configuration data */
};
/* ARM SPI PL022 device structure */
struct spi_pl022_dev_t {
const struct spi_pl022_dev_cfg_t* const cfg; /*!< SPI driver
configuration */
struct spi_pl022_dev_data_t* const data; /*!< SPI driver data */
};
enum spi_pl022_error_t {
SPI_PL022_ERR_NONE = 0, /*!< No error */
SPI_PL022_ERR_INVALID_ARGS, /*!< Invalid input arguments */
SPI_PL022_ERR_NOT_INIT, /*!< SPI driver is not initialized */
SPI_PL022_ERR_NO_TX, /*!< SPI transm FIFO full */
SPI_PL022_ERR_NO_RX, /*!< SPI receive FIFO empty */
SPI_PL022_ERR_BAD_CONFIG, /*!< Bad SPI configuration */
};
/* Interrupt mask defines for the interrupt APIs */
/* Receive Overrun Interrupt */
#define SPI_PL022_RX_OR_INTR_POS 0
#define SPI_PL022_RX_OR_INTR_MSK (0x1ul<<SPI_PL022_RX_OR_INTR_POS)
/* Receive Timeout Interrupt */
#define SPI_PL022_RX_TO_INTR_POS 1
#define SPI_PL022_RX_TO_INTR_MSK (0x1ul<<SPI_PL022_RX_TO_INTR_POS)
/* Receive FIFO Interrupt */
#define SPI_PL022_RX_FIFO_INTR_POS 2
#define SPI_PL022_RX_FIFO_INTR_MSK (0x1ul<<SPI_PL022_RX_FIFO_INTR_POS)
/* Transmit FIFO Interrupt */
#define SPI_PL022_TX_FIFO_INTR_POS 3
#define SPI_PL022_TX_FIFO_INTR_MSK (0x1ul<<SPI_PL022_TX_FIFO_INTR_POS)
#define SPI_PL022_ALL_INTR_MSK \
((0x1ul<<(SPI_PL022_TX_FIFO_INTR_POS+1))-1)
/* Status register bit defines */
/* Transmit FIFO empty */
#define SPI_PL022_SSPSR_TFE_POS 0
#define SPI_PL022_SSPSR_TFE_MSK (0x1ul<<SPI_PL022_SSPSR_TFE_POS)
/* Transmit FIFO not full */
#define SPI_PL022_SSPSR_TNF_POS 1
#define SPI_PL022_SSPSR_TNF_MSK (0x1ul<<SPI_PL022_SSPSR_TNF_POS)
/* Receive FIFO not empty */
#define SPI_PL022_SSPSR_RNE_POS 2
#define SPI_PL022_SSPSR_RNE_MSK (0x1ul<<SPI_PL022_SSPSR_RNE_POS)
/* Receive FIFO full */
#define SPI_PL022_SSPSR_RFF_POS 3
#define SPI_PL022_SSPSR_RFF_MSK (0x1ul<<SPI_PL022_SSPSR_RFF_POS)
/* Busy either tx/rx or transmit fifo not empty */
#define SPI_PL022_SSPSR_BSY_POS 4
#define SPI_PL022_SSPSR_BSY_MSK (0x1ul<<SPI_PL022_SSPSR_BSY_POS)
/**
* \brief Enables PL022 SPI device
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_dev_enable(struct spi_pl022_dev_t* dev);
/**
* \brief Disables PL022 SPI device
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_dev_disable(struct spi_pl022_dev_t* dev);
/**
* \brief Returns SPI status register
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t spi_pl022_get_status(struct spi_pl022_dev_t* dev);
/**
* \brief Initializes the SPI PL022 device.
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] sys_clk System clock.
*
* \return Error code from \ref spi_pl022_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum spi_pl022_error_t spi_pl022_init(struct spi_pl022_dev_t* dev,
uint32_t sys_clk);
/**
* \brief Sets the SPI PL022 device configuration.
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] ctrl_cfg SPI control configuration.
*
* \return Error code from \ref spi_pl022_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum spi_pl022_error_t spi_pl022_set_ctrl_cfg(struct spi_pl022_dev_t* dev,
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg);
/**
* \brief Gets the SPI PL022 device configuration.
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[out] ctrl_cfg Pointer to fill the SPI control configuration.
*
* \return Error code from \ref spi_pl022_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum spi_pl022_error_t spi_pl022_get_ctrl_cfg(struct spi_pl022_dev_t* dev,
struct spi_pl022_ctrl_cfg_t* ctrl_cfg);
/**
* \brief Selects SPI PL022 device as Master or Slave
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] mode Mode selection \ref spi_pl022_mode_select_t
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_select_mode(struct spi_pl022_dev_t* dev,
enum spi_pl022_mode_select_t mode);
/**
* \brief Enables/disables SPI PL022 Slave device output
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] mode Mode selection \ref spi_pl022_slave_output_mode_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dev is Slave or Master
*/
void spi_pl022_set_slave_output(struct spi_pl022_dev_t* dev,
enum spi_pl022_slave_output_mode_t mode);
/**
* \brief Enables SPI PL022 device in loopback mode
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] mode Mode selection \ref spi_pl022_loopback_select_t
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_set_loopback_mode(struct spi_pl022_dev_t* dev,
enum spi_pl022_loopback_select_t mode);
/**
* \brief Clears interrupt mask of SPI PL022
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] irq_mask Selection of interrupts to enable
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_enable_interrupt(struct spi_pl022_dev_t* dev,
uint32_t irq_mask);
/**
* \brief Sets interrupt mask of SPI PL022
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] irq_mask Selection of interrupts to disable
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_disable_interrupt(struct spi_pl022_dev_t* dev,
uint32_t irq_mask);
/**
* \brief Gets raw interrupt status of SPI PL022
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \return Returns raw interrupt status value
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t spi_pl022_get_raw_irq_status(struct spi_pl022_dev_t* dev);
/**
* \brief Gets masked interrupt status of SPI PL022
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \return Returns masked interrupt status value
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t spi_pl022_get_masked_irq_status(struct spi_pl022_dev_t* dev);
/**
* \brief Sets interrupt mask of SPI PL022
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] irq_mask Selection of interrupts to disable
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_clear_interrupt(struct spi_pl022_dev_t* dev,
uint32_t irq_mask);
/**
* \brief Enables transmit or receive DMA
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] dma Selects the DMA to be enabled
* - bit position 0 - Receive DMA
* - bit position 1 - Transmit DMA
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_dma_mode_enable(struct spi_pl022_dev_t* dev,
uint32_t dma);
/**
* \brief Disables transmit or receive DMA
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] dma Selects the DMA to be disabled
* - bit position 0 - Receive DMA
* - bit position 1 - Transmit DMA
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_dma_mode_disable(struct spi_pl022_dev_t* dev,
uint32_t dma);
/**
* \brief Gets peripheral identification of the device
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[out] periphid Pointer to fill peripheral ids
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_get_periphID(struct spi_pl022_dev_t* dev,
struct spi_pl022_periphid_t* periphid);
/**
* \brief Gets PrimeCell identification of the device
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[out] cellid Pointer to fill PrimeCell ids
*
* \note This function doesn't check if dev is NULL.
*/
void spi_pl022_get_PrimeCell_ID(struct spi_pl022_dev_t* dev,
struct spi_pl022_primecell_id_t* cellid);
/**
* \brief Sets system clock.
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] sys_clk System clock.
*
* \return Error code from \ref spi_pl022_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum spi_pl022_error_t spi_pl022_set_sys_clk(struct spi_pl022_dev_t* dev,
uint32_t sys_clk);
/**
* \brief Reads single data from SPI. Non blocking.
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[out] rx_ptr Buffer pointer to be filled
* must be enough for configured word size
*
* \return Error code from \ref spi_pl022_error_t
*
* \note This function doesn't check if dev is NULL and
* if the driver is initialized to reduce the number of checks and
* make the function execution faster.
*/
enum spi_pl022_error_t spi_pl022_read(struct spi_pl022_dev_t* dev,
void *rx_ptr);
/**
* \brief Reads single data from slave SPI. Non blocking.
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \return Returns data value from the device
*
* \note This function doesn't check if dev is NULL and
* does not validate whether there is any data in the RX buffer
*/
uint32_t spi_pl022_slave_read(struct spi_pl022_dev_t* dev);
/**
* \brief Writes single data to SPI. Non blocking.
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] mode Master or slave \ref spi_pl022_mode_select_t
* \param[out] tx_ptr Pointer to the data to be sent
*
* \return Error code from \ref spi_pl022_error_t
*
* \note This function doesn't check if dev is NULL and
* if the driver is initialized to reduce the number of checks and
* make the function execution faster.
*/
enum spi_pl022_error_t spi_pl022_write(struct spi_pl022_dev_t* dev,
const enum spi_pl022_mode_select_t mode,
const void *tx_ptr);
/**
* \brief Transmit and Receive data on SPI in a blocking call
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
* \param[in] tx_ptr Buffer pointer to be filled
* \param[in/out] tx_len_ptr Num values to transfer (updated on error)
* need to be multiples of transfer word length
* \param[out] rx_ptr Buffer pointer to be filled
* \param[in/out] rx_len_ptr Num values to receive (updated on error)
* need to be multiples of transfer word length
*
* \return Error code from \ref spi_pl022_error_t
*
* \note This function doesn't check if dev is NULL and
* if the driver is initialized to reduce the number of checks and
* make the function execution faster.
*/
enum spi_pl022_error_t spi_pl022_txrx_blocking(struct spi_pl022_dev_t* dev,
const void *tx_ptr,
uint32_t *tx_len_ptr,
void *rx_ptr,
uint32_t *rx_len_ptr);
/************************** TEST APIs ****************************/
/**
* \brief Enables Test FIFO mode
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \note This function doesn't check if dev is NULL
*/
void spi_pl022_test_fifo_enable(struct spi_pl022_dev_t* dev);
/**
* \brief Disables Test FIFO mode
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \note This function doesn't check if dev is NULL
*/
void spi_pl022_test_fifo_disable(struct spi_pl022_dev_t* dev);
/**
* \brief Enables Integration Test mode
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \note This function doesn't check if dev is NULL
*/
void spi_pl022_integration_test_enable(struct spi_pl022_dev_t* dev);
/**
* \brief Disables Integration Test mode
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \note This function doesn't check if dev is NULL
*/
void spi_pl022_integration_test_disable(struct spi_pl022_dev_t* dev);
/**
* \brief Writes data to Test data register
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \note This function doesn't check if dev is NULL and
* whether Test FIFO mode is enabled
*/
void spi_pl022_write_test_data(struct spi_pl022_dev_t* dev, void *tx_ptr);
/**
* \brief Reads integration test output register
*
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
*
* \note This function doesn't check if dev is NULL
*/
uint32_t spi_pl022_read_test_output_reg(struct spi_pl022_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __SPI_PL022_DRV_H__ */

View File

@@ -0,0 +1,223 @@
/*
* 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.
*/
/**
* \file timer_cmsdk_drv.c
* \brief Generic driver for CMSDK APB Timers.
* The timer is a 32-bit down-counter with the following features:
* - optional programmable external clock source
* - programmable interrupt source, triggered if counter reaches 0
* - automatic reload if counter reaches 0
*/
#include "timer_cmsdk_drv.h"
/** Setter bit manipulation macro */
#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
/** Clearing bit manipulation macro */
#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
/** Getter bit manipulation macro */
#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
/**
* \brief Timer register map structure
*
*/
struct timer_cmsdk_reg_map_t {
volatile uint32_t ctrl; /* Offset: 0x000 (R/W) control register */
volatile uint32_t value; /* Offset: 0x004 (R/W) current value register */
volatile uint32_t reload; /* Offset: 0x008 (R/W) reload value register */
union {
volatile uint32_t intstatus; /* Offset: 0x00C (R/ ) interrupt
* status register */
volatile uint32_t intclear; /* Offset: 0x00C ( /W) interrupt
* clear register */
}intreg;
};
/**
* \brief CTRL register bit definitions
*
*/
enum ctrl_reg_bits_t{
CTRL_REG_ENUM_ENABLE_INDEX = 0,
CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX = 1,
CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX = 2,
CTRL_REG_ENUM_IRQ_ENABLE_INDEX = 3
};
/**
* \brief INTSTATUS/INTCLEAR register bit definitions
*
*/
enum interrupt_reg_bits_t{
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX = 0
};
void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
if (dev->data->is_initialized == 0) {
register_map->ctrl = 0;
register_map->reload = TIMER_CMSDK_DEFAULT_RELOAD;
dev->data->is_initialized = 1;
}
}
bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev)
{
return dev->data->is_initialized;
}
void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
}
void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
}
bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->ctrl,
CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
}
void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
}
void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
}
bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->ctrl,
CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
}
void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
}
void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
}
bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
}
void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
}
void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
}
bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
}
bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->intreg.intstatus,
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
}
void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->intreg.intclear,
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
}
uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->value;
}
void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
uint32_t reload)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->reload = reload;
}
void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->value = register_map->reload;
}
uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->reload;
}
uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->reload - register_map->value;
}

View File

@@ -0,0 +1,254 @@
/*
* 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.
*/
/**
* \file timer_cmsdk_drv.h
* \brief Generic driver for CMSDK APB Timers.
* The timer is a 32-bit down-counter with the following features:
* - optional programmable external clock source
* - programmable interrupt source, triggered if counter reaches 0
* - automatic reload if counter reaches 0
*/
#ifndef __TIMER_CMSDK_DRV_H__
#define __TIMER_CMSDK_DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Maximum reload value */
#define TIMER_CMSDK_MAX_RELOAD UINT32_MAX /* max of 32-bit */
#define TIMER_CMSDK_DEFAULT_RELOAD TIMER_CMSDK_MAX_RELOAD
/** CMSDK timer device configuration structure */
struct timer_cmsdk_dev_cfg_t {
const uintptr_t base; /*!< Timer base address */
};
/** CMSDK timer device data structure */
struct timer_cmsdk_dev_data_t {
bool is_initialized; /*!< Indicates if the timer is initialized */
};
/* CMSDK timer device structure */
struct timer_cmsdk_dev_t {
const struct timer_cmsdk_dev_cfg_t* const cfg; /*!< Timer configuration */
struct timer_cmsdk_dev_data_t* const data; /*!< Timer data */
};
/**
* \brief Initializes timer to a known default state, which is:
* - timer disabled
* - timer interrupt disabled
* - clock source set to internal
* - external input disabled
* - reload value maxed out
* Init should be called prior to any other process and
* it's the caller's responsibility to follow proper call order.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if a timer is initialized.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if initialized, false otherwise
*/
bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Enables external input, which could be used as clock source
* by calling \ref timer_cmsdk_set_clock_to_external.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Disables external input.
* Make sure if the timer is explicitly wanted to be stopped or set
* the clock source to internal by \ref timer_cmsdk_set_clock_to_internal.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if external input is enabled.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if enabled, false otherwise
*/
bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Sets the clock source to internal.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Sets the clock source to external.
* Make sure external input is enabled correspondingly
* by \ref timer_cmsdk_enable_external_input.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if clock source is external input.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if external, false if internal
*/
bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Enables timer operation.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Disables the given hardware timer.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if a timer is enabled.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if enabled, false otherwise
*/
bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Enables timer interrupt.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Disables timer interrupt.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if a timer interrupt is enabled.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if enabled, false otherwise
*/
bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Gets timer interrupt status
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* * \return true if active, false otherwise
*/
bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Clears timer interrupt
* The interrupt request is held until it is cleared.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Reads timer current value.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return Timer value
*/
uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Sets the reload value of the selected timer.
*
* New reload value takes effect when:
* - timer is restarted
* - on timer underflow
* - when timer_cmsdk_reset is called
*
* \note In r1p0 technical reference manual it's incorrectly stated
* writing the reload value automatically sets the current value also.
* r1p1 technical reference manual includes the fix.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
* \param[in] reload Timer reload value to set.
* This is the start value of the 32-bit down counter,
* which automatically reloaded if 0 is reached.
*/
void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Resets the timer counter to the reload value instantly
* (i.e. without waiting for underflow).
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Gets the reload value of the selected timer.
* This is the start value of the 32-bit down counter,
* which is automatically reloaded if 0 is reached by the counter.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return Reload value of the selected timer.
*/
uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Reads the number of ticks elapsed in the current cycle.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return Get elapsed number of ticks since last reload was set.
* Elapsed = (Reload value - Current value)
*/
uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __TIMER_CMSDK_DRV_H__ */