Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
@@ -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__
|
||||
@@ -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__*/
|
||||
@@ -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__
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
Reference in New Issue
Block a user