diff --git a/COPYING b/COPYING
index 860f3884798..79ebbeac361 100644
--- a/COPYING
+++ b/COPYING
@@ -1,29 +1,47 @@
-COPYING -- Describes the terms under which Nuttx is distributed. A copy of
-the BSD-style licensing is included in this file. In my words -- I believe
-that you should free to use NuttX in any environment, private, private,
-commercial, open, closed, etc. provided only that you respect the modest
-copyright notices as described in license (below), respect Trademarks, and
-include a copy of the BSD license. Please feel free to contact me if you
-have any licensing concerns.
+COPYING
+=======
-Copyright Date Notation: Copyright information is provided in the header
-of each file. This copyright information includes the name of the copyright
-holder and the year(s) in which copyrighted additions to the file were made
-to the file. A comma (',') is used to separate years in the list of years.
-A hyphen ('-') is used as a more compact notation when additions were made
-over several consecutive years. So for example, "2007, 2011" would mean
-that copyrighted additions were made during the years of 2007 and 2011
-whereas "2007-2011" would indicate copyrighted additions in the years 2007,
-2008, 2009, 2010, and 2011.
+Describes the terms under which Nuttx is distributed. A copy of the BSD-
+style licensing is included in this file. In my words -- I believe that you
+should free to use NuttX in any environment, private, private, commercial,
+open, closed, etc. provided only that you respect the modest copyright
+notices as described in license (below), respect Trademarks, and include a
+copy of the BSD license. Please feel free to contact me if you have any
+icensing concerns.
-Copyright Line Continuation: Copy information which exceeds the usable line
-lengh may be broken and continued on the following line, such as:
+Tool Licenses
+-------------
+
+Tools under the nuttx/tools directory are not intended for binary
+distribution. You may find other licensing on individual tools in that
+directory. If you intend to redistribute these tools in binary form, please
+respect the individual license of each tool as identified in the file header
+of the tool source files.
+
+Copyright Date Notation
+-----------------------
+
+Copyright information is provided in the header of each file. This
+copyright information includes the name of the copyright holder and the
+year(s) in which copyrighted additions to the file were made to the file.
+A comma (',') is used to separate years in the list of years. A hyphen ('-')
+is used as a more compact notation when additions were made over several
+consecutive years. So for example, "2007, 2011" would mean that copyrighted
+additions were made during the years of 2007 and 2011 whereas "2007-2011"
+would indicate copyrighted additions in the years 2007, 2008, 2009, 2010,
+and 2011.
+
+Copyright Line Continuation
+---------------------------
+
+Copy information which exceeds the usable line lengh may be broken and
+continued on the following line, such as:
Copyright (C) 2007-2010, 2012, 2014-2015, 2017 Gregory Nutt. All
rights reserved.
NuttX
-^^^^^
+=====
License for NuttX in general (authorship and copyright dates on individual
files will vary):
@@ -64,7 +82,7 @@ files will vary):
****************************************************************************/
FAT Long File Names
-^^^^^^^^^^^^^^^^^^^
+===================
NOTE: If CONFIG_FAT_LFN is defined in your NuttX configuration file, then
there may be some legal, patent issues. The following was extracted from
@@ -99,7 +117,7 @@ FAT Long File Names
So you have been forewarned: Use the long filename at your own risk!
uIP
-^^^
+===
Many lower-level networking components of NuttX derive from uIP which
has a similar BSD style license:
@@ -108,7 +126,7 @@ has a similar BSD style license:
All rights reserved.
IGMP
-^^^^
+===
IGMP support, if enabled, adds additional logic by Steve Reynolds:
@@ -116,7 +134,7 @@ IGMP support, if enabled, adds additional logic by Steve Reynolds:
All rights reserved.
The HID Parser in drivers/usbhost
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+=================================
Adapted from the LUFA Library (MIT license):
@@ -144,8 +162,8 @@ The HID Parser in drivers/usbhost
Certain functions in the NuttX C-library derive from other BSD-compatible
sources:
-fs/nfs:
-^^^^^^^
+fs/nfs
+======
NFS:
@@ -166,7 +184,7 @@ fs/nfs:
California, Berkeley and its contributors."
fs/spiffs
-^^^^^^^^^
+=========
The MIT License (MIT)
@@ -189,14 +207,14 @@ fs/spiffs
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-strtod():
-^^^^^^^^
+strtod()
+========
Copyright (C) 2002 Michael Ringgaard. All rights reserved.
Copyright (C) 2006-2007 H. Peter Anvin.
-dtoa():
-^^^^^^
+dtoa()
+======
If you enable floating point conversions with CONFIG_LIBC_FLOATINGPOINT,
then some files with an unmodified BSD license will be included. That
@@ -207,7 +225,7 @@ dtoa():
California, Berkeley and its contributors."
libc/string/lib_vikmemcpy.c
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+===========================
If you enable CONFIG_MEMCPY_VIK, then you will build with the optimized
version of memcpy from Daniel Vik. Licensing information for that version
@@ -236,7 +254,7 @@ libc/string/lib_vikmemcpy.c
distribution.
libs/libc/math
-^^^^^^^^^^^^^^
+==============
If you enable CONFIG_LIB, you will build the math library at libc/math.
This library was taken from the math library developed for the Rhombus
@@ -258,7 +276,7 @@ libs/libc/math
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
drivers/video/ov2640
-^^^^^^^^^^^^^^^^^^^^
+====================
WARNING: Some of the information in the data tables in this file came
from other projects with conflicting licenses: Linux and ArduCAM. Those
diff --git a/Documentation/NuttXCCodingStandard.html b/Documentation/NuttXCCodingStandard.html
index cd6eead0d59..2b187b50fc1 100644
--- a/Documentation/NuttXCCodingStandard.html
+++ b/Documentation/NuttXCCodingStandard.html
@@ -17,7 +17,9 @@
- 1.0 General Conventions
+
+ 1.0 General Conventions
+
- 2.0 Data and Type Definitions
+
+ 2.0 Data and Type Definitions
+
- 3.0 Functions
+
+ 3.0 Functions
+
- 4.0 Statements
+
+ 4.0 Statements
+
- Appendix A
+
+ 5.0 C++
+
+
+ Appendix A
+
A.1 C Source File Structure
A.2 C Header File Structure
@@ -74,7 +87,7 @@
NuttX C Coding Standard
- Last Updated: February 5, 2019
+ Last Updated: July 6, 2019
@@ -247,7 +260,7 @@
Forming Guard Names.
Then pre-processor macro name used in the guard is formed from the full, relative path to the header for from the top-level, controlled directory.
- That pat is preceded by __ and _ replaces each character that would otherwise be invalid in a macro name.
+ That path is preceded by __ and _ replaces each character that would otherwise be invalid in a macro name.
So, for example, __INCLUDE_NUTTX_ARCH_H corresponds to the header file include/nuttx/arch.h
@@ -1026,6 +1039,16 @@ int animals(int animal)
Indentation of Pre-Processor Lines.
C Pre-processor commands following any conditional computation are also indented following basically the indentation same rules, differing in that the # always remains in column 1.
+
+ When C pre-processor statements are indented, they should be should be indented by 2 spaces per level-of-indentation following the #.
+ C pre-processor statements should be indented when they are enclosed within C pre-processor conditional logic (#if..#endif). The level of indentation increases with each level of such nested conditional logic.
+
+
+ C pre-processor statements should always be indented in this way in the Pre-processor Definitions section of each file.
+ C pre-processor statements may be indented in the Public/Private Data and Public/Private Functions sections of the file.
+ However, often the indentation of C pre-processor statements conflicts with the indentation of the C code and makes the code more difficult to read.
+ In such cases, indentation of C pre-processor statements should be ommitted in those sections (only).
+
@@ -1802,6 +1825,10 @@ enum xyz_state_e
Side effects.
Be careful of side effects.
+ -
+ Indentation.
+ See the Indentation of Pre-Processor Lines requirements above.
+
Other Applicable Coding Standards.
@@ -2065,7 +2092,14 @@ ptr = (FAR struct somestruct_s *)value;
As a rule of thumb, the length of a function should be limited so that it would fit on a single page (if you were to print the source code).
-
- Space after the function body
+ Return Statement.
+ The argument of the
return statement should not be enclosed in parentheses.
+ A reasonable exception is the case where the returned value argument is a complex expression and where the parentheses improve the readability of the code.
+ Such complex expressions might be Boolean expressions or expressions containing conditions.
+ Simple arithmetic computations would not be considered complex expressions.
+
+ -
+ Space after the function body.
A one (and only one) blank line must follow the closing right brace of the function body.
@@ -2094,7 +2128,7 @@ ptr = (FAR struct somestruct_s *)value;
}
}
- return e / a;
+ return (e / a);
}
|
@@ -2102,28 +2136,28 @@ ptr = (FAR struct somestruct_s *)value;
Correct
int myfunction(int a, int b)
- {
- int c;
- int d;
- int e;
- int i;
+ {
+ int c;
+ int d;
+ int e;
+ int i;
- c = a
- d = b;
- e = c + d;
+ c = a
+ d = b;
+ e = c + d;
- for (i = 0; i < a; i++)
- {
- int j;
+ for (i = 0; i < a; i++)
+ {
+ int j;
- for (j = 0; j < b; j++)
- {
- e += j * d;
- }
- }
+ for (j = 0; j < b; j++)
+ {
+ e += j * d;
+ }
+ }
- return e / a;
- }
+ return e / a;
+ }
@@ -2720,6 +2754,127 @@ error:
See the discussion of pointers for information about the FAR qualifier used above.
+
+
+
+ There is no existing document that provides a complete coding standard for NuttX C++ files.
+ This section is included here to provide some minimal guidance in C++ code development.
+ In most details like indentation, spacing, and file organization, it is identical to the C coding standard.
+ But there are significant differences in the acceptable standard beyond that.
+ The primary differences are as follows:
+
+
+ -
+
+ C++ style comments are not only permissible but are required (other than for the following exception).
+ This includes the block comments of in the Source File Structure described in an Appendix to this standard.
+
+
+ -
+
+ Deoxygen tags are acceptable. As are C style comments when needed to provide DOxygen tags.
+
+
+ -
+
+ There is currently no requirement to conform any specific C++ version.
+ However, for portability reasons, conformance to older, pre-C++11 standards is encouraged where reasonable.
+
+ -
+
+ C++ file name extensions: The extension .cxx is used for C++ source files; the extension .hxx is used for C++ header files.
+
+ -
+
+ All naming must use CamelCase.
+ Use of the underbar character, '_' is discouraged.
+ This includes variables, classes, structures, ..., etc.: All user-nameable C++ elements.
+ Pre-processor definitions are still required to be all upper case.
+
+
+ -
+
+ Local variable, method names, and function names must all begin with a lower case letter.
+ As examples, myLocalVariable would be a compliant name for a local variable;
+ myMethod would be a compliant name for a method;
+
+ -
+
+ Namespaces, global variable, class, structure, template, and enumeration names begin with a capital letter identifying what is being named:
+
+
+
+
+ -
+ Namespace Names
+
+ -
+ Namespaces begin with an upper case character but no particular character is specified.
+ As an example,
MyNamespace is fully compliant.
+
+ -
+ Global Variable Names
+
+ -
+ Global variables and singletons begin with an upper case 'G'.
+ For example,
GMyGlobalVariable.
+ The prefix g_ is never used.
+
+ -
+ Implementation Class Names
+
+ -
+ Classes that implement methods begin with an upper case 'C'.
+ For example,
CMyClass.
+ A fully qualified method of CMyClass could be MyNamespace::CMyClass::myMethod
+
+ -
+ Pure Virtual Base Class Names
+
+ -
+ Such base classes begin with an upper case 'I'.
+ For example,
IMyInterface.
+
+ -
+ Template Class Names
+
+ -
+ Template classes begin with an upper case 'T'.
+ For example,
TMyTemplate.
+
+ -
+
typedef'd Type Names
+
+ -
+ Currently all such types also begin with an upper case 'T'.
+ That probably needs some resolution to distinguish for template names.
+ The suffix
_t is never used.
+
+ -
+ Structure Names
+
+ -
+ Structures begin with an upper case 'S'.
+ For example,
SMyStructure.
+ The suffix _s is never used.
+
+ -
+ Enumerations Names
+
+ -
+ Enumerations begin with an upper case 'E'.
+ For example,
EMyEnumeration.
+ The suffix _e is never used.
+
+
+
+
|
diff --git a/Documentation/README.html b/Documentation/README.html
index 094a883ce9e..fa56f3d72df 100644
--- a/Documentation/README.html
+++ b/Documentation/README.html
@@ -8,7 +8,7 @@
|
NuttX README Files
- Last Updated: June 4, 2019
+ Last Updated: June 17, 2019
|
@@ -160,6 +160,7 @@ nuttx/
| |- lpcxpresso-lpc54628/
| | `- README.txt
| |- makerlisp/
+ | | |- nsh/README.txt
| | `- README.txt\
| |- maple/
| | `- README.txt\
@@ -253,6 +254,8 @@ nuttx/
| | `- README.txt
| |- pic32mz-starterkit/
| | `- README.txt
+ | |- pnev5180b/
+ | | `- README.txt
| |- qemu-i486/
| | `- README.txt
| |- sabre-6quad/
diff --git a/Kconfig b/Kconfig
index dbcf9ee9ff6..77c73411dc9 100644
--- a/Kconfig
+++ b/Kconfig
@@ -281,6 +281,13 @@ config RRLOAD_BINARY
Create nuttx.rr in the rrload binary format used with
BSPs from www.ridgerun.com using the tools/mkimage.sh script.
+config CXD56_BINARY
+ bool "spk binary format"
+ default n
+ ---help---
+ Create nuttx.spk binary format used on spresense board and boards
+ based on cxd56xx arch.
+
config INTELHEX_BINARY
bool "Intel HEX binary format"
default n
@@ -1684,6 +1691,10 @@ menu "Audio Support"
source audio/Kconfig
endmenu
+menu "Video Support"
+source video/Kconfig
+endmenu
+
menu "Wireless Support"
source wireless/Kconfig
endmenu
diff --git a/README.txt b/README.txt
index d4e4acb15e8..3ab4d62b2f1 100644
--- a/README.txt
+++ b/README.txt
@@ -135,6 +135,10 @@ Installing Cygwin
of the Cygwin utilities that you will need to build NuttX. The
build will fail in numerous places because of missing packages.
+ NOTE: The last time I installed EVERYTHING, the download was
+ about 5GiB. The server I selected was also very slow so it took
+ over a day to do the whole install!
+
NOTE: You don't really have to install EVERYTHING but I cannot
answer the question "Then what should I install?" I don't know
the answer to that and so will continue to recommend installing
@@ -147,6 +151,19 @@ Installing Cygwin
Perhaps a minimum set would be those packages listed below for the
"Ubuntu Bash under Windows 10" installation?
+ UPDATE: Sergey Frolov had success with the following minimal
+ Cygwin configuration:
+
+ 1. After starting the Cygwin installer, keep the recommended
+ packages that are pre-selected in the default configuration.
+ 2. Using the installation tools, add the following packages:
+
+ make (GNU make) bison libgmp3-dev
+ gcc-core byacc libmpfr-dev
+ gcc-g++ gperf libmpc-dev
+ flex gdb automake-1.15
+ libncurses-dev libgmp-dev
+
After installing Cygwin, you will get lots of links for installed
tools and shells. I use the RXVT native shell. It is fast and reliable
and does not require you to run the Cygwin X server (which is neither
@@ -154,10 +171,6 @@ Installing Cygwin
instructions assume that you are at a bash command line prompt in
either Linux or in Cygwin shell.
- UPDATE: The last time I installed EVERYTHING, the download was
- about 5GiB. The server I selected was also very slow so it took
- over a day to do the whole install!
-
Using MSYS
----------
@@ -457,6 +470,14 @@ Downloading from Repositories
Cloning the Repository
+ BEFORE cloning repositories on any Windows platform do the following GIT
+ command:
+
+ git config --global core.autocrlf false
+
+ That will avoid conversions of linefeeds (newlines, \n) to carriage
+ return plus linefeed sequences (\r\n)
+
The current NuttX du jour is available in from a GIT repository. Here are
instructions for cloning the core NuttX RTOS (corresponding to the nuttx
tarball discussed above)::
@@ -1834,6 +1855,7 @@ nuttx/
| |- lpcxpresso-lpc54628/
| | `- README.txt
| |- makerlisp/
+ | | |- nsh/README.txt
| | `- README.txt
| |- maple/
| | `- README.txt
@@ -1926,6 +1948,8 @@ nuttx/
| | `- README.txt
| |- pic32mz-starterkit/
| | `- README.txt
+ | |- pnev5180b/
+ | | `- README.txt
| |- qemu-i486/
| | `- README.txt
| |- sabre-6quad/
diff --git a/TODO b/TODO
index 67587d1ab78..34b3a156710 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-NuttX TODO List (Last updated April 29, 2019)
+NuttX TODO List (Last updated July 1, 2019)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@@ -19,7 +19,7 @@ nuttx/:
(9) Kernel/Protected Build
(3) C++ Support
(5) Binary loaders (binfmt/)
- (18) Network (net/, drivers/net)
+ (17) Network (net/, drivers/net)
(4) USB (drivers/usbdev, drivers/usbhost)
(2) Other drivers (drivers/)
(9) Libraries (libs/libc/, libs/libm/)
@@ -1653,23 +1653,6 @@ o Network (net/, drivers/net)
before, so I suspect it might not be so prevalent as one
might expect.
- Title: TCP SOCKETS CLOSED TOO QUICKLY
- Description: When a socket is closed, the resources are torn down
- immediately (unless the SO_LINGER option is selected). As a
- result, the socket does not send the FIN and this looks like
- an unexpected, abnormal loss of connection to the remote peer.
-
- Actually, it is worse than this: The is NO logic to send
- FIN in when the file is close. This is pretty easy to do,
- however:
-
- - Wait for a TCP poll, then
- - Call tcp_append with TCP_CLOSE in the flags. There is
- already logic in tcp_appsend to send the FIN in this case,
- it is just not being use.
- Status: Open
- Priority: Medium-Low.
-
Title: LOCAL DATAGRAM RECVFROM RETURNS WRONG SENDER ADDRESS
Description: The recvfrom logic for local datagram sockets returns the
incorrect sender "from" address. Instead, it returns the
diff --git a/arch/arm/include/cxd56xx/adc.h b/arch/arm/include/cxd56xx/adc.h
new file mode 100644
index 00000000000..83dcb7975a8
--- /dev/null
+++ b/arch/arm/include/cxd56xx/adc.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * arch/arm/include/cxd56xx/adc.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_INCLUDE_CXD56XX_CXD56_ADC_H
+#define __ARCH_ARM_INCLUDE_CXD56XX_CXD56_ADC_H
+
+/****************************************************************************
+ * include files
+ ***************************************************************************/
+
+#include
+#include
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ANIOC_USER (AN_FIRST + AN_NCMDS)
+
+/* Start sampling
+ *
+ * param None
+ * return ioctl return value provides success/failure indication
+ */
+
+#define ANIOC_CXD56_START _ANIOC(ANIOC_USER + 0)
+
+/* Stop sampling
+ *
+ * param None
+ * return ioctl return value provides success/failure indication
+ */
+
+#define ANIOC_CXD56_STOP _ANIOC(ANIOC_USER + 1)
+
+/* Set sampling frequency
+ *
+ * param None
+ * return ioctl return value provides success/failure indication
+ */
+
+#define ANIOC_CXD56_FREQ _ANIOC(ANIOC_USER + 2)
+
+/* Set fifo size
+ *
+ * param None
+ * return ioctl return value provides success/failure indication
+ */
+
+#define ANIOC_CXD56_FIFOSIZE _ANIOC(ANIOC_USER + 3)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Initialize valid ADC channels
+ *
+ * return OK(0) is success. negative value is failure.
+ */
+
+int cxd56_adcinitialize(void);
+
+#endif /* __ARCH_ARM_INCLUDE_CXD56XX_CXD56_ADC_H */
diff --git a/arch/arm/include/cxd56xx/battery_ioctl.h b/arch/arm/include/cxd56xx/battery_ioctl.h
new file mode 100644
index 00000000000..bbd37a70eef
--- /dev/null
+++ b/arch/arm/include/cxd56xx/battery_ioctl.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+ * include/arch/chip/battery_ioctl.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_INCLUDE_CXD56XX_BATTERY_IOCTL_H
+#define __ARCH_ARM_INCLUDE_CXD56XX_BATTERY_IOCTL_H
+
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* ioctl commands */
+
+#define BATIOC_GET_CHGVOLTAGE _BATIOC(0x0010)
+#define BATIOC_GET_CHGCURRENT _BATIOC(0x0012)
+#define BATIOC_GET_RECHARGEVOL _BATIOC(0x0013)
+#define BATIOC_SET_RECHARGEVOL _BATIOC(0x0014)
+#define BATIOC_GET_COMPCURRENT _BATIOC(0x0015)
+#define BATIOC_SET_COMPCURRENT _BATIOC(0x0016)
+#define BATIOC_GET_TEMPTABLE _BATIOC(0x0017)
+#define BATIOC_SET_TEMPTABLE _BATIOC(0x0018)
+#define BATIOC_GET_CURRENT _BATIOC(0x0019)
+#define BATIOC_GET_VOLTAGE _BATIOC(0x001a)
+
+#define BATIOC_MONITOR_ENABLE _BATIOC(0x0030)
+#define BATIOC_MONITOR_STATUS _BATIOC(0x0031)
+#define BATIOC_MONITOR_SET _BATIOC(0x0032)
+#define BATIOC_MONITOR_GET _BATIOC(0x0033)
+
+#define BATIOC_DEBUG _BATIOC(0x00db)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct battery_temp_table_s
+{
+ int T60; /* 60 degree C */
+ int T45; /* 45 degree C */
+ int T10; /* 10 degree C */
+ int T00; /* 0 degree C */
+};
+
+struct bat_monitor_enable_s
+{
+ int on;
+ int interval;
+ int threshold_volt;
+ int threshold_current;
+};
+
+struct bat_monitor_status_s
+{
+ int run;
+ int index;
+ int latest;
+ int totalwatt;
+ int totaltime;
+};
+
+struct bat_monitor_set_s
+{
+ int clearbuf;
+ int clearsum;
+};
+
+struct bat_monitor_rec_s
+{
+ uint16_t index;
+ uint16_t timestamp;
+ uint16_t voltage;
+ int16_t current;
+};
+
+struct bat_monitor_log_s
+{
+ FAR struct bat_monitor_rec_s *rec;
+ int index;
+ int size;
+};
+
+#endif /* __ARCH_ARM_INCLUDE_CXD56XX_BATTERY_IOCTL_H */
diff --git a/arch/arm/include/cxd56xx/cisif.h b/arch/arm/include/cxd56xx/cisif.h
new file mode 100644
index 00000000000..2967fd07269
--- /dev/null
+++ b/arch/arm/include/cxd56xx/cisif.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+ * arch/arm/include/cxd56xx/cisif.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_INCLUDE_CXD56XX_CISIF_H
+#define __ARCH_ARM_INCLUDE_CXD56XX_CISIF_H
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+typedef void (*notify_callback_t)(uint8_t code, uint32_t size, uint32_t addr);
+typedef void (*comp_callback_t)(uint8_t code, uint32_t size, uint32_t addr);
+
+struct cisif_init_yuv_param_s
+{
+ uint16_t hsize;
+ uint16_t vsize;
+ uint32_t notify_size;
+ notify_callback_t notify_func;
+};
+
+typedef struct cisif_init_yuv_param_s cisif_init_yuv_param_t;
+
+struct cisif_init_jpeg_param_s
+{
+ uint32_t notify_size;
+ notify_callback_t notify_func;
+};
+
+typedef struct cisif_init_jpeg_param_s cisif_init_jpeg_param_t;
+
+struct cisif_sarea_s
+{
+ uint8_t *strg_addr;
+ uint32_t strg_size;
+};
+
+typedef struct cisif_sarea_s cisif_sarea_t;
+
+struct cisif_param_s
+{
+ uint32_t format;
+ cisif_init_yuv_param_t yuv_param;
+ cisif_init_jpeg_param_t jpg_param;
+ cisif_sarea_t sarea;
+ comp_callback_t comp_func;
+};
+
+typedef struct cisif_param_s cisif_param_t;
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+int cxd56_cisifinit(void);
+int cxd56_cisiffinalize(void);
+int cxd56_cisifstartcapture(cisif_param_t *param, cisif_sarea_t *sarea);
+int cxd56_cisifstopcapture(void);
+int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM_INCLUDE_CXD56XX_CISIF_H */
diff --git a/arch/arm/include/cxd56xx/irq.h b/arch/arm/include/cxd56xx/irq.h
index 7b20667d800..f3aa541d281 100644
--- a/arch/arm/include/cxd56xx/irq.h
+++ b/arch/arm/include/cxd56xx/irq.h
@@ -218,21 +218,6 @@
#define NR_VECTORS CXD56_IRQ_NIRQS
#define NR_IRQS CXD56_IRQ_NIRQS
-/* Cortex-M0 External interrupts (vectors >= 16) */
-
-#if 0
-# define CXD56M0_IRQ_NIRQS (CXD56_IRQ_EXTINT + CXD56M0_IRQ_NEXTINT)
-#endif
-
-/* Total number of IRQ numbers (This will need to be revisited if/when the
- * Cortex-M0 is supported)
- */
-
-#if 0
-# define NR_VECTORS CXD56M0_IRQ_NIRQS
-# define NR_IRQS CXD56M0_IRQ_NIRQS
-#endif
-
/****************************************************************************
* Public Types
****************************************************************************/
diff --git a/arch/arm/include/cxd56xx/pm.h b/arch/arm/include/cxd56xx/pm.h
index 50b05271023..5f0ba2c0272 100644
--- a/arch/arm/include/cxd56xx/pm.h
+++ b/arch/arm/include/cxd56xx/pm.h
@@ -32,9 +32,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
-/**
- * @file pm.h
- */
#ifndef __ARCH_ARM_INCLUDE_CXD56XX_PM_H
#define __ARCH_ARM_INCLUDE_CXD56XX_PM_H
diff --git a/arch/arm/include/cxd56xx/scu.h b/arch/arm/include/cxd56xx/scu.h
new file mode 100644
index 00000000000..450044bd875
--- /dev/null
+++ b/arch/arm/include/cxd56xx/scu.h
@@ -0,0 +1,560 @@
+/****************************************************************************
+ * arch/arm/include/cxd56xx/scu.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_INCLUDE_CXD56XX_SCU_H
+#define __ARCH_ARM_INCLUDE_CXD56XX_SCU_H
+
+/****************************************************************************
+ * include files
+ ****************************************************************************/
+
+#include
+#include
+#include
+
+/***************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define _SCUIOCBASE (0xa000)
+
+#define _SCUIOCVALID(c) (_IOC_TYPE(c)==_SCUIOCBASE)
+#define _SCUIOC(nr) _IOC(_SCUIOCBASE,nr)
+
+/*
+ * Set FIFO size used by sequencer
+ *
+ * uint16_t FIFO size in bytes
+ * return ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETFIFO _SCUIOC(0x0001)
+
+/*
+ * Free FIFO used by sequencer
+ *
+ * param: none
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_FREEFIFO _SCUIOC(0x0002)
+
+/*
+ * Set sequencer sampling rate
+ *
+ * param: uint8_t: sampling rate
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETSAMPLE _SCUIOC(0x0003)
+
+/*
+ * Enable/Disable sign conversion preprocessing
+ *
+ * param: unsigned long: 0 = disable, 1 = enable
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETSIGNCONV _SCUIOC(0x0004)
+
+/*
+ * Set offset/gain adjustment parameter
+ *
+ * param: Pointer to struct adjust_xyz_s.
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETOGADJUST _SCUIOC(0x0005)
+
+/*
+ * Clear offset/gain adjustment parameter
+ *
+ * param: none
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_CLROGADJUST _SCUIOC(0x0006)
+
+/*
+ * Set IIR filter coefficiencies
+ *
+ * param: Pointer to struct math_filter_s
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETFILTER _SCUIOC(0x0007)
+
+/*
+ * Set event notifier parameters
+ *
+ * Set event notifier. This command must use with IIR filter, so it will be
+ * error when no filter set by SCUIOC_SETFILTER.
+ *
+ * param: Pointer to struct scuev_notify_s
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETNOTIFY _SCUIOC(0x0008)
+
+/*
+ * Set elements per sample
+ *
+ * SCU can be treat 3 axis sample data as 1 or 2 axis data. For example,
+ * user can be used to detect via event notifier, about the board is
+ * tilting, by X and Y axis data from accelerometer.
+ * This setting will be affected for IIR Filter and event notifier.
+ *
+ * param: unsigned long: 1 - 3
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETELEMENTS _SCUIOC(0x0009)
+
+/*
+ * Set decimation parameters (Decimator only)
+ *
+ * param: Pointer to struct decimation_s
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETDECIMATION _SCUIOC(0x000a)
+
+/*
+ * Set FIFO sample data watermark
+ *
+ * param: Pointer of struct scufifo_wm_s
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETWATERMARK _SCUIOC(0x000b)
+
+/*
+ * Start sequencer
+ *
+ * param: None
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_START _SCUIOC(0x0010)
+
+/*
+ * Stop sequencer
+ *
+ * param: None
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_STOP _SCUIOC(0x0011)
+
+/*
+ * Set FIFO overwrite mode
+ *
+ * param: unsigned long: 0 = overwrite disable, 1 = overwrite enable
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_SETFIFOMODE _SCUIOC(0x0012)
+
+/*
+ * Delete FIFO data
+ *
+ * param: uint16_t delete size
+ * return: ioctl return value provides success/failure indication
+ */
+
+#define SCUIOC_DELFIFODATA _SCUIOC(0x0013)
+
+#define SCU_BUS_SPI 1 /*< SPI bus */
+#define SCU_BUS_I2C0 2 /*< I2C0 bus */
+#define SCU_BUS_I2C1 3 /*< I2C1 bus */
+#define SCU_BUS_LPADC0 0x10 /*< LPADC0 */
+#define SCU_BUS_LPADC1 0x11 /*< LPADC1 */
+#define SCU_BUS_LPADC2 0x12 /*< LPADC2 */
+#define SCU_BUS_LPADC3 0x13 /*< LPADC3 */
+#define SCU_BUS_HPADC0 0x14 /*< HPADC1 */
+#define SCU_BUS_HPADC1 0x15 /*< HPADC2 */
+
+/* Send 1 byte instruction */
+
+#define SCU_INST_SEND(val) ((val) & 0xff)
+
+/* Receive n byte instruction (n: 1 - 8) */
+
+#define SCU_INST_RECV(n) ((1 << 8) | (((n) - 1) & 0x7) << 12)
+
+#define SCU_INST_TERM (1 << 11)
+#define SCU_INST_RESTART (1 << 10)
+#define SCU_INST_STOP (1 << 9)
+
+/* Indicate this instruction is last */
+
+#define SCU_INST_LAST (SCU_INST_TERM|SCU_INST_STOP)
+
+/* Sequencer types */
+
+#define SEQ_TYPE_NORMAL 0 /*< Normal sequencer */
+#define SEQ_TYPE_DECI 1 /*< Decimator */
+
+/* Event control */
+
+#define SCU_EV_RISE_EN (1 << 31) /*< Rise event enable */
+#define SCU_EV_FALL_EN (1 << 30) /*< Fall event enable */
+#define SCU_EV_OUT8BITS (1 << 29) /*< Output only upper 8 bits */
+
+#define SCU_EV_OUTSHIFT 16
+#define SCU_EV_OUTMASK (3 << SCU_EV_OUTSHIFT)
+#define SCU_EV_OUTALWAYS (0 << SCU_EV_OUTSHIFT) /*< Always output to FIFO */
+#define SCU_EV_OUTSTART (1 << SCU_EV_OUTSHIFT) /*< Output start after event occurred */
+#define SCU_EV_OUTSTOP (2 << SCU_EV_OUTSHIFT) /*< Output stop after event occurred */
+#define SCU_EV_NOTOUT (3 << SCU_EV_OUTSHIFT) /*< No output to FIFO */
+
+#define SCU_EV_WRITESAMPLEMASK 0xfff
+
+/* Output samples when event occurred */
+
+#define SCU_EV_WRITESAMPLES(sample) ((sample) & SCU_EV_WRITESAMPLEMASK)
+
+/* Event type flags */
+
+#define SCU_EV_RISE (1) /*< Rise (low to high) event occurred */
+#define SCU_EV_FALL (2) /*< Fall (high to low) event occurred */
+
+/* Level adjustment (decimator only) */
+
+#define SCU_LEVELADJ_X1 (0) /*< Level adjustment x1 */
+#define SCU_LEVELADJ_X2 (1) /*< Level adjustment x2 */
+#define SCU_LEVELADJ_X4 (2) /*< Level adjustment x4 */
+#define SCU_LEVELADJ_X8 (3) /*< Level adjustment x8 */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/*
+ * IIR filter position
+ * details IIR filter can be set 2 filters on data path.
+ * image html scu_IIR_filter_path.png
+ */
+
+enum filter_pos_e
+{
+ FILTER_POS_NONE = 0, /*< Filter none */
+ FILTER_POS_AA, /*< 2 for all */
+ FILTER_POS_FF, /*< 2 for FIFO */
+ FILTER_POS_AF, /*< 1 for all, 1 for FIFO */
+ FILTER_POS_EE, /*< 2 for Event detector */
+ FILTER_POS_AE, /*< 1 for all, 1 for Event detector */
+ FILTER_POS_FE, /*< 1 for FIFO, 1 for Event detector */
+};
+
+/* Sample timestamp */
+
+struct scutimestamp_s
+{
+ uint32_t sec; /*< Seconds */
+ uint16_t tick; /*< Clock tick (based on 32768 Hz) */
+};
+
+/* IIR filter coefficiencies */
+
+struct iir_coeff_s
+{
+ uint32_t h; /* High 32 bit */
+ uint8_t l; /* Low 8 bit */
+};
+
+/* IIR filter setting */
+
+struct iir_filter_s
+{
+ uint8_t ishift; /*< Input shift */
+ uint8_t oshift; /*< Output shift */
+ struct iir_coeff_s coeff[5]; /*< IIR filter coefficiencies */
+};
+
+/* Math Function IIR filter setting */
+
+struct math_filter_s
+{
+ enum filter_pos_e pos; /*< Insert position identifier */
+ struct iir_filter_s filter[2]; /*< IIR filter parameters */
+};
+
+/*
+ * Event configuration
+ *
+ * a threshold is rise/fall threshold for input data.
+ * When set this member for a rise in struct scuev_notify_s, counting data
+ * if higher than threshold, and a fall is vise-versa.
+ * a count0 is used for prevent chattering. a count1 is used for counting
+ * continuously input.
+ * When configured for a rise, SCU processing as follows:
+ *
+ * - Counting higher value than threshold coninuously
+ * - If counter reached to a count0, start actual couning
+ * - If input data fall less than threshold before reached to a count0,
+ * then stop and reset counts
+ * - If total count is reached to a count0 + a count1, then raise rise event
+ * - If count1 is zero, then notify when count reached to a count0
+ * immediately
+ * - If threshold or count0 is zero, configuration is ignored
+ */
+
+struct sensor_event_s
+{
+ uint16_t threshold; /*< Threshold */
+ uint16_t count0; /*< Preventing counts */
+ uint16_t count1; /*< Actual counts */
+ uint16_t delaysamples; /*< Event notification delay in samples */
+};
+
+/* Arguments for event signal */
+
+struct scuev_arg_s
+{
+ struct scutimestamp_s ts; /*< timestamp stored when event occurred. */
+ uint32_t type; /*< Event type (SCU_EV_RISE or SCU_EV_FALL) */
+};
+
+/* Event notifier setting */
+
+struct scuev_notify_s
+{
+ int signo; /*< Signal number (0 - 31, except system reserved) */
+
+ struct sensor_event_s rise; /*< Rise threshold */
+ struct sensor_event_s fall; /*< Fall threshold */
+
+ uint32_t ctrl; /*< Event control */
+
+ FAR struct scuev_arg_s *arg; /*< Arguments for event raised */
+};
+
+/* Offset/gain adjustment parameter */
+
+struct adjust_s {
+ uint16_t offset; /*< Offset value */
+ uint16_t gain; /*< Gain value */
+};
+
+/* Offset/gain adjustment parameter for 3 axis */
+
+struct adjust_xyz_s {
+ struct adjust_s x; /*< For X axis */
+ struct adjust_s y; /*< For Y axis */
+ struct adjust_s z; /*< For Z axis */
+};
+
+/* Decimation parameter */
+
+struct decimation_s
+{
+ uint8_t ratio; /*< Decimation ratio (1 / (2 ^ ratio)), 0 - 9 */
+ uint8_t leveladj; /*< Output data multiplier */
+ uint8_t forcethrough; /*< Force through */
+};
+
+/* Watermark notification */
+
+struct scufifo_wm_s
+{
+ int signo; /*< Signal number (0 - 31, except system reserved) */
+
+ /* Pointer to memomry to be timestamp stored */
+
+ FAR struct scutimestamp_s *ts;
+
+ /*
+ * Watermark value. SCU notifies when
+ * stored samples over watermark in FIFO.
+ * Valid value range: 1 - 65535
+ */
+
+ uint16_t watermark;
+};
+
+struct seq_s; /* The sequencer object */
+
+/*
+ * Open sequencer
+ *
+ * param [in] type : Sequencer type. Set one of the following definitions.
+ * - #SEQ_TYPE_NORMAL
+ * - #SEQ_TYPE_DECI
+ * param [in] bustype : Bustype. Set one of the foollowing definitions.
+ * - #SCU_BUS_I2C0
+ * - #SCU_BUS_I2C1
+ * - #SCU_BUS_SPI
+ *
+ * return: struct seq_s pointer is success. NULL is failure.
+ */
+
+FAR struct seq_s *seq_open(int type, int bustype);
+
+/*
+ * Close sequencer device
+ *
+ * param [in] seq : Sequencer instance
+ */
+
+void seq_close(FAR struct seq_s *seq);
+
+/*
+ * Read sequencer FIFO data
+ *
+ * param [in] seq : Sequencer instance
+ * param [in] fifoid : FIFO ID (decimator only)
+ * param [out] buffer : Pointer to data receive buffer
+ * param [in] length : Buffer length
+ *
+ * return : OK(0) is success. negative value is failure.
+ */
+
+int seq_read(FAR struct seq_s *seq, int fifoid, char *buffer, int length);
+
+/*
+ * Sequencer specific ioctl
+ *
+ * This API should be called from each sensor driver ioctl().
+ *
+ * param [in] seq : Sequencer instance
+ * param [in] fifoid : FIFO ID (decimator only)
+ * param [in] cmd : ioctl commands (SCUIOC_*).
+ * param [in,out] arg : Argument for each commands
+ *
+ * see #scu_ioctl
+ *
+ * return: OK(0) is success. negative value is failure.
+ */
+
+int seq_ioctl(FAR struct seq_s *seq, int fifoid, int cmd, unsigned long arg);
+
+/*
+ * Set cyclic sequencer instruction
+ *
+ * param [in] seq : Sequencer instance
+ * param [in] inst : Pointer to instruction array
+ * param [in] nr_insts : Number of instructions
+ *
+ * return OK(0) is success. negative value is failure.
+ */
+
+int seq_setinstruction(FAR struct seq_s *seq, const uint16_t *inst,
+ uint16_t nr_insts);
+
+/*
+ * Set sample data format
+ *
+ * param [in] seq : Sequencer instance
+ * param [in] sample : Bytes per sample
+ * param [in] offset : Start offset of sampling data
+ * param [in] elemsize : Bytes of 1 element in sample
+ * param [in] swapbyte : Enable/Disable byte swapping
+ *
+ * return OK(0) is success. negative value is failure.
+ */
+
+void seq_setsample(FAR struct seq_s *seq, uint8_t sample, uint8_t offset,
+ uint8_t elemsize, bool swapbyte);
+
+/*
+ * Set slave ID or address
+ *
+ * param [in] seq : An instance of sequencer
+ * param [in] slave_addr : In SPI, slave select ID. In I2C, bus address.
+ */
+
+void seq_setaddress(FAR struct seq_s *seq, uint32_t slave_addr);
+
+/*
+ * SPI data transfer via sequencer.
+ *
+ * This function use 'oneshot' feature on SCU. So user unnecessary to specify
+ * any opened sequencer.
+ * This function usefull for accessing register directly.
+ *
+ * param [in] slavesel : Slave select
+ * param [in] inst : Sequencer instruction
+ * param [in] nr_insts : Number of instructions
+ * param [out] buffer : Pointer to receive buffer, if no need to receive,
+ * then NULL.
+ * param [in] len : buffer length (ignored when buffer is NULL)
+ *
+ * return OK(0) is success. negative value is failure.
+ */
+
+int scu_spitransfer(int slavesel, uint16_t *inst, uint32_t nr_insts,
+ uint8_t *buffer, int len);
+
+/*
+ * I2C data transfer via sequencer
+ *
+ * This function use 'oneshot' feature on SCU. So user unnecessary to
+ * specify any opened sequencer.
+ * This function usefull for accessing register directly.
+ *
+ * param [in] port : I2C port (0 or 1)
+ * param [in] slave : Slave address
+ * param [in] inst : Sequencer instruction
+ * param [in] nr_insts : Number of instructions
+ * param [out] buffer : Pointer to receive buffer, if no need to receive,
+ * then NULL.
+ * param [in] len : buffer length (ignored when buffer is NULL)
+ *
+ * return OK(0) is success. negative value is failure.
+ */
+
+int scu_i2ctransfer(int port, int slave, uint16_t *inst, uint32_t nr_insts,
+ uint8_t *buffer, int len);
+
+/*
+ * Initialize SCU
+ *
+ * warning: This API called from board_app_initialize().
+ * Do not call this API from each sensor drivers.
+ */
+
+void scu_initialize(void);
+
+/*
+ * Uninitialize SCU
+ *
+ * warning: This API called from board_app_initialize().
+ * Do not call this API from each sensor drivers.
+ */
+
+void scu_uninitialize(void);
+
+#endif /* __ARCH_ARM_INCLUDE_CXD56XX_SCU_H */
diff --git a/arch/arm/include/cxd56xx/timer.h b/arch/arm/include/cxd56xx/timer.h
new file mode 100644
index 00000000000..5a33ea18e90
--- /dev/null
+++ b/arch/arm/include/cxd56xx/timer.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+ * arch/arm/include/cxd56xx/timer.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_INCLUDE_CXD56XX_TIMER_H
+#define __ARCH_ARM_INCLUDE_CXD56XX_TIMER_H
+
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/*
+ * Set callback handler
+ *
+ * param A pointer to struct timer_sethandler_s
+ * return ioctl return value provides success/failure indication
+ */
+
+#define TCIOC_SETHANDLER _TCIOC(0x0020)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* This is the type of the argument passed to the TCIOC_SETHANDLER ioctl */
+
+struct timer_sethandler_s
+{
+ FAR void *arg; /* An argument */
+ CODE tccb_t handler; /* The timer interrupt handler */
+};
+
+#endif /* __ARCH_ARM_INCLUDE_CXD56XX_TIMER_H */
diff --git a/arch/arm/src/am335x/Kconfig b/arch/arm/src/am335x/Kconfig
index dea00146f61..43c2de66537 100644
--- a/arch/arm/src/am335x/Kconfig
+++ b/arch/arm/src/am335x/Kconfig
@@ -94,16 +94,18 @@ config AM335X_GPIO
bool "GPIO"
default n
+config AM335X_LCDC
+ bool "LCD controller"
+ default n
+ depends on VIDEO && EXPERIMENTAL
+ select VIDEO_EDID
+
config AM335X_TSC
bool "Touchscreen Controller"
default n
-config AM335X_LCDC
- bool "LCD Controller"
- default n
-
config AM335X_CPSW
- bool "Ethernet subsustem"
+ bool "Ethernet subsystem"
default n
config AM335X_PWMSS
@@ -134,11 +136,11 @@ config AM335X_I2C0
bool "Multi-master I2C Controller 0"
default n
-config AM335X_I2C0
+config AM335X_I2C1
bool "Multi-master I2C Controller 1"
default n
-config AM335X_I2C0
+config AM335X_I2C2
bool "Multi-master I2C Controller 2"
default n
@@ -248,4 +250,135 @@ config AM335X_DDR_MAPSIZE
plus the size of the available heap. NOTE that RAM_SIZE may not
include all of SDRAM up to the end of mapped region.
+menu "LCD Configuration"
+ depends on AM335X_LCDC
+
+config AM335X_LCDC_FB_VBASE
+ hex "Video RAM base address (virtual)"
+ default 0x80000000
+ ---help---
+ Base address of the video RAM frame buffer. The default of 0x80000000
+ assumes that the framebuffer lies at the beginning of DRAM and that
+ a 1-to-1 virtual-to-physical address mapping is used.
+
+config AM335X_LCDC_FB_PBASE
+ hex "Video RAM base address (physical)"
+ default 0x80000000
+ ---help---
+ Base address of the video RAM frame buffer. The default of 0x80000000
+ assumes that the framebuffer lies at the beginning of DRAM.
+
+config AM335X_LCDC_FB_SIZE
+ hex "Video RAM base size"
+ default 0x00100000
+ ---help---
+ Size of the video RAM frame buffer. Default: 1Mb.
+
+config AM335X_LCDC_USE_CLKIN
+ bool "Use optional input clock"
+ default n
+
+config AM335X_LCDC_CLKIN_FREQUENCY
+ int "Input clock frequency"
+ default 0
+ depends on AM335X_LCDC_USE_CLKIN
+
+config AM335X_LCDC_REFRESH_FREQ
+ int "LCD refesh rate (Hz)"
+ default 50
+ ---help---
+ LCD refesh rate (Hz)
+
+choice
+ prompt "Bits per pixel"
+ default AM335X_LCDC_BPP16_565
+
+config AM335X_LCDC_BPP1
+ bool "1 BPP"
+
+config AM335X_LCDC_BPP2
+ bool "2 BPP"
+
+config AM335X_LCDC_BPP4
+ bool "4 BPP"
+
+config AM335X_LCDC_BPP8
+ bool "8 BPP"
+
+config AM335X_LCDC_BPP12_444
+ bool "12 bpp, 4:4:4 mode"
+
+config AM335X_LCDC_BPP16_565
+ bool "16 BPP, 5:6:5 mode"
+
+config AM335X_LCDC_BPP24
+ bool "24 BPP, 8:8:8 mode (packed)"
+
+config AM335X_LCDC_BPP32
+ bool "32 BPP, 8:8:8 mode (unpacked)"
+
+endchoice
+
+config AM335X_LCDC_BGR
+ bool "Blue-Green-Red color order"
+ default n
+ depends on !AM335X_LCDC_MONOCHROME
+ ---help---
+ This option selects BGR color order vs. default RGB
+
+config AM335X_LCDC_BACKCOLOR
+ hex "Initial background color"
+ default 0x0
+ ---help---
+ Initial background color
+
+config AM335X_LCDC_ACBIAS
+ int "AC bias pin frequency"
+ default 255
+ range 0 255
+
+config AM335X_LCDC_ACBIAS_PINT
+ int "AC bias pin transitions per interrupt"
+ default 0
+ range 0 15
+
+choice
+ prompt "DMA burst size"
+ default AM335X_LCDC_DMA_BURST16
+
+config AM335X_LCDC_DMA_BURST1
+ bool "1"
+
+config AM335X_LCDC_DMA_BURST2
+ bool "2"
+
+config AM335X_LCDC_DMA_BURST4
+ bool "4"
+
+config AM335X_LCDC_DMA_BURST8
+ bool "8"
+
+config AM335X_LCDC_DMA_BURST16
+ bool "16"
+
+endchoice
+
+config AM335X_LCDC_FDD
+ int "Palette loading delay"
+ default 128
+ range 0 255
+
+config AM335X_LCDC_SYNC_EDGE
+ bool "HSYNC/VSYNC rise or fall"
+ default n
+
+config AM335X_LCDC_SYNC_CTRL
+ bool "Hsync/Vsync pixel clock control on/off"
+ default y
+
+config AM335X_LCDC_PIXCLK_INVERT
+ bool "Invert pixel clock"
+ default y
+
+endmenu # LCD Configuration
endif # ARCH_CHIP_AM335X
diff --git a/arch/arm/src/am335x/Make.defs b/arch/arm/src/am335x/Make.defs
index 65cff8e6982..e3032d691cc 100644
--- a/arch/arm/src/am335x/Make.defs
+++ b/arch/arm/src/am335x/Make.defs
@@ -126,6 +126,7 @@ CHIP_ASRCS =
CHIP_CSRCS = am335x_boot.c am335x_clockconfig.c am335x_pinmux.c am335x_irq.c
CHIP_CSRCS += am335x_gpio.c am335x_lowputc.c am335x_serial.c am335x_wdog.c
+CHIP_CSRCS += am335x_sysclk.c
ifneq ($(CONFIG_SCHED_TICKLESS),y)
CHIP_CSRCS += am335x_timerisr.c
@@ -133,4 +134,8 @@ endif
ifeq ($(CONFIG_AM335X_GPIO_IRQ),y)
CHIP_CSRCS += am335x_gpioirq.c
-endif
\ No newline at end of file
+endif
+
+ifeq ($(CONFIG_AM335X_LCDC),y)
+CHIP_CSRCS += am335x_lcdc.c am335x_edid.c
+endif
diff --git a/arch/arm/src/am335x/am335x_boot.c b/arch/arm/src/am335x/am335x_boot.c
index a948bd1ebd7..14e5159b37e 100644
--- a/arch/arm/src/am335x/am335x_boot.c
+++ b/arch/arm/src/am335x/am335x_boot.c
@@ -66,6 +66,13 @@
* Pre-processor Definitions
****************************************************************************/
+/* If the LCDC is enabled, then this will provide the number of sections
+ * to map for the framebuffer.
+ */
+
+#define AM335X_LCDC_FBNSECTIONS \
+ ((CONFIG_AM335X_LCDC_FB_SIZE + 0x000fffff) >> 20)
+
/****************************************************************************
* Name: showprogress
*
@@ -105,9 +112,8 @@
extern uint32_t _vector_start; /* Beginning of vector block */
extern uint32_t _vector_end; /* End+1 of vector block */
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
+#define SAMA5_LCDC_FBNSECTIONS \
+ ((CONFIG_SAMA5_LCDC_FB_SIZE + 0x000fffff) >> 20)
/****************************************************************************
* Private Data
@@ -120,32 +126,55 @@ extern uint32_t _vector_end; /* End+1 of vector block */
#ifndef CONFIG_ARCH_ROMPGTABLE
static const struct section_mapping_s g_section_mapping[] =
{
- { AM335X_GPMC_PSECTION, AM335X_GPMC_VSECTION, /* Includes vectors and page table */
+ {
+ AM335X_GPMC_PSECTION, AM335X_GPMC_VSECTION, /* Includes vectors and page table */
AM335X_GPMC_MMUFLAGS, AM335X_GPMC_NSECTIONS
},
- { AM335X_BROM_PSECTION, AM335X_BROM_VSECTION,
+ {
+ AM335X_BROM_PSECTION, AM335X_BROM_VSECTION,
AM335X_BROM_MMUFLAGS, AM335X_BROM_NSECTIONS
},
- { AM335X_ISRAM_PSECTION, AM335X_ISRAM_VSECTION,
+ {
+ AM335X_ISRAM_PSECTION, AM335X_ISRAM_VSECTION,
AM335X_ISRAM_MMUFLAGS, AM335X_ISRAM_NSECTIONS
},
- { AM335X_OCMC0_PSECTION, AM335X_OCMC0_VSECTION,
+ {
+ AM335X_OCMC0_PSECTION, AM335X_OCMC0_VSECTION,
AM335X_OCMC0_MMUFLAGS, AM335X_OCMC0_NSECTIONS
},
- { AM335X_PERIPH_PSECTION, AM335X_PERIPH_VSECTION,
+ {
+ AM335X_PERIPH_PSECTION, AM335X_PERIPH_VSECTION,
AM335X_PERIPH_MMUFLAGS, AM335X_PERIPH_NSECTIONS
},
- { AM335X_DDR_PSECTION, AM335X_DDR_VSECTION,
+ {
+ AM335X_DDR_PSECTION, AM335X_DDR_VSECTION,
AM335X_DDR_MMUFLAGS, AM335X_DDR_NSECTIONS
}
+
+#ifdef CONFIG_AM335X_LCDC
+ ,
+
+ /* LCDC Framebuffer. This entry reprograms a part of one of the above
+ * regions, making it non-cache-able and non-buffer-able.
+ */
+
+ {
+ CONFIG_AM335X_LCDC_FB_PBASE, CONFIG_AM335X_LCDC_FB_VBASE,
+ MMU_IOFLAGS, AM335X_LCDC_FBNSECTIONS
+ }
+#endif
};
#define NMAPPINGS \
(sizeof(g_section_mapping) / sizeof(struct section_mapping_s))
-const size_t g_num_mappings = NMAPPINGS;
+static const size_t g_num_mappings = NMAPPINGS;
#endif
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
/****************************************************************************
* Name: am335x_setupmappings
*
diff --git a/arch/arm/src/am335x/am335x_clockconfig.c b/arch/arm/src/am335x/am335x_clockconfig.c
index e719561c153..50e8a8b7f80 100644
--- a/arch/arm/src/am335x/am335x_clockconfig.c
+++ b/arch/arm/src/am335x/am335x_clockconfig.c
@@ -40,13 +40,39 @@
#include
#include "up_arch.h"
-#if 0
-/* TODO: add clock register module */
-#include "hardware/am335x_ccm.h"
-#endif
+#include "hardware/am335x_cm.h"
#include "am335x_config.h"
#include "am335x_clockconfig.h"
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: am335x_dmtimer1ms_clockconfig
+ ****************************************************************************/
+
+static inline void am335x_dmtimer1ms_clockconfig(void)
+{
+ putreg32(CM_DPLL_DMTIMER1_CLKSEL_CLK_M_OSC,
+ AM335X_CM_DPLL_CLKSEL_TIMER1MS_CLK);
+
+ while ((getreg32(AM335X_CM_DPLL_CLKSEL_TIMER1MS_CLK) &
+ CM_DPLL_DMTIMER1MS_CLKSEL_MASK)
+ != CM_DPLL_DMTIMER1_CLKSEL_CLK_M_OSC)
+ {
+ }
+
+ modifyreg32(AM335X_CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_CLKCTRL_MODULEMODE_MASK,
+ CM_WKUP_CLKCTRL_MODULEMODE_ENABLE);
+
+ while ((getreg32(AM335X_CM_WKUP_TIMER1_CLKCTRL) &
+ (CM_WKUP_CLKCTRL_MODULEMODE_MASK | CM_WKUP_CLKCTRL_IDLEST_MASK))
+ != (CM_WKUP_CLKCTRL_MODULEMODE_ENABLE | CM_WKUP_CLKCTRL_IDLEST_FUNC))
+ {
+ }
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -75,6 +101,8 @@ void am335x_clockconfig(void)
* 792MHz.
*/
+ am335x_dmtimer1ms_clockconfig();
+
#ifndef CONFIG_AM335X_BOOT_SDRAM
# warning Missing logic
#endif
diff --git a/arch/arm/src/am335x/am335x_edid.c b/arch/arm/src/am335x/am335x_edid.c
new file mode 100644
index 00000000000..1d5aed8d177
--- /dev/null
+++ b/arch/arm/src/am335x/am335x_edid.c
@@ -0,0 +1,397 @@
+/****************************************************************************
+ * arch/arm/src/am335x/am335x_wdog.c
+ *
+ * Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt
+ *
+ * The LCD driver derives from the LPC54xx LCD driver but also includes
+ * information from the FreeBSD AM335x LCD driver which was released under
+ * a two-clause BSD license:
+ *
+ * Copyright 2013 Oleksandr Tymoshenko
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include "am335x_lcdc.h"
+
+/****************************************************************************
+ * Pre-processor definitions Functions
+ ****************************************************************************/
+
+#define MODE_HBP(mode) ((mode)->htotal - (mode)->hsync_end)
+#define MODE_HFP(mode) ((mode)->hsync_start - (mode)->hdisplay)
+#define MODE_HSW(mode) ((mode)->hsync_end - (mode)->hsync_start)
+#define MODE_VBP(mode) ((mode)->vtotal - (mode)->vsync_end)
+#define MODE_VFP(mode) ((mode)->vsync_start - (mode)->vdisplay)
+#define MODE_VSW(mode) ((mode)->vsync_end - (mode)->vsync_start)
+
+#define MAX_PIXEL_CLOCK 126000
+#define MAX_BANDWIDTH (1280*1024*60)
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: am335x_lcd_edid
+ *
+ * Description:
+ * Return the vertical refresh rate for this video mode.
+ *
+ ****************************************************************************/
+
+static uint32_t
+ am335x_videomode_vrefresh(FAR const struct edid_videomode_s *videomode)
+{
+ uint32_t refresh;
+
+ /* Calculate vertical refresh rate */
+
+ refresh = (videomode->dotclock * 1000 / videomode->htotal);
+ refresh = (refresh + videomode->vtotal / 2) / videomode->vtotal;
+
+ if (videomode->flags & VID_INTERLACE)
+ {
+ refresh *= 2;
+ }
+
+ if (videomode->flags & VID_DBLSCAN)
+ {
+ refresh /= 2;
+ }
+
+ return refresh;
+}
+
+/****************************************************************************
+ * Name: am335x_videomode_valid
+ *
+ * Description:
+ * Return true if the provided video mode is valid.
+ *
+ ****************************************************************************/
+
+static bool
+ am335x_videomode_valid(FAR const struct edid_videomode_s *videomode)
+{
+ size_t fbstride;
+ size_t fbsize;
+ uint32_t hbp;
+ uint32_t hfp;
+ uint32_t hsw;
+ uint32_t vbp;
+ uint32_t vfp;
+ uint32_t vsw;
+ uint32_t vrefresh;
+
+ if (videomode->dotclock > MAX_PIXEL_CLOCK)
+ {
+ return false;
+ }
+
+ if (videomode->hdisplay & 0xf)
+ {
+ return false;
+ }
+
+ if (videomode->vdisplay > 2048)
+ {
+ return false;
+ }
+
+ /* Check ranges for timing parameters */
+
+ hbp = MODE_HBP(videomode) - 1;
+ hfp = MODE_HFP(videomode) - 1;
+ hsw = MODE_HSW(videomode) - 1;
+ vbp = MODE_VBP(videomode);
+ vfp = MODE_VFP(videomode);
+ vsw = MODE_VSW(videomode) - 1;
+
+ if (hbp > 0x3ff)
+ {
+ return false;
+ }
+
+ if (hfp > 0x3ff)
+ {
+ return false;
+ }
+
+ if (hsw > 0x3ff)
+ {
+ return false;
+ }
+
+ if (vbp > 0xff)
+ {
+ return false;
+ }
+
+ if (vfp > 0xff)
+ {
+ return false;
+ }
+
+ if (vsw > 0x3f)
+ {
+ return false;
+ }
+
+ vrefresh = am335x_videomode_vrefresh(videomode);
+ if (videomode->vdisplay * videomode->hdisplay * vrefresh > MAX_BANDWIDTH)
+ {
+ return false;
+ }
+
+ /* Finally, make sure that the framebuffer buffer region is large enough
+ * to support this video mode.
+ */
+
+ fbstride = (videomode->hdisplay * AM335X_BPP + 7) >> 3;
+ fbsize = videomode->vdisplay * fbstride;
+
+ if (fbsize > AM335X_LCDC_FB_SIZE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************************
+ * Name: am335x_lcd_pickmode
+ *
+ * Description:
+ * If there is access to Extended Display Identification Data (EDIDI),
+ * then the board-specific logic may read the EDID data and use this
+ * function to select an appropriate video mode.
+ *
+ * edid_parse() should be used to convert the raw EDID data into the
+ * digested form of struct edid_info.
+ *
+ * The returned video mode may be used to both (1) configure HDMI and (2)
+ * initialize the AM335x LCD controller.
+ *
+ ****************************************************************************/
+
+static const struct edid_videomode_s *
+ am335x_lcd_pickmode(FAR struct edid_info_s *ei)
+{
+ FAR const struct edid_videomode_s *videomode;
+ int n;
+
+ /* Get standard VGA as default */
+
+ videomode = NULL;
+
+ /* Pick a video mode -- First check if we can support the preferred mode. */
+
+ if (ei->edid_preferred_mode != NULL)
+ {
+ if (am335x_videomode_valid(ei->edid_preferred_mode))
+ {
+ videomode = ei->edid_preferred_mode;
+ return videomode;
+ }
+ }
+
+ /* Sort video modes by refresh rate, aspect ratio (*), then resolution.
+ * Preferred mode or largest mode is first in the list and other modes
+ * are sorted on closest match to that mode.
+ */
+
+ edid_sort_modes(ei->edid_modes, &ei->edid_preferred_mode, ei->edid_nmodes);
+
+ /* Pick the first valid mode in the list */
+
+ for (n = 0; n < ei->edid_nmodes; n++)
+ {
+ if (am335x_videomode_valid(&ei->edid_modes[n]))
+ {
+ videomode = &ei->edid_modes[n];
+ break;
+ }
+ }
+
+ return videomode;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: am335x_lcd_videomode
+ *
+ * Description:
+ * If the video mod is known, then the board-specific logic may read the
+ * use this function to convert the video mode data to an instance of
+ * struct am335x_panel_info_s which then may be used to initialize the
+ * the LCD/
+ *
+ * Input Parameters:
+ * videomode - A reference to the desired video mode.
+ * panel - A user provided location to receive the panel data.
+ *
+ * Returned value:
+ * None. Always succeeds.
+ *
+ ****************************************************************************/
+
+void am335x_lcd_videomode(FAR const struct edid_videomode_s *videomode,
+ FAR struct am335x_panel_info_s *panel)
+{
+ lcdinfo("Detected videomode: %dx%d @ %dKHz\n",
+ videomode->hdisplay, videomode->vdisplay,
+ am335x_videomode_vrefresh(videomode));
+
+ panel->width = videomode->hdisplay;
+ panel->height = videomode->vdisplay;
+ panel->hfp = videomode->hsync_start - videomode->hdisplay;
+ panel->hbp = videomode->htotal - videomode->hsync_end;
+ panel->hsw = videomode->hsync_end - videomode->hsync_start;
+ panel->vfp = videomode->vsync_start - videomode->vdisplay;
+ panel->vbp = videomode->vtotal - videomode->vsync_end;
+ panel->vsw = videomode->vsync_end - videomode->vsync_start;
+ panel->pixelclk_active = true;
+
+ /* Logic for HSYNC should be reversed */
+
+ panel->hsync_active = ((videomode->flags & VID_NHSYNC) != 0);
+ panel->vsync_active = ((videomode->flags & VID_NVSYNC) == 0);
+ panel->pixclk = videomode->dotclock * 1000;
+
+ /* Set other values to the default */
+
+#ifdef CONFIG_AM335X_LCDC_SYNC_EDGE
+ panel->sync_edge = true;
+#else
+ panel->sync_edge = false;
+#endif
+
+#ifdef CONFIG_AM335X_LCDC_SYNC_CTRL
+ panel->sync_ctrl = true;
+#else
+ panel->sync_ctrl = false;
+#endif
+
+#ifdef CONFIG_AM335X_LCDC_PIXCLK_INVERT
+ panel->pixelclk_active = true;
+#else
+ panel->pixelclk_active = false;
+#endif
+
+ panel->acbias = CONFIG_AM335X_LCDC_ACBIAS;
+ panel->acbias_pint = CONFIG_AM335X_LCDC_ACBIAS_PINT;
+ panel->dma_burstsz = AM335X_LCD_DMA_BURSTSZ;
+ panel->bpp = AM335X_BPP; /* REVISIT */
+ panel->fdd = CONFIG_AM335X_LCDC_FDD;
+}
+
+/****************************************************************************
+ * Name: am335x_lcd_edid
+ *
+ * Description:
+ * If there is access to Extended Display Identification Data (EDID),
+ * then the board-specific logic may read the EDID data and use this
+ * function to initialize an instance of struct am335x_panel_info_s.
+ *
+ * The returned video mode may optionally be returned to configure HDMI.
+ *
+ * Input Parameters:
+ * edid - A reference to the raw EDID data.
+ * len - The length of the EDID data in bytes
+ * panel - A user provided location to receive the panel data.
+ * selected - A user provided location to receive the selected video mode.
+ *
+ * Returned value:
+ * None. Always succeeds. The logic will fallback to VGA mode if no
+ * EDID data is provided or if there is no valid video mode in the EDID
+ * data.
+ *
+ ****************************************************************************/
+
+void am335x_lcd_edid(FAR const uint8_t *edid, size_t edid_len,
+ FAR struct am335x_panel_info_s *panel,
+ FAR struct edid_videomode_s *selected)
+{
+ FAR const struct edid_videomode_s *videomode = NULL;
+ struct edid_info_s ei;
+
+ /* Do we have EDID data? */
+
+ if (edid != NULL && edid_len > 0)
+ {
+ /* Parse the EDID data */
+
+ if (edid_parse(edid, &ei) == 0)
+ {
+ videomode = am335x_lcd_pickmode(&ei);
+ }
+ else
+ {
+ lcderr("ERROR: Failed to parse EDID\n");
+ }
+ }
+
+ /* Use standard VGA as fallback */
+
+ if (videomode == NULL)
+ {
+ videomode = edid_mode_lookup("640x480x60");
+ DEBUGASSERT(videomode != NULL);
+ }
+
+ /* Initialize the LCD using the selected video mode */
+
+ am335x_lcd_videomode(videomode, panel);
+
+ /* Return the selected video mode */
+
+ if (selected != NULL)
+ {
+ memcpy(selected, videomode, sizeof(struct edid_videomode_s));
+ }
+}
diff --git a/arch/arm/src/am335x/am335x_lcdc.c b/arch/arm/src/am335x/am335x_lcdc.c
new file mode 100644
index 00000000000..f629ed932ad
--- /dev/null
+++ b/arch/arm/src/am335x/am335x_lcdc.c
@@ -0,0 +1,948 @@
+/****************************************************************************
+ * arch/arm/src/am225x/am335x_lcd.c
+ *
+ * Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt
+ *
+ * This driver derives from the LPC54xx LCD driver but also includes
+ * information from the FreeBSD AM335x LCD driver which was released under
+ * a two-clause BSD license:
+ *
+ * Copyright 2013 Oleksandr Tymoshenko
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "up_arch.h"
+#include "hardware/am335x_cm.h"
+#include "am335x_pinmux.h"
+#include "am335x_config.h"
+#include "am335x_gpio.h"
+#include "am335x_sysclk.h"
+#include "am335x_lcdc.h"
+
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DPLL_MAX_MUL 0x800
+#define DPLL_MAX_DIV 0x80
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Get information about the video controller configuration and the
+ * configuration of each color plane.
+ */
+
+static int am335x_getvideoinfo(FAR struct fb_vtable_s *vtable,
+ FAR struct fb_videoinfo_s *vinfo);
+static int am335x_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
+ FAR struct fb_planeinfo_s *pinfo);
+
+/* The following is provided only if the video hardware supports RGB color
+ * mapping
+ */
+
+#ifdef CONFIG_FB_CMAP
+static int am335x_getcmap(FAR struct fb_vtable_s *vtable,
+ FAR struct fb_cmap_s *cmap);
+static int am335x_putcmap(FAR struct fb_vtable_s *vtable,
+ FAR const struct fb_cmap_s *cmap);
+#endif
+
+/* The following is provided only if the video hardware supports a hardware
+ * cursor
+ */
+
+#ifdef CONFIG_FB_HWCURSOR
+static int am335x_getcursor(FAR struct fb_vtable_s *vtable,
+ FAR struct fb_cursorattrib_s *attrib);
+static int am335x_setcursor(FAR struct fb_vtable_s *vtable,
+ FAR struct fb_setcursor_s *settings);
+#endif
+
+/* Miscellaneous internal functions */
+
+static int am335x_lcd_interrupt(int irq, void *context, void *arg);
+static uint32_t am335x_lcd_divisor(uint32_t reference, uint32_t frequency);
+static int am335x_set_refclk(uint32_t frequency);
+static int am335x_get_refclk(uint32_t *frequency);
+static int am335x_lcdc_enableclk(void);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* The framebuffer object -- There is no private state information in this
+ * framebuffer driver.
+ */
+
+struct fb_vtable_s g_fbinterface =
+{
+ .getvideoinfo = am335x_getvideoinfo,
+ .getplaneinfo = am335x_getplaneinfo,
+#ifdef CONFIG_FB_CMAP
+ .getcmap = am335x_getcmap,
+ .putcmap = am335x_putcmap,
+#endif
+#ifdef CONFIG_FB_HWCURSOR
+ .getcursor = am335x_getcursor,
+ .setcursor = am335x_setcursor,
+#endif
+};
+
+struct am335x_lcd_dev_s
+{
+ /* Saved panel configuration */
+
+ struct am335x_panel_info_s panel;
+
+ sem_t exclsem; /* Assure mutually exclusive access */
+ nxgl_coord_t stride; /* Width of framebuffer in bytes */
+ size_t fbsize; /* Size of the framebuffer allocation */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Since there is only a single LCD controller, its state structure can be
+ * allocated in .bss.
+ */
+
+static struct am335x_lcd_dev_s g_lcddev;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: am335x_getvideoinfo
+ ****************************************************************************/
+
+static int am335x_getvideoinfo(FAR struct fb_vtable_s *vtable,
+ FAR struct fb_videoinfo_s *vinfo)
+{
+ struct am335x_lcd_dev_s *priv = &g_lcddev;
+
+ lcdinfo("vtable=%p vinfo=%p\n", vtable, vinfo);
+ if (vtable && vinfo)
+ {
+ vinfo->fmt = AM335X_COLOR_FMT; /* REVISIT */
+ vinfo->xres = priv->panel.width;
+ vinfo->yres = priv->panel.height;
+ vinfo->nplanes = 1;
+#ifdef CONFIG_FB_OVERLAY
+ vinfo->noverlays = 0;
+#endif
+ return OK;
+ }
+
+ lcderr("ERROR: Returning EINVAL\n");
+ return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: am335x_getplaneinfo
+ ****************************************************************************/
+
+static int am335x_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
+ FAR struct fb_planeinfo_s *pinfo)
+{
+ struct am335x_lcd_dev_s *priv = &g_lcddev;
+
+ lcdinfo("vtable=%p planeno=%d pinfo=%p\n", vtable, planeno, pinfo);
+
+ if (vtable != NULL && planeno == 0 && pinfo != NULL)
+ {
+#ifdef CONFIG_BUILD_KERNEL
+ pinfo->fbmem = (FAR void *)CONFIG_AM335X_LCDC_FB_PBASE;
+#else
+ pinfo->fbmem = (FAR void *)CONFIG_AM335X_LCDC_FB_VBASE;
+#endif
+ pinfo->fblen = priv->fbsize;
+ pinfo->stride = priv->stride;
+ pinfo->display = 0;
+ pinfo->bpp = priv->panel.bpp;
+ return OK;
+ }
+
+ lcderr("ERROR: Returning EINVAL\n");
+ return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: am335x_getcmap
+ ****************************************************************************/
+
+#ifdef CONFIG_FB_CMAP
+static int am335x_getcmap(FAR struct fb_vtable_s *vtable,
+ FAR struct fb_cmap_s *cmap)
+{
+ return -ENOSYS;
+}
+#endif
+
+/****************************************************************************
+ * Name: am335x_putcmap
+ ****************************************************************************/
+
+#ifdef CONFIG_FB_CMAP
+static int am335x_putcmap(FAR struct fb_vtable_s *vtable,
+ FAR const struct fb_cmap_s *cmap)
+{
+ return -ENOSYS;
+}
+#endif
+
+/****************************************************************************
+ * Name: am335x_getcursor
+ ****************************************************************************/
+
+#ifdef CONFIG_FB_HWCURSOR
+static int am335x_getcursor(FAR struct fb_vtable_s *vtable,
+ FAR struct fb_cursorattrib_s *attrib)
+{
+ lcdinfo("vtable=%p attrib=%p\n", vtable, attrib);
+ return -ENOSYS;
+}
+#endif
+
+/****************************************************************************
+ * Name: am335x_setcursor
+ ****************************************************************************/
+
+#ifdef CONFIG_FB_HWCURSOR
+static int am335x_setcursor(FAR struct fb_vtable_s *vtable,
+ FAR struct fb_setcursor_s *settings)
+{
+ lcdinfo("vtable=%p settings=%p\n", vtable, settings);
+ return -ENOSYS;
+}
+#endif
+
+/****************************************************************************
+ * Name: am335x_lcd_interrupt
+ ****************************************************************************/
+
+static int am335x_lcd_interrupt(int irq, void *context, void *arg)
+{
+ struct am335x_lcd_dev_s *priv = (struct am335x_lcd_dev_s *)arg;
+ uint32_t regval;
+
+ regval = getreg32(AM335X_LCD_IRQ_STAT);
+ putreg32(AM335X_LCD_IRQ_STAT, regval);
+
+ /* Read value back to make sure it reached the hardware */
+
+ regval = getreg32(AM335X_LCD_IRQ_STAT);
+ if ((regval & LCD_IRQ_SYNC) != 0 || (regval & LCD_IRQ_PL) != 0)
+ {
+ regval = getreg32(AM335X_LCD_RASTER_CTRL);
+ regval &= ~LCD_RASTER_CTRL_LCD_EN;
+ putreg32(AM335X_LCD_RASTER_CTRL, regval);
+
+ regval = getreg32(AM335X_LCD_RASTER_CTRL);
+ regval |= LCD_RASTER_CTRL_LCD_EN;
+ putreg32(AM335X_LCD_RASTER_CTRL, regval);
+ goto done;
+ }
+
+ if ((regval & LCD_IRQ_EOF0) != 0)
+ {
+ putreg32(AM335X_LCD_DMA_FB0_BASE, CONFIG_AM335X_LCDC_FB_PBASE);
+ putreg32(AM335X_LCD_DMA_FB0_CEIL,
+ CONFIG_AM335X_LCDC_FB_PBASE + priv->fbsize - 1);
+ regval &= ~LCD_IRQ_EOF0;
+ }
+
+ if ((regval & LCD_IRQ_EOF1) != 0)
+ {
+ putreg32(AM335X_LCD_DMA_FB1_BASE, CONFIG_AM335X_LCDC_FB_PBASE);
+ putreg32(AM335X_LCD_DMA_FB1_CEIL,
+ CONFIG_AM335X_LCDC_FB_PBASE + priv->fbsize - 1);
+ regval &= ~LCD_IRQ_EOF1;
+ }
+
+ if ((regval & LCD_IRQ_FUF) != 0)
+ {
+ /* TODO: Handle FUF */
+
+ regval &= ~LCD_IRQ_FUF;
+ }
+
+ if ((regval & LCD_IRQ_ACB) != 0)
+ {
+ /* TODO: Handle ACB */
+
+ regval &= ~LCD_IRQ_ACB;
+ }
+
+done:
+ putreg32(AM335X_LCD_END_INT, 0);
+
+ /* Read value back to make sure it reached the hardware */
+
+ regval = getreg32(AM335X_LCD_END_INT);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: am335x_lcd_divisor
+ ****************************************************************************/
+
+static uint32_t am335x_lcd_divisor(uint32_t reference, uint32_t frequency)
+{
+ uint32_t div;
+ uint32_t delta;
+ uint32_t mindelta;
+ int i;
+
+ mindelta = frequency;
+ div = 255;
+
+ /* Raster mode case: divisors are in range from 2 to 255 */
+
+ for (i = 2; i < 255; i++)
+ {
+ delta = reference / i - frequency;
+ if (delta < 0)
+ {
+ delta = -delta;
+ }
+
+ if (delta < mindelta)
+ {
+ div = i;
+ mindelta = delta;
+ }
+ }
+
+ return div;
+}
+
+/****************************************************************************
+ * Name: am335x_set_refclk
+ ****************************************************************************/
+
+static int am335x_set_refclk(uint32_t frequency)
+{
+ uint32_t sysclk;
+ uint32_t mul;
+ uint32_t div;
+ uint32_t delta;
+ uint32_t mindelta;
+ int timeout;
+ int i;
+ int j;
+
+ sysclk = am335x_get_sysclk();
+
+ /* Bypass mode */
+
+ putreg32(AM335X_CM_WKUP_CLKMODE_DPLL_DISP, 0x4);
+
+ /* Make sure it's in bypass mode */
+
+ while ((getreg32(AM335X_CM_WKUP_IDLEST_DPLL_DISP) & (1 << 8)) == 0)
+ {
+ up_udelay(10);
+ }
+
+ /* Dumb and non-optimal implementation */
+
+ mul = 0;
+ div = 0;
+ mindelta = frequency;
+
+ for (i = 1; i < DPLL_MAX_MUL; i++)
+ {
+ for (j = 1; j < DPLL_MAX_DIV; j++)
+ {
+ delta = frequency - i * (sysclk / j);
+ if (delta < 0)
+ {
+ delta = -delta;
+ }
+
+ if (delta < mindelta)
+ {
+ mul = i;
+ div = j;
+ mindelta = delta;
+ }
+
+ if (mindelta == 0)
+ {
+ break;
+ }
+ }
+ }
+
+ putreg32(AM335X_CM_WKUP_CLKSEL_DPLL_DISP, (mul << 8) | (div - 1));
+
+ /* Locked mode */
+
+ putreg32(AM335X_CM_WKUP_CLKMODE_DPLL_DISP, 0x7);
+
+ timeout = 10000;
+ while ((getreg32(AM335X_CM_WKUP_IDLEST_DPLL_DISP) & (1 << 0)) == 0 &&
+ timeout-- > 0)
+ {
+ up_udelay(10);
+ }
+
+ return timeout > 0 ? OK : -ETIMEDOUT;
+}
+
+/****************************************************************************
+ * Name: am335x_get_refclk
+ ****************************************************************************/
+
+static int am335x_get_refclk(uint32_t *frequency)
+{
+ uint32_t regval;
+ uint32_t sysclk;
+
+ regval = getreg32(AM335X_CM_WKUP_CLKMODE_DPLL_DISP);
+
+ /* Check if we are running in bypass */
+
+ if ((regval & (1 << 23)) != 0)
+ {
+ return -ENXIO;
+ }
+
+ sysclk = am335x_get_sysclk();
+ *frequency = ((regval >> 8) & 0x7ff) * (sysclk / ((regval & 0x7f) + 1));
+ return OK;
+}
+
+/****************************************************************************
+ * Name: am335x_lcdc_enableclk
+ ****************************************************************************/
+
+static int am335x_lcdc_enableclk(void)
+{
+ /* Set MODULEMODE to ENABLE(2) */
+
+ putreg32(AM335X_CM_PER_LCDC_CLKCTRL, CM_WKUP_CLKCTRL_MODULEMODE_ENABLE);
+
+ /* Wait for MODULEMODE to reflect that it is enabled */
+
+ while ((getreg32(AM335X_CM_PER_LCDC_CLKCTRL) & CM_WKUP_CLKCTRL_MODULEMODE_MASK)
+ != CM_WKUP_CLKCTRL_MODULEMODE_ENABLE)
+ {
+ up_udelay(10);
+ }
+
+ /* Wait for IDLEST to become fully functional */
+
+ while ((getreg32(AM335X_CM_PER_LCDC_CLKCTRL) & CM_WKUP_CLKCTRL_IDLEST_MASK)
+ != CM_WKUP_CLKCTRL_IDLEST_FUNC)
+ {
+ up_udelay(10);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: am335x_lcd_initialize
+ *
+ * Description:
+ * Initialize the AM335x for use the display described by the provided
+ * instance of struct am335x_panel_info_s.
+ *
+ * This function must be called by board specific logic to initialize the
+ * LCD. Normally the calling sequence is as follows:
+ *
+ * 1a. Graphics application starts and initializes the NX server via
+ * boardctl(BOARDIOC_NX_START). This calls the graphics
+ * initialization function nxmu_start() which, in turn, will call
+ * up_fbinitialize(). Or,
+ * 1b. The framebuffer character driver is initialized and calls
+ * up_fbinitialize().
+ * 2. The function up_fbinitialize() must reside in board specific logic
+ * under configs/. It must create the instance of struct
+ * am335x_panel_info_s and call this function with that instance.
+ *
+ * For a directly connected LCD, either (1) the struct am335x_panel_info_s
+ * may be initialized with constant data or (2) the desired video mode can
+ * obtained via lookup from edid_mode_lookup() and the struct
+ * am335x_panel_info_s can be created with am335x_lcd_videomode().
+ *
+ * If there is access to Extended Display Identification Data (EDID), then
+ * the board-specific logic may read the EDID data and use
+ * am335x_lcd_edid() to use the EDID data to initialize the struct
+ * am335x_panel_info_s instance.
+ *
+ * Input Parameters:
+ * panel - Provides information about the connect LCD panel.
+ *
+ * Returned value:
+ * Zero (OK) is returned on success; a negated errno value is returned in
+ * the the case of a failure.
+ *
+ ****************************************************************************/
+
+int am335x_lcd_initialize(FAR const struct am335x_panel_info_s *panel)
+{
+ struct am335x_lcd_dev_s *priv = &g_lcddev;
+ uint32_t regval;
+ uint32_t reffreq;
+ uint32_t timing0;
+ uint32_t timing1;
+ uint32_t timing2;
+ uint32_t logburst;
+ uint32_t hbp;
+ uint32_t hfp;
+ uint32_t hsw;
+ uint32_t vbp;
+ uint32_t vfp;
+ uint32_t vsw;
+ uint32_t width;
+ uint32_t height;
+ int div;
+ int ret;
+
+ DEBUGASSERT(panel != NULL);
+
+ /* Configure LCD pins */
+
+ lcdinfo("Configuring pins\n");
+
+#if !defined(CONFIG_AM335X_LCDC_BPP16_565) && !defined(CONFIG_AM335X_LCDC_BPP12_444)
+ am335x_gpio_config(GPIO_LCD_DATA0);
+ am335x_gpio_config(GPIO_LCD_DATA1);
+ am335x_gpio_config(GPIO_LCD_DATA2);
+#endif
+#ifndef CONFIG_AM335X_LCDC_BPP12_444
+ am335x_gpio_config(GPIO_LCD_DATA3);
+#endif
+ am335x_gpio_config(GPIO_LCD_DATA4);
+ am335x_gpio_config(GPIO_LCD_DATA5);
+ am335x_gpio_config(GPIO_LCD_DATA6);
+ am335x_gpio_config(GPIO_LCD_DATA7);
+
+#if AM335X_BPP > 8 /* Or STN 8-BPP Dual panel */
+#if !defined(CONFIG_AM335X_LCDC_BPP16_565) && !defined(CONFIG_AM335X_LCDC_BPP12_444)
+ am335x_gpio_config(GPIO_LCD_DATA8);
+ am335x_gpio_config(GPIO_LCD_DATA9);
+#endif
+#ifndef CONFIG_AM335X_LCDC_BPP12_444
+ am335x_gpio_config(GPIO_LCD_DATA10);
+ am335x_gpio_config(GPIO_LCD_DATA11);
+#endif
+ am335x_gpio_config(GPIO_LCD_DATA12);
+ am335x_gpio_config(GPIO_LCD_DATA13);
+ am335x_gpio_config(GPIO_LCD_DATA14);
+ am335x_gpio_config(GPIO_LCD_DATA15);
+#endif
+
+#if AM335X_BPP > 16 || defined(CONFIG_AM335X_LCDC_TFTPANEL)
+#if !defined(CONFIG_AM335X_LCDC_BPP16_565) && !defined(CONFIG_AM335X_LCDC_BPP12_444)
+ am335x_gpio_config(GPIO_LCD_DATA16);
+ am335x_gpio_config(GPIO_LCD_DATA17);
+ am335x_gpio_config(GPIO_LCD_DATA18);
+#endif
+#ifndef CONFIG_AM335X_LCDC_BPP12_444
+ am335x_gpio_config(GPIO_LCD_DATA19);
+#endif
+ am335x_gpio_config(GPIO_LCD_DATA20);
+ am335x_gpio_config(GPIO_LCD_DATA21);
+ am335x_gpio_config(GPIO_LCD_DATA22);
+ am335x_gpio_config(GPIO_LCD_DATA23);
+#endif
+
+ /* Other pins */
+
+ am335x_gpio_config(GPIO_LCD_HSYNC);
+ am335x_gpio_config(GPIO_LCD_VSYNC);
+ am335x_gpio_config(GPIO_LCD_AC_BIAS_EN);
+ am335x_gpio_config(GPIO_LCD_MEMORY_CLK_1);
+ am335x_gpio_config(GPIO_LCD_MEMORY_CLK_2);
+
+ /* Initialize the device state singleton */
+
+ sem_init(&priv->exclsem, 0, 1);
+ memcpy(&priv->panel, panel, sizeof(struct am335x_panel_info_s));
+
+ /* Save framebuffer information */
+
+ priv->stride = (priv->panel.width * priv->panel.bpp + 7) >> 3;
+ priv->fbsize = priv->stride * priv->panel.height;
+ DEBUGASSERT(priv->fbsize <= AM335X_LCDC_FB_SIZE);
+
+ /* Attach the LCD interrupt */
+
+ ret = irq_attach(AM335X_IRQ_LCDC, am335x_lcd_interrupt, priv);
+ if (ret < 0)
+ {
+ lcderr("ERROR: Failed to attach LCDC interrupt.");
+ }
+
+ /* Set the initial reference clock to twice the VGA pixel clock for now. */
+
+ (void)am335x_set_refclk(2 * 25175000);
+
+ /* Enable clocking to the LCD peripheral. */
+
+ lcdinfo("Enable clocking to the LCD controller\n");
+
+ ret = am335x_lcdc_enableclk();
+ if (ret < 0)
+ {
+ lcderr("ERROR: Failed to enable clocking\n");
+ return ret;
+ }
+
+ /* Adjust reference clock to get double of requested pixel clock frequency
+ * HDMI/DVI displays are very sensitive to error in frequency value.
+ */
+
+ ret = am335x_set_refclk(2 * priv->panel.pixclk);
+ if (ret < 0)
+ {
+ lcderr("ERROR: Failed to set source frequency\n");
+ return ret;
+ }
+
+ /* Read back the actual reference clock frequency */
+
+ ret = am335x_get_refclk(&reffreq);
+ if (ret < 0)
+ {
+ lcderr("ERROR: Failed to get reference frequency\n");
+ return ret;
+ }
+
+ /* Panel initialization */
+
+ /* Put the LCD framebuffer memory in a known state */
+
+ am335x_lcdclear(CONFIG_AM335X_LCDC_BACKCOLOR);
+
+ /* Only raster mode is supported */
+
+ regval = LCD_CTRL_MODE_RASTER;
+ div = am335x_lcd_divisor(reffreq, priv->panel.pixclk);
+ regval |= (div << LCD_CTRL_CLKDIV_SHIFT);
+ putreg32(AM335X_LCD_CTRL, regval);
+
+ /* Set timing */
+
+ timing0 = timing1 = timing2 = 0;
+
+ hbp = priv->panel.hbp - 1;
+ hfp = priv->panel.hfp - 1;
+ hsw = priv->panel.hsw - 1;
+
+ vbp = priv->panel.vbp;
+ vfp = priv->panel.vfp;
+ vsw = priv->panel.vsw - 1;
+
+ height = priv->panel.height - 1;
+ width = priv->panel.width - 1;
+
+ /* Horizontal back porch */
+
+ timing0 |= (hbp & 0xff) << LCD_RASTER_TIMING_0_HBP_SHIFT;
+ timing2 |= ((hbp >> 8) & 3) << LCD_RASTER_TIMING_2_HBP_HBITS_SHIFT;
+
+ /* Horizontal front porch */
+
+ timing0 |= (hfp & 0xff) << LCD_RASTER_TIMING_0_HFP_SHIFT;
+ timing2 |= ((hfp >> 8) & 3) << LCD_RASTER_TIMING_2_HFP_HBITS_SHIFT;
+
+ /* Horizontal sync width */
+
+ timing0 |= (hsw & 0x3f) << LCD_RASTER_TIMING_0_HSW_SHIFT;
+ timing2 |= ((hsw >> 6) & 0xf) << LCD_RASTER_TIMING_2_HSW_HBITS_SHIFT;
+
+ /* Vertical back porch, front porch, sync width */
+
+ timing1 |= (vbp & 0xff) << LCD_RASTER_TIMING_1_VBP_SHIFT;
+ timing1 |= (vfp & 0xff) << LCD_RASTER_TIMING_1_VFP_SHIFT;
+ timing1 |= (vsw & 0x3f) << LCD_RASTER_TIMING_1_VSW_SHIFT;
+
+ /* Pixels per line */
+
+ timing0 |= ((width >> 10) & 1) << LCD_RASTER_TIMING_0_PPLLSB_SHIFT;
+ timing0 |= ((width >> 4) & 0x3f) << LCD_RASTER_TIMING_0_PPLLSB_SHIFT;
+
+ /* Lines per panel */
+
+ timing1 |= (height & 0x3ff) << LCD_RASTER_TIMING_1_LPP_SHIFT;
+ timing2 |= ((height >> 10) & 1) << LCD_RASTER_TIMING_2_LPP_B10_SHIFT;
+
+ /* Clock signal settings */
+
+ if (priv->panel.sync_ctrl)
+ {
+ timing2 |= LCD_RASTER_TIMING_2_PHSVS_ON;
+ }
+
+ if (priv->panel.sync_edge)
+ {
+ timing2 |= LCD_RASTER_TIMING_2_PHSVS_RF;
+ }
+
+ if (!priv->panel.hsync_active)
+ {
+ timing2 |= LCD_RASTER_TIMING_2_IHS;
+ }
+
+ if (!priv->panel.vsync_active)
+ {
+ timing2 |= LCD_RASTER_TIMING_2_IVS;
+ }
+
+ if (!priv->panel.pixelclk_active)
+ {
+ timing2 |= LCD_RASTER_TIMING_2_IPC;
+ }
+
+ /* AC bias */
+
+ timing2 |= (priv->panel.acbias << LCD_RASTER_TIMING_2_ACB_SHIFT);
+ timing2 |= (priv->panel.acbias_pint << LCD_RASTER_TIMING_2_ACBI_SHIFT);
+
+ putreg32(AM335X_LCD_RASTER_TIMING_0, timing0);
+ putreg32(AM335X_LCD_RASTER_TIMING_1, timing1);
+ putreg32(AM335X_LCD_RASTER_TIMING_2, timing2);
+
+ /* DMA settings */
+
+ regval = LCD_DMA_CTRL_FRAME_MODE;
+
+ /* Find power of 2 for current burst size */
+
+ switch (priv->panel.dma_burstsz)
+ {
+ case 1:
+ logburst = 0;
+ break;
+
+ case 2:
+ logburst = 1;
+ break;
+
+ case 4:
+ logburst = 2;
+ break;
+
+ case 8:
+ logburst = 3;
+ break;
+
+ case 16:
+ default:
+ logburst = 4;
+ break;
+ }
+
+ regval |= (logburst << LCD_DMA_CTRL_BURST_SIZE_SHIFT);
+
+ /* XXX: FIFO TH */
+
+ regval |= (0 << LCD_DMA_CTRL_TH_FIFO_RDY_SHIFT);
+ putreg32(AM335X_LCD_DMA_CTRL, regval);
+
+ putreg32(AM335X_LCD_DMA_FB0_BASE, CONFIG_AM335X_LCDC_FB_PBASE);
+ putreg32(AM335X_LCD_DMA_FB0_BASE, CONFIG_AM335X_LCDC_FB_PBASE + priv->fbsize - 1);
+ putreg32(AM335X_LCD_DMA_FB1_BASE, CONFIG_AM335X_LCDC_FB_PBASE);
+ putreg32(AM335X_LCD_DMA_FB1_CEIL, CONFIG_AM335X_LCDC_FB_PBASE + priv->fbsize - 1);
+
+ /* Enable LCD */
+
+ regval = LCD_RASTER_CTRL_LCD_TFT;
+ regval |= (priv->panel.fdd << LCD_RASTER_CTRL_REQDLY_SHIFT);
+ regval |= LCD_RASTER_CTRL_DATA;
+
+ if (priv->panel.bpp >= 24)
+ {
+ regval |= LCD_RASTER_CTRL_TFT24;
+ }
+
+ if (priv->panel.bpp == 32)
+ {
+ regval |= LCD_RASTER_CTRL_TFT24_UNPACKED;
+ }
+
+ putreg32(AM335X_LCD_RASTER_CTRL, regval);
+
+ putreg32(AM335X_LCD_CLKC_ENABLE,
+ LCD_CLKC_ENABLE_CORE | LCD_CLKC_ENABLE_LIDD |
+ LCD_CLKC_ENABLE_DMA);
+
+ putreg32(AM335X_LCD_CLKC_RESET, LCD_CLKC_RESET_MAIN);
+ up_udelay(100);
+ putreg32(AM335X_LCD_CLKC_RESET, 0);
+
+ regval = LCD_IRQ_DONE | LCD_IRQ_RR_DONE | LCD_IRQ_SYNC | LCD_IRQ_ACB |
+ LCD_IRQ_PL | LCD_IRQ_FUF | LCD_IRQ_EOF0 | LCD_IRQ_EOF1;
+ putreg32(AM335X_LCD_IRQ_EN_SET, regval);
+
+ regval = getreg32(AM335X_LCD_RASTER_CTRL);
+ regval |= LCD_RASTER_CTRL_LCD_EN;
+ putreg32(AM335X_LCD_RASTER_CTRL, regval);
+
+ putreg32(AM335X_LCD_SYSC, LCD_SYSC_IDLE_SMART | LCD_SYSC_STANDBY_SMART);
+
+#ifdef CONFIG_AM335X_LCDC_BACKLIGHT
+ /* Turn on the back light
+ * REVISIT: Current assumes a discrete ON/OFF control. Needs additional
+ * support for backlight level control.
+ */
+
+ am335x_backlight(true);
+#endif
+
+ /* Enable interrupts at the interrupt controller */
+
+ up_enable_irq(AM335X_IRQ_LCDC);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_fbgetvplane
+ *
+ * Description:
+ * Return a a reference to the framebuffer object for the specified video
+ * plane of the specified plane. Many OSDs support multiple planes of video.
+ *
+ * Input Parameters:
+ * display - In the case of hardware with multiple displays, this
+ * specifies the display. Normally this is zero.
+ * vplane - Identifies the plane being queried.
+ *
+ * Returned Value:
+ * A non-NULL pointer to the frame buffer access structure is returned on
+ * success; NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane)
+{
+ lcdinfo("vplane: %d\n", vplane);
+ if (vplane == 0)
+ {
+ return &g_fbinterface;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/****************************************************************************
+ * Name: up_fbuninitialize
+ *
+ * Description:
+ * Uninitialize the framebuffer support for the specified display.
+ *
+ * Input Parameters:
+ * display - In the case of hardware with multiple displays, this
+ * specifies the display. Normally this is zero.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void up_fbuninitialize(int display)
+{
+#ifdef CONFIG_AM335X_LCDC_BACKLIGHT
+ /* Turn off the back light */
+
+ am335x_backlight(false);
+#endif
+
+ /* Reset/Disable the LCD controller */
+ /* Disable clocking to the LCD peripheral */
+ /* Detach and disable the LCDC interrupt */
+}
+
+/****************************************************************************
+ * Name: am335x_lcdclear
+ *
+ * Description:
+ * This is a non-standard LCD interface just for the AM335x. Clearing
+ * the display in the normal way by writing a sequences of runs that
+ * covers the entire display can be slow. Here the display is cleared by
+ * simply setting all VRAM memory to the specified color.
+ *
+ ****************************************************************************/
+
+void am335x_lcdclear(nxgl_mxpixel_t color)
+{
+ struct am335x_lcd_dev_s *priv = &g_lcddev;
+#if AM335X_BPP > 16
+ uint32_t *dest = (uint32_t *)CONFIG_AM335X_LCDC_FB_VBASE;
+ int incr = sizeof(uint32_t);
+#else
+ uint16_t *dest = (uint16_t *)CONFIG_AM335X_LCDC_FB_VBASE;
+ int incr = sizeof(uint16_t);
+#endif
+ int i;
+
+ lcdinfo("Clearing display: color=%04x VRAM=%08lx size=%lu\n",
+ color, (unsigned long)CONFIG_AM335X_LCDC_FB_VBASE,
+ (unsigned long)priv->fbsize);
+
+ for (i = 0; i < priv->fbsize; i += incr)
+ {
+ *dest++ = color;
+ }
+}
diff --git a/arch/arm/src/am335x/am335x_lcdc.h b/arch/arm/src/am335x/am335x_lcdc.h
new file mode 100644
index 00000000000..03a59663d1a
--- /dev/null
+++ b/arch/arm/src/am335x/am335x_lcdc.h
@@ -0,0 +1,302 @@
+/****************************************************************************
+ * arch/arm/src/am335x/am335x_lcdc.h
+ *
+ * Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt
+ *
+ * The LCD driver derives from the LPC54xx LCD driver but also includes
+ * information from the FreeBSD AM335x LCD driver which was released under
+ * a two-clause BSD license:
+ *
+ * Copyright 2013 Oleksandr Tymoshenko
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* The LPC54 LCD driver uses the common framebuffer interfaces declared in
+ * include/nuttx/video/fb.h.
+ */
+
+#ifndef __ARCH_ARM_SRC_AM335X_AM335X_LCDC_H
+#define __ARCH_ARM_SRC_AM335X_AM335X_LCDC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+
+#include
+
+#include "hardware/am335x_lcd.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+/* Background color */
+
+#ifndef CONFIG_AM335X_LCDC_BACKCOLOR
+# warning "Assuming background color == 16"
+# define CONFIG_AM335X_LCDC_BACKCOLOR 0 /* Initial background color */
+#endif
+
+/* Default characteristics (may be overridden via struct am335x_panel_info_s */
+
+/* Bits per pixel / color format */
+
+#undef AM335X_COLOR_FMT
+#if defined(CONFIG_AM335X_LCDC_BPP1)
+# define AM335X_BPP 1
+# define AM335X_COLOR_FMT FB_FMT_Y1
+#elif defined(CONFIG_AM335X_LCDC_BPP2)
+# define AM335X_BPP 2
+# define AM335X_COLOR_FMT FB_FMT_Y2
+#elif defined(CONFIG_AM335X_LCDC_BPP4)
+# define AM335X_BPP 4
+# define AM335X_COLOR_FMT FB_FMT_Y4
+#elif defined(CONFIG_AM335X_LCDC_BPP8)
+# define AM335X_BPP 8
+# define AM335X_COLOR_FMT FB_FMT_Y8
+#elif defined(CONFIG_AM335X_LCDC_BPP12_444)
+# define AM335X_BPP 1 12
+# define AM335X_COLOR_FMT FB_FMT_RGB12_444
+#elif defined(CONFIG_AM335X_LCDC_BPP16_565)
+# define AM335X_BPP 16
+# define AM335X_COLOR_FMT FB_FMT_RGB16_565
+#elif defined(CONFIG_AM335X_LCDC_BPP24)
+# define AM335X_BPP 24 RGB */
+# define AM335X_COLOR_FMT FB_FMT_RGB24
+#else
+# warning "Assuming 16 BPP 5:6:5"
+# define AM335X_BPP 16
+# define CONFIG_AM335X_LCDC_BPP16_565 1
+# define AM335X_COLOR_FMT FB_FMT_RGB16_565
+#endif
+
+#ifndef CONFIG_AM335X_LCDC_ACBIAS
+# warning "Assuming AC bias == 255"
+# define CONFIG_AM335X_LCDC_ACBIAS 255
+#endif
+
+#ifndef CONFIG_AM335X_LCDC_ACBIAS_PINT
+# warning "Assuming AC bias per interrupt == 0"
+# define CONFIG_AM335X_LCDC_ACBIAS_PINT 0
+#endif
+
+#if defined(CONFIG_AM335X_LCDC_DMA_BURST1)
+# define AM335X_LCD_DMA_BURSTSZ 1
+#elif defined(CONFIG_AM335X_LCDC_DMA_BURST2)
+# define AM335X_LCD_DMA_BURSTSZ 2
+#elif defined(CONFIG_AM335X_LCDC_DMA_BURST4)
+# define AM335X_LCD_DMA_BURSTSZ 4
+#elif defined(CONFIG_AM335X_LCDC_DMA_BURST8)
+# define AM335X_LCD_DMA_BURSTSZ 8
+#elif defined(CONFIG_AM335X_LCDC_DMA_BURST16)
+# define AM335X_LCD_DMA_BURSTSZ 16
+#else
+# warning "Assuming DMA burst size == 16"
+# define CONFIG_AM335X_LCDC_DMA_BURST16 1
+# define AM335X_LCD_DMA_BURSTSZ 16
+#endif
+
+#ifndef CONFIG_AM335X_LCDC_FDD
+# warning "Assuming FDD == 128"
+# define CONFIG_AM335X_LCDC_FDD 128
+#endif
+
+#if (CONFIG_AM335X_LCDC_FB_SIZE & 0x000fffff) != 0
+# warning "Framebuffer size must be a multiple of 1Mb"
+#endif
+
+#define AM335X_LCDC_FB_SIZE \
+ ((CONFIG_AM335X_LCDC_FB_SIZE + 0x000fffff) & ~0x000fffff)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Describes the LCD panel configuration */
+
+struct am335x_panel_info_s
+{
+ bool hsync_active; /* HSync active */
+ bool vsync_active; /* Invert VSync */
+ bool sync_edge; /* HSYNC/VSYNC rise or fall */
+ bool sync_ctrl; /* Hsync/Vsync pixel clock control on/off */
+ bool pixelclk_active; /* Invert pixel clock */
+
+ uint32_t width; /* Display width (pixels) */
+ uint32_t height; /* Display height (lines) */
+ uint32_t hfp; /* Horizontal front porch (pixels) */
+ uint32_t hbp; /* Horizontal back porch (pixels) */
+ uint32_t hsw; /* HSync width */
+ uint32_t vfp; /* Vertical front porch (lines) */
+ uint32_t vbp; /* Vertical back porch (lines) */
+ uint32_t vsw; /* VSync width */
+ uint32_t pixclk; /* Pixel clock */
+
+ uint32_t acbias; /* AC bias pin frequency */
+ uint32_t acbias_pint; /* AC bias pins transitions per interrupt */
+ uint32_t dma_burstsz; /* DMA burst size */
+ uint32_t bpp; /* Bits per pixel */
+ uint32_t fdd; /* Palette loading delay */
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: am335x_lcd_initialize
+ *
+ * Description:
+ * Initialize the AM335x for use the display described by the provided
+ * instance of struct am335x_panel_info_s.
+ *
+ * This function must be called by board specific logic to initialize the
+ * LCD. Normally the calling sequence is as follows:
+ *
+ * 1a. Graphics application starts and initializes the NX server via
+ * boardctl(BOARDIOC_NX_START). This calls the graphics
+ * initialization function nxmu_start() which, in turn, will call
+ * up_fbinitialize(). Or,
+ * 1b. The framebuffer character driver is initialized and calls
+ * up_fbinitialize().
+ * 2. The function up_fbinitialize() must reside in board specific logic
+ * under configs/. It must create the instance of struct
+ * am335x_panel_info_s and call this function with that instance.
+ *
+ * For a directly connected LCD, either (1) the struct am335x_panel_info_s
+ * may be initialized with constant data or (2) the desired video mode can
+ * obtained via lookup from edid_mode_lookup() and the struct
+ * am335x_panel_info_s can be created with am335x_lcd_videomode().
+ *
+ * If there is access to Extended Display Identification Data (EDID), then
+ * the board-specific logic may read the EDID data and use
+ * am335x_lcd_edid() to use the EDID data to initialize the struct
+ * am335x_panel_info_s instance.
+ *
+ * Input Parameters:
+ * panel - Provides information about the connect LCD panel.
+ *
+ * Returned value:
+ * Zero (OK) is returned on success; a negated errno value is returned in
+ * the the case of a failure.
+ *
+ ****************************************************************************/
+
+int am335x_lcd_initialize(FAR const struct am335x_panel_info_s *panel);
+
+/****************************************************************************
+ * Name: am335x_lcdclear
+ *
+ * Description:
+ * This is a non-standard LCD interface just for the AM335x. Clearing
+ * the display in the normal way by writing a sequences of runs that
+ * covers the entire display can be slow. Here the display is cleared by
+ * simply setting all VRAM memory to the specified color.
+ *
+ ****************************************************************************/
+
+void am335x_lcdclear(nxgl_mxpixel_t color);
+
+/****************************************************************************
+ * Name: am335x_lcd_videomode
+ *
+ * Description:
+ * If the video mod is known, then the board-specific logic may read the
+ * use this function to convert the video mode data to an instance of
+ * struct am335x_panel_info_s which then may be used to initialize the
+ * the LCD/
+ *
+ * Input Parameters:
+ * videomode - A reference to the desired video mode.
+ * panel - A user provided location to receive the panel data.
+ *
+ * Returned value:
+ * None. Always succeeds.
+ *
+ ****************************************************************************/
+
+struct edid_videomode_s; /* Forward reference */
+
+void am335x_lcd_videomode(FAR const struct edid_videomode_s *videomode,
+ FAR struct am335x_panel_info_s *panel);
+
+/****************************************************************************
+ * Name: am335x_lcd_edid
+ *
+ * Description:
+ * If there is access to Extended Display Identification Data (EDID),
+ * then the board-specific logic may read the EDID data and use this
+ * function to initialize an instance of struct am335x_panel_info_s.
+ *
+ * The returned video mode may optionally be returned to configure HDMI.
+ *
+ * Input Parameters:
+ * edid - A reference to the raw EDID data.
+ * len - The length of the EDID data in bytes
+ * panel - A user provided location to receive the panel data.
+ * selected - A user provided location to receive the selected video mode.
+ *
+ * Returned value:
+ * None. Always succeeds. The logic will fallback to VGA mode if no
+ * EDID data is provided or if there is no valid video mode in the EDID
+ * data.
+ *
+ ****************************************************************************/
+
+void am335x_lcd_edid(FAR const uint8_t *edid, size_t edid_len,
+ FAR struct am335x_panel_info_s *panel,
+ FAR struct edid_videomode_s *selected);
+
+/****************************************************************************
+ * Name: am335x_backlight
+ *
+ * Description:
+ * If CONFIG_AM335X_LCDC_BACKLIGHT is defined, then the board-specific
+ * logic must provide this interface to turn the backlight on and off.
+ *
+ * REVISIT: Current assumes a discrete ON/OFF control. Needs additional
+ * support for backlight level control.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_AM335X_LCDC_BACKLIGHT
+void am335x_backlight(bool blon);
+#endif
+
+#endif /* __ARCH_ARM_SRC_AM335X_AM335X_LCDC_H */
diff --git a/arch/arm/src/am335x/am335x_sysclk.c b/arch/arm/src/am335x/am335x_sysclk.c
new file mode 100644
index 00000000000..b812d37ae8d
--- /dev/null
+++ b/arch/arm/src/am335x/am335x_sysclk.c
@@ -0,0 +1,102 @@
+/****************************************************************************
+ * arch/arm/src/am335x/am335x_sysclk.c
+ *
+ * Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+
+#include "up_arch.h"
+#include "hardware/am335x_memorymap.h"
+#include "am335x_sysclk.h"
+
+/****************************************************************************
+ * Pre-processor definitions
+ ****************************************************************************/
+
+/* REVISIT: These belong in a control module register header file */
+
+#define AM335X_SCM_CTRL_STATUS_OFFSET 0x40
+#define AM335X_SCM_CTRL_STATUS (AM335X_CONTROL_MODULE_VADDR + AM335X_SCM_CTRL_STATUS_OFFSET)
+#define SCM_CTRL_STATUS_SYSBOOT1_SHIFT (22) /* Bits 22-23: Crystal clock frequency selection */
+#define SCM_CTRL_STATUS_SYSBOOT1_MASK (3 << SCM_CTRL_STATUS_SYSBOOT1_SHIFT)
+# define SCM_CTRL_STATUS_SYSBOOT1_19p2MHZ (0 << SCM_CTRL_STATUS_SYSBOOT1_SHIFT)
+# define SCM_CTRL_STATUS_SYSBOOT1_24MHZ (1 << SCM_CTRL_STATUS_SYSBOOT1_SHIFT)
+# define SCM_CTRL_STATUS_SYSBOOT1_25MHZ (2 << SCM_CTRL_STATUS_SYSBOOT1_SHIFT)
+# define SCM_CTRL_STATUS_SYSBOOT1_26MHZ (3 << SCM_CTRL_STATUS_SYSBOOT1_SHIFT)
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: am335x_get_sysclk
+ *
+ * Description:
+ * Return the sysclk frequency
+ *
+ ****************************************************************************/
+
+int32_t am335x_get_sysclk(void)
+{
+ uint32_t regval;
+
+ /* Read the input clock freq from the control module. */
+
+ regval = getreg32(AM335X_SCM_CTRL_STATUS);
+
+ /* Return the frequency of the configured crystal */
+
+ switch (regval & SCM_CTRL_STATUS_SYSBOOT1_MASK)
+ {
+ case SCM_CTRL_STATUS_SYSBOOT1_19p2MHZ: /* 19.2Mhz */
+ return 19200000;
+
+ case SCM_CTRL_STATUS_SYSBOOT1_24MHZ: /* 24Mhz */
+ return 24000000;
+
+ case SCM_CTRL_STATUS_SYSBOOT1_25MHZ: /* 25Mhz */
+ return 25000000;
+
+ case SCM_CTRL_STATUS_SYSBOOT1_26MHZ: /* 26Mhz */
+ return 26000000;
+ }
+
+ return -EINVAL; /* Should never happen */
+}
diff --git a/arch/arm/src/am335x/am335x_sysclk.h b/arch/arm/src/am335x/am335x_sysclk.h
new file mode 100644
index 00000000000..15669c50b0f
--- /dev/null
+++ b/arch/arm/src/am335x/am335x_sysclk.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * arch/arm/src/am335x/am335x_sysclk.h
+ *
+ * Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_AM335X_AM335X_SYSCLK_H
+#define __ARCH_ARM_SRC_AM335X_AM335X_SYSCLK_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: am335x_get_sysclk
+ *
+ * Description:
+ * Return the sysclk frequency
+ *
+ ****************************************************************************/
+
+int32_t am335x_get_sysclk(void);
+
+#endif /* __ARCH_ARM_SRC_AM335X_AM335X_SYSCLK_H */
diff --git a/arch/arm/src/am335x/am335x_timerisr.c b/arch/arm/src/am335x/am335x_timerisr.c
index f54d5709553..cdda7ae9c2e 100644
--- a/arch/arm/src/am335x/am335x_timerisr.c
+++ b/arch/arm/src/am335x/am335x_timerisr.c
@@ -51,20 +51,15 @@
#include "up_arch.h"
#include "hardware/am335x_timer.h"
+#define USE_TIMER1MS
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-#ifdef USE_TIMER1MS
-/* Timer 1 clock selects the external 32.768 KHz oscillator/clock */
-
-# define TMR_CLOCK (32768)
-
-#else
/* Timer clock selects system clock CLK_M_OSC (24MHz) */
# define TMR_CLOCK (24000000ll)
-#endif
/* The desired timer interrupt frequency is provided by the definition
* CLK_TCK (see include/time.h). CLK_TCK defines the desired number of
@@ -78,21 +73,12 @@
#define TMR_TLDR (0xffffffff - (TMR_CLOCK / CLK_TCK) + 1)
#define TMR_TCRR (0xffffffff - (TMR_CLOCK / CLK_TCK) + 1)
-#ifdef USE_TIMER1MS
-# define TMR_TPIR \
- (((TMR_CLOCK / CLK_TCK + 1) * 1000000l) - \
- (TMR_CLOCK * (1000000l / CLK_TCK)))
-# define TMR_TNIR \
- (((TMR_CLOCK / CLK_TCK) * 1000000l) - \
- (TMR_CLOCK * (1000000l / CLK_TCK)))
-#else
-# define TMR_TPIR \
+#define TMR_TPIR \
(((TMR_CLOCK / CLK_TCK + 1) * 1000000ll) - \
(TMR_CLOCK * (1000000ll / CLK_TCK)))
-# define TMR_TNIR \
+#define TMR_TNIR \
(((TMR_CLOCK / CLK_TCK) * 1000000ll) - \
(TMR_CLOCK * (1000000ll / CLK_TCK)))
-#endif
/****************************************************************************
* Private Functions
@@ -214,6 +200,5 @@ void arm_timer_initialize(void)
/* And enable the timer interrupt */
up_enable_irq(AM335X_IRQ_TIMER2);
-
#endif
}
diff --git a/arch/arm/src/am335x/am335x_wdog.c b/arch/arm/src/am335x/am335x_wdog.c
index 7b0aec8ec2c..8d98d9946bf 100644
--- a/arch/arm/src/am335x/am335x_wdog.c
+++ b/arch/arm/src/am335x/am335x_wdog.c
@@ -58,13 +58,13 @@
void am335x_wdog_disable_all(void)
{
- putreg32(WDT_WSPR_STOP_FEED_A, AM335X_WDT_WSPR);
- while ((getreg32(AM335X_WDT_WWPS) & WDT_WWPS_W_PEND_WSPR) != 0)
+ putreg32(WDT_SPR_STOP_FEED_A, AM335X_WDT_SPR);
+ while ((getreg32(AM335X_WDT_WPS) & WDT_WPS_W_PEND_WSPR) != 0)
{
}
- putreg32(WDT_WSPR_STOP_FEED_B, AM335X_WDT_WSPR);
- while ((getreg32(AM335X_WDT_WWPS) & WDT_WWPS_W_PEND_WSPR) != 0)
+ putreg32(WDT_SPR_STOP_FEED_B, AM335X_WDT_SPR);
+ while ((getreg32(AM335X_WDT_WPS) & WDT_WPS_W_PEND_WSPR) != 0)
{
}
}
diff --git a/arch/arm/src/am335x/hardware/am335x_cm.h b/arch/arm/src/am335x/hardware/am335x_cm.h
new file mode 100644
index 00000000000..1618daaf4ba
--- /dev/null
+++ b/arch/arm/src/am335x/hardware/am335x_cm.h
@@ -0,0 +1,368 @@
+/********************************************************************************************
+ * arch/arm/src/am335x/hardware/am335x_cm.h
+ *
+ * Copyright (C) 2019 Petro Karashchenko. All rights reserved.
+ * Author: Petro Karashchenko
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ********************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_CM_H
+#define __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_CM_H
+
+/********************************************************************************************
+ * Included Files
+ ********************************************************************************************/
+
+#include
+#include
+
+/********************************************************************************************
+ * Pre-processor Definitions
+ ********************************************************************************************/
+
+/* Clock Module Register Offsets ************************************************************/
+
+#define AM335X_CM_PER_L4LS_CLKSTCTRL_OFFSET 0x0000
+#define AM335X_CM_PER_L3S_CLKSTCTRL_OFFSET 0x0004
+#define AM335X_CM_PER_L3_CLKSTCTRL_OFFSET 0x000c
+#define AM335X_CM_PER_CPGMAC0_CLKCTRL_OFFSET 0x0014
+#define AM335X_CM_PER_LCDC_CLKCTRL_OFFSET 0x0018
+#define AM335X_CM_PER_USB0_CLKCTRL_OFFSET 0x001c
+#define AM335X_CM_PER_TPTC0_CLKCTRL_OFFSET 0x0024
+#define AM335X_CM_PER_EMIF_CLKCTRL_OFFSET 0x0028
+#define AM335X_CM_PER_OCMCRAM_CLKCTRL_OFFSET 0x002c
+#define AM335X_CM_PER_GPMC_CLKCTRL_OFFSET 0x0030
+#define AM335X_CM_PER_MCASP0_CLKCTRL_OFFSET 0x0034
+#define AM335X_CM_PER_UART5_CLKCTRL_OFFSET 0x0038
+#define AM335X_CM_PER_MMC0_CLKCTRL_OFFSET 0x003c
+#define AM335X_CM_PER_ELM_CLKCTRL_OFFSET 0x0040
+#define AM335X_CM_PER_I2C2_CLKCTRL_OFFSET 0x0044
+#define AM335X_CM_PER_I2C1_CLKCTRL_OFFSET 0x0048
+#define AM335X_CM_PER_SPI0_CLKCTRL_OFFSET 0x004c
+#define AM335X_CM_PER_SPI1_CLKCTRL_OFFSET 0x0050
+#define AM335X_CM_PER_L4LS_CLKCTRL_OFFSET 0x0060
+#define AM335X_CM_PER_MCASP1_CLKCTRL_OFFSET 0x0068
+#define AM335X_CM_PER_UART1_CLKCTRL_OFFSET 0x006c
+#define AM335X_CM_PER_UART2_CLKCTRL_OFFSET 0x0070
+#define AM335X_CM_PER_UART3_CLKCTRL_OFFSET 0x0074
+#define AM335X_CM_PER_UART4_CLKCTRL_OFFSET 0x0078
+#define AM335X_CM_PER_TIMER7_CLKCTRL_OFFSET 0x007c
+#define AM335X_CM_PER_TIMER2_CLKCTRL_OFFSET 0x0080
+#define AM335X_CM_PER_TIMER3_CLKCTRL_OFFSET 0x0084
+#define AM335X_CM_PER_TIMER4_CLKCTRL_OFFSET 0x0088
+#define AM335X_CM_PER_GPIO1_CLKCTRL_OFFSET 0x00ac
+#define AM335X_CM_PER_GPIO2_CLKCTRL_OFFSET 0x00b0
+#define AM335X_CM_PER_GPIO3_CLKCTRL_OFFSET 0x00b4
+#define AM335X_CM_PER_TPCC_CLKCTRL_OFFSET 0x00bc
+#define AM335X_CM_PER_DCAN0_CLKCTRL_OFFSET 0x00c0
+#define AM335X_CM_PER_DCAN1_CLKCTRL_OFFSET 0x00c4
+#define AM335X_CM_PER_EPWMSS1_CLKCTRL_OFFSET 0x00cc
+#define AM335X_CM_PER_EPWMSS0_CLKCTRL_OFFSET 0x00d4
+#define AM335X_CM_PER_EPWMSS2_CLKCTRL_OFFSET 0x00d8
+#define AM335X_CM_PER_L3_INSTR_CLKCTRL_OFFSET 0x00dc
+#define AM335X_CM_PER_L3_CLKCTRL_OFFSET 0x00e0
+#define AM335X_CM_PER_IEEE5000_CLKCTRL_OFFSET 0x00e4
+#define AM335X_CM_PER_PRU_ICSS_CLKCTRL_OFFSET 0x00e8
+#define AM335X_CM_PER_TIMER5_CLKCTRL_OFFSET 0x00ec
+#define AM335X_CM_PER_TIMER6_CLKCTRL_OFFSET 0x00f0
+#define AM335X_CM_PER_MMC1_CLKCTRL_OFFSET 0x00f4
+#define AM335X_CM_PER_MMC2_CLKCTRL_OFFSET 0x00f8
+#define AM335X_CM_PER_TPTC1_CLKCTRL_OFFSET 0x00fc
+#define AM335X_CM_PER_TPTC2_CLKCTRL_OFFSET 0x0100
+#define AM335X_CM_PER_SPINLOCK_CLKCTRL_OFFSET 0x010c
+#define AM335X_CM_PER_MAILBOX0_CLKCTRL_OFFSET 0x0110
+#define AM335X_CM_PER_L4HS_CLKSTCTRL_OFFSET 0x011c
+#define AM335X_CM_PER_L4HS_CLKCTRL_OFFSET 0x0120
+#define AM335X_CM_PER_OCPWP_L3_CLKSTCTRL_OFFSET 0x012c
+#define AM335X_CM_PER_OCPWP_CLKCTRL_OFFSET 0x0130
+#define AM335X_CM_PER_PRU_ICSS_CLKSTCTRL_OFFSET 0x0140
+#define AM335X_CM_PER_CPSW_CLKSTCTRL_OFFSET 0x0144
+#define AM335X_CM_PER_LCDC_CLKSTCTRL_OFFSET 0x0148
+#define AM335X_CM_PER_CLKDIV32K_CLKCTRL_OFFSET 0x014c
+#define AM335X_CM_PER_CLK_24MHZ_CLKSTCTRL_OFFSET 0x0150
+
+#define AM335X_CM_WKUP_CLKSTCTRL_OFFSET 0x0000
+#define AM335X_CM_WKUP_CONTROL_CLKCTRL_OFFSET 0x0004
+#define AM335X_CM_WKUP_GPIO0_CLKCTRL_OFFSET 0x0008
+#define AM335X_CM_WKUP_L4WKUP_CLKCTRL_OFFSET 0x000c
+#define AM335X_CM_WKUP_TIMER0_CLKCTRL_OFFSET 0x0010
+#define AM335X_CM_WKUP_DEBUGSS_CLKCTRL_OFFSET 0x0014
+#define AM335X_CM_WKUP_L3_AON_CLKSTCTRL_OFFSET 0x0018
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_MPU_OFFSET 0x001c
+#define AM335X_CM_WKUP_IDLEST_DPLL_MPU_OFFSET 0x0020
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_MPU_OFFSET 0x0024
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_MPU_OFFSET 0x0028
+#define AM335X_CM_WKUP_CLKSEL_DPLL_MPU_OFFSET 0x002c
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_DDR_OFFSET 0x0030
+#define AM335X_CM_WKUP_IDLEST_DPLL_DDR_OFFSET 0x0034
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_DDR_OFFSET 0x0038
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_DDR_OFFSET 0x003c
+#define AM335X_CM_WKUP_CLKSEL_DPLL_DDR_OFFSET 0x0040
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_DISP_OFFSET 0x0044
+#define AM335X_CM_WKUP_IDLEST_DPLL_DISP_OFFSET 0x0048
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_DISP_OFFSET 0x004c
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_DISP_OFFSET 0x0050
+#define AM335X_CM_WKUP_CLKSEL_DPLL_DISP_OFFSET 0x0054
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_CORE_OFFSET 0x0058
+#define AM335X_CM_WKUP_IDLEST_DPLL_CORE_OFFSET 0x005c
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_CORE_OFFSET 0x0060
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_CORE_OFFSET 0x0064
+#define AM335X_CM_WKUP_CLKSEL_DPLL_CORE_OFFSET 0x0068
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_PER_OFFSET 0x006c
+#define AM335X_CM_WKUP_IDLEST_DPLL_PER_OFFSET 0x0070
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_PER_OFFSET 0x0074
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_PER_OFFSET 0x0078
+#define AM335X_CM_WKUP_CLKDCOLDO_DPLL_PER_OFFSET 0x007c
+#define AM335X_CM_WKUP_DIV_M4_DPLL_CORE_OFFSET 0x0080
+#define AM335X_CM_WKUP_DIV_M5_DPLL_CORE_OFFSET 0x0084
+#define AM335X_CM_WKUP_CLKMODE_DPLL_MPU_OFFSET 0x0088
+#define AM335X_CM_WKUP_CLKMODE_DPLL_PER_OFFSET 0x008c
+#define AM335X_CM_WKUP_CLKMODE_DPLL_CORE_OFFSET 0x0090
+#define AM335X_CM_WKUP_CLKMODE_DPLL_DDR_OFFSET 0x0094
+#define AM335X_CM_WKUP_CLKMODE_DPLL_DISP_OFFSET 0x0098
+#define AM335X_CM_WKUP_CLKSEL_DPLL_PERIPH_OFFSET 0x009c
+#define AM335X_CM_WKUP_DIV_M2_DPLL_DDR_OFFSET 0x00a0
+#define AM335X_CM_WKUP_DIV_M2_DPLL_DISP_OFFSET 0x00a4
+#define AM335X_CM_WKUP_DIV_M2_DPLL_MPU_OFFSET 0x00a8
+#define AM335X_CM_WKUP_DIV_M2_DPLL_PER_OFFSET 0x00ac
+#define AM335X_CM_WKUP_M3_CLKCTRL_OFFSET 0x00b0
+#define AM335X_CM_WKUP_UART0_CLKCTRL_OFFSET 0x00b4
+#define AM335X_CM_WKUP_I2C0_CLKCTRL_OFFSET 0x00b8
+#define AM335X_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET 0x00bc
+#define AM335X_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET 0x00c0
+#define AM335X_CM_WKUP_TIMER1_CLKCTRL_OFFSET 0x00c4
+#define AM335X_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET 0x00c8
+#define AM335X_CM_WKUP_L4WKUP_AON_CLKSTCTRL_OFFSET 0x00cc
+#define AM335X_CM_WKUP_WDT1_CLKCTRL_OFFSET 0x00d4
+#define AM335X_CM_WKUP_DIV_M6_DPLL_CORE_OFFSET 0x00d8
+
+#define AM335X_CM_DPLL_CLKSEL_TIMER7_CLK_OFFSET 0x0004
+#define AM335X_CM_DPLL_CLKSEL_TIMER2_CLK_OFFSET 0x0008
+#define AM335X_CM_DPLL_CLKSEL_TIMER3_CLK_OFFSET 0x000c
+#define AM335X_CM_DPLL_CLKSEL_TIMER4_CLK_OFFSET 0x0010
+#define AM335X_CM_DPLL_CLKSEL_MAC_CLK_OFFSET 0x0014
+#define AM335X_CM_DPLL_CLKSEL_TIMER5_CLK_OFFSET 0x0018
+#define AM335X_CM_DPLL_CLKSEL_TIMER6_CLK_OFFSET 0x001c
+#define AM335X_CM_DPLL_CLKSEL_CPTS_RFT_CLK_OFFSET 0x0020
+#define AM335X_CM_DPLL_CLKSEL_TIMER1MS_CLK_OFFSET 0x0028
+#define AM335X_CM_DPLL_CLKSEL_GFX_FCLK_OFFSET 0x002c
+#define AM335X_CM_DPLL_CLKSEL_PRU_ICSS_OCP_CLK_OFFSET 0x0030
+#define AM335X_CM_DPLL_CLKSEL_LCDC_PIXEL_CLK_OFFSET 0x0034
+#define AM335X_CM_DPLL_CLKSEL_WDT1_CLK_OFFSET 0x0038
+#define AM335X_CM_DPLL_CLKSEL_GPIO0_DBCLK_OFFSET 0x003c
+
+#define AM335X_CM_MPU_CLKSTCTRL_OFFSET 0x0000
+#define AM335X_CM_MPU_CLKCTRL_OFFSET 0x0004
+
+#define AM335X_CM_DEVICE_CLKOUT_CTRL_OFFSET 0x0000
+
+#define AM335X_CM_RTC_CLKCTRL_OFFSET 0x0000
+#define AM335X_CM_RTC_CLKSTCTRL_OFFSET 0x0004
+
+#define AM335X_CM_GFX_L3_CLKSTCTRL_OFFSET 0x0000
+#define AM335X_CM_GFX_CLKCTRL_OFFSET 0x0004
+#define AM335X_CM_GFX_L4LS_CLKSTCTRL_OFFSET 0x000c
+#define AM335X_CM_GFX_MMUCFG_CLKCTRL_OFFSET 0x0010
+#define AM335X_CM_GFX_MMUDATA_CLKCTRL_OFFSET 0x0014
+
+#define AM335X_CM_CEFUSE_CLKSTCTRL_OFFSET 0x0000
+#define AM335X_CM_CEFUSE_CLKCTRL_OFFSET 0x0020
+
+/* Clock Module Register Addresses **********************************************************/
+
+#define AM335X_CM_PER_L4LS_CLKSTCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_L4LS_CLKSTCTRL_OFFSET)
+#define AM335X_CM_PER_L3S_CLKSTCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_L3S_CLKSTCTRL_OFFSET)
+#define AM335X_CM_PER_L3_CLKSTCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_L3_CLKSTCTRL_OFFSET)
+#define AM335X_CM_PER_CPGMAC0_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_CPGMAC0_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_LCDC_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_LCDC_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_USB0_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_USB0_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TPTC0_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TPTC0_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_EMIF_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_EMIF_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_OCMCRAM_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_OCMCRAM_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_GPMC_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_GPMC_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_MCASP0_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_MCASP0_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_UART5_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_UART5_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_MMC0_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_MMC0_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_ELM_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_ELM_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_I2C2_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_I2C2_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_I2C1_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_I2C1_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_SPI0_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_SPI0_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_SPI1_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_SPI1_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_L4LS_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_L4LS_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_MCASP1_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_MCASP1_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_UART1_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_UART1_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_UART2_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_UART2_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_UART3_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_UART3_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_UART4_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_UART4_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TIMER7_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TIMER7_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TIMER2_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TIMER2_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TIMER3_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TIMER3_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TIMER4_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TIMER4_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_GPIO1_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_GPIO1_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_GPIO2_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_GPIO2_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_GPIO3_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_GPIO3_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TPCC_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TPCC_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_DCAN0_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_DCAN0_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_DCAN1_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_DCAN1_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_EPWMSS1_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_EPWMSS1_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_EPWMSS0_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_EPWMSS0_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_EPWMSS2_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_EPWMSS2_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_L3_INSTR_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_L3_INSTR_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_L3_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_L3_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_IEEE5000_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_IEEE5000_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_PRU_ICSS_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_PRU_ICSS_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TIMER5_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TIMER5_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TIMER6_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TIMER6_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_MMC1_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_MMC1_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_MMC2_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_MMC2_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TPTC1_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TPTC1_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_TPTC2_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_TPTC2_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_SPINLOCK_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_SPINLOCK_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_MAILBOX0_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_MAILBOX0_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_L4HS_CLKSTCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_L4HS_CLKSTCTRL_OFFSET)
+#define AM335X_CM_PER_L4HS_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_L4HS_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_OCPWP_L3_CLKSTCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_OCPWP_L3_CLKSTCTRL_OFFSET)
+#define AM335X_CM_PER_OCPWP_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_OCPWP_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_PRU_ICSS_CLKSTCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_PRU_ICSS_CLKSTCTRL_OFFSET)
+#define AM335X_CM_PER_CPSW_CLKSTCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_CPSW_CLKSTCTRL_OFFSET)
+#define AM335X_CM_PER_LCDC_CLKSTCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_LCDC_CLKSTCTRL_OFFSET)
+#define AM335X_CM_PER_CLKDIV32K_CLKCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_CLKDIV32K_CLKCTRL_OFFSET)
+#define AM335X_CM_PER_CLK_24MHZ_CLKSTCTRL (AM335X_CM_PER_VADDR + AM335X_CM_PER_CLK_24MHZ_CLKSTCTRL_OFFSET)
+
+#define AM335X_CM_WKUP_CLKSTCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKSTCTRL_OFFSET)
+#define AM335X_CM_WKUP_CONTROL_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CONTROL_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_GPIO0_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_GPIO0_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_L4WKUP_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_L4WKUP_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_TIMER0_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_TIMER0_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_DEBUGSS_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_DEBUGSS_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_L3_AON_CLKSTCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_L3_AON_CLKSTCTRL_OFFSET)
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_MPU (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_AUTOIDLE_DPLL_MPU_OFFSET)
+#define AM335X_CM_WKUP_IDLEST_DPLL_MPU (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_IDLEST_DPLL_MPU_OFFSET)
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_MPU (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_MPU_OFFSET)
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_MPU (AM335X_CM_WKUP_VADDR + AM335X_CM-WKUP_SSC_MODFREQDIV_DPLL_MPU_OFFSET)
+#define AM335X_CM_WKUP_CLKSEL_DPLL_MPU (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKSEL_DPLL_MPU_OFFSET)
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_DDR (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_AUTOIDLE_DPLL_DDR_OFFSET)
+#define AM335X_CM_WKUP_IDLEST_DPLL_DDR (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_IDLEST_DPLL_DDR_OFFSET)
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_DDR (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_DDR_OFFSET)
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_DDR (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_DDR_OFFSET)
+#define AM335X_CM_WKUP_CLKSEL_DPLL_DDR (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKSEL_DPLL_DDR_OFFSET)
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_DISP (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_AUTOIDLE_DPLL_DISP_OFFSET)
+#define AM335X_CM_WKUP_IDLEST_DPLL_DISP (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_IDLEST_DPLL_DISP_OFFSET)
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_DISP (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_DISP_OFFSET)
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_DISP (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_DISP_OFFSET)
+#define AM335X_CM_WKUP_CLKSEL_DPLL_DISP (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKSEL_DPLL_DISP_OFFSET)
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_CORE (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_AUTOIDLE_DPLL_CORE_OFFSET)
+#define AM335X_CM_WKUP_IDLEST_DPLL_CORE (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_IDLEST_DPLL_CORE_OFFSET)
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_CORE (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_CORE_OFFSET)
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_CORE (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_CORE_OFFSET)
+#define AM335X_CM_WKUP_CLKSEL_DPLL_CORE (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKSEL_DPLL_CORE_OFFSET)
+#define AM335X_CM_WKUP_AUTOIDLE_DPLL_PER (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_AUTOIDLE_DPLL_PER_OFFSET)
+#define AM335X_CM_WKUP_IDLEST_DPLL_PER (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_IDLEST_DPLL_PER_OFFSET)
+#define AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_PER (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SSC_DELTAMSTEP_DPLL_PER_OFFSET)
+#define AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_PER (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SSC_MODFREQDIV_DPLL_PER_OFFSET)
+#define AM335X_CM_WKUP_CLKDCOLDO_DPLL_PER (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKDCOLDO_DPLL_PER_OFFSET)
+#define AM335X_CM_WKUP_DIV_M4_DPLL_CORE (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_DIV_M4_DPLL_CORE_OFFSET)
+#define AM335X_CM_WKUP_DIV_M5_DPLL_CORE (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_DIV_M5_DPLL_CORE_OFFSET)
+#define AM335X_CM_WKUP_CLKMODE_DPLL_MPU (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKMODE_DPLL_MPU_OFFSET)
+#define AM335X_CM_WKUP_CLKMODE_DPLL_PER (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKMODE_DPLL_PER_OFFSET)
+#define AM335X_CM_WKUP_CLKMODE_DPLL_CORE (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKMODE_DPLL_CORE_OFFSET)
+#define AM335X_CM_WKUP_CLKMODE_DPLL_DDR (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKMODE_DPLL_DDR_OFFSET)
+#define AM335X_CM_WKUP_CLKMODE_DPLL_DISP (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKMODE_DPLL_DISP_OFFSET)
+#define AM335X_CM_WKUP_CLKSEL_DPLL_PERIPH (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_CLKSEL_DPLL_PERIPH_OFFSET)
+#define AM335X_CM_WKUP_DIV_M2_DPLL_DDR (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_DIV_M2_DPLL_DDR_OFFSET)
+#define AM335X_CM_WKUP_DIV_M2_DPLL_DISP (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_DIV_M2_DPLL_DISP_OFFSET)
+#define AM335X_CM_WKUP_DIV_M2_DPLL_MPU (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_DIV_M2_DPLL_MPU_OFFSET)
+#define AM335X_CM_WKUP_DIV_M2_DPLL_PER (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_DIV_M2_DPLL_PER_OFFSET)
+#define AM335X_CM_WKUP_WKUP_M3_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_M3_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_UART0_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_UART0_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_I2C0_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_I2C0_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_ADC_TSC_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_SMARTREFLEX0_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SMARTREFLEX0_CLKCTRL _OFFSET)
+#define AM335X_CM_WKUP_TIMER1_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_TIMER1_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_SMARTREFLEX1_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_L4WKUP_AON_CLKSTCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_L4WKUP_AON_CLKSTCTRL_OFFSET)
+#define AM335X_CM_WKUP_WDT1_CLKCTRL (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_WDT1_CLKCTRL_OFFSET)
+#define AM335X_CM_WKUP_DIV_M6_DPLL_CORE (AM335X_CM_WKUP_VADDR + AM335X_CM_WKUP_DIV_M6_DPLL_CORE_OFFSET)
+
+#define AM335X_CM_DPLL_CLKSEL_TIMER7_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_TIMER7_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_TIMER2_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_TIMER2_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_TIMER3_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_TIMER3_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_TIMER4_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_TIMER4_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_MAC_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_MAC_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_TIMER5_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_TIMER5_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_TIMER6_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_TIMER6_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_CPTS_RFT_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_CPTS_RFT_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_TIMER1MS_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_TIMER1MS_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_GFX_FCLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_GFX_FCLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_PRU_ICSS_OCP_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_PRU_ICSS_OCP_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_LCDC_PIXEL_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_LCDC_PIXEL_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_WDT1_CLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_WDT1_CLK_OFFSET)
+#define AM335X_CM_DPLL_CLKSEL_GPIO0_DBCLK (AM335X_CM_DPLL_VADDR + AM335X_CM_DPLL_CLKSEL_GPIO0_DBCLK_OFFSET)
+
+#define AM335X_CM_MPU_CLKSTCTRL (AM335X_CM_MPU_VADDR + AM335X_CM_MPU_CLKSTCTRL_OFFSET)
+#define AM335X_CM_MPU_CLKCTRL (AM335X_CM_MPU_VADDR + AM335X_CM_MPU_CLKCTRL_OFFSET)
+
+#define AM335X_CM_DEVICE_CLKOUT_CTRL (AM335X_CM_DEVICE_VADDR + AM335X_CM_DEVICE_CLKOUT_CTRL_OFFSET)
+
+#define AM335X_CM_RTC_CLKCTRL (AM335X_CM_RTC_VADDR + AM335X_CM_RTC_CLKCTRL_OFFSET)
+#define AM335X_CM_RTC_CLKSTCTRL (AM335X_CM_RTC_VADDR + AM335X_CM_RTC_CLKSTCTRL_OFFSET)
+
+#define AM335X_CM_GFX_L3_CLKSTCTRL (AM335X_CM_GFX_VADDR + AM335X_CM_GFX_L3_CLKSTCTRL_OFFSET)
+#define AM335X_CM_GFX_CLKCTRL (AM335X_CM_GFX_VADDR + AM335X_CM_GFX_CLKCTRL_OFFSET)
+#define AM335X_CM_GFX_L4LS_CLKSTCTRL (AM335X_CM_GFX_VADDR + AM335X_CM_GFX_L4LS_CLKSTCTRL_OFFSET)
+#define AM335X_CM_GFX_MMUCFG_CLKCTRL (AM335X_CM_GFX_VADDR + AM335X_CM_GFX_MMUCFG_CLKCTRL_OFFSET)
+#define AM335X_CM_GFX_MMUDATA_CLKCTRL (AM335X_CM_GFX_VADDR + AM335X_CM_GFX_MMUDATA_CLKCTRL_OFFSET)
+
+#define AM335X_CM_CEFUSE_CLKSTCTRL (AM335X_CM_CEFUSE_VADDR + AM335X_CM_CEFUSE_CLKSTCTRL_OFFSET)
+#define AM335X_CM_CEFUSE_CLKCTRL (AM335X_CM_CEFUSE_VADDR + AM335X_CM_CEFUSE_CLKCTRL_OFFSET)
+
+/* Clock Module Register Bit Definitions **************************************************/
+
+#define CM_WKUP_CLKCTRL_MODULEMODE_SHIFT (0) /* Bits 0-1: Control the way mandatory clocks are managed */
+#define CM_WKUP_CLKCTRL_MODULEMODE_MASK (3 << CM_WKUP_CLKCTRL_MODULEMODE_SHIFT)
+# define CM_WKUP_CLKCTRL_MODULEMODE_DISABLE (0 << CM_WKUP_CLKCTRL_MODULEMODE_SHIFT) /* Module is disable by SW */
+# define CM_WKUP_CLKCTRL_MODULEMODE_ENABLE (2 << CM_WKUP_CLKCTRL_MODULEMODE_SHIFT) /* Module is explicitly enabled */
+#define CM_WKUP_CLKCTRL_IDLEST_SHIFT (16) /* Bits 16-17: Module idle status. */
+#define CM_WKUP_CLKCTRL_IDLEST_MASK (3 << CM_WKUP_CLKCTRL_IDLEST_SHIFT)
+# define CM_WKUP_CLKCTRL_IDLEST_FUNC (0 << CM_WKUP_CLKCTRL_IDLEST_SHIFT) /* Module is fully functional, including OCP */
+# define CM_WKUP_CLKCTRL_IDLEST_TRANS (1 << CM_WKUP_CLKCTRL_IDLEST_SHIFT) /* Module is performing transition: wakeup, or sleep, or sleep abortion */
+# define CM_WKUP_CLKCTRL_IDLEST_IDLE (2 << CM_WKUP_CLKCTRL_IDLEST_SHIFT) /* Module is in Idle mode (only OCP part) */
+# define CM_WKUP_CLKCTRL_IDLEST_DISABLED (3 << CM_WKUP_CLKCTRL_IDLEST_SHIFT) /* Module is disabled and cannot be accessed */
+#define CM_WKUP_CLKCTRL_STBYST (1 << 18) /* Bit 18: Module standby status. */
+
+#define CM_DPLL_DMTIMER1MS_CLKSEL_SHIFT (0) /* Bits 0-2: Mux select line for DMTIMER_1MS clock */
+#define CM_DPLL_DMTIMER1MS_CLKSEL_MASK (7 << CM_DPLL_DMTIMER1MS_CLKSEL_SHIFT)
+# define CM_DPLL_DMTIMER1_CLKSEL_CLK_M_OSC (0 << CM_DPLL_DMTIMER1MS_CLKSEL_SHIFT) /* Select CLK_M_OSC clock */
+# define CM_DPLL_DMTIMER1_CLKSEL_CLK_32KHZ (1 << CM_DPLL_DMTIMER1MS_CLKSEL_SHIFT) /* Select CLK_32KHZ clock */
+# define CM_DPLL_DMTIMER1_CLKSEL_TCLKIN (2 << CM_DPLL_DMTIMER1MS_CLKSEL_SHIFT) /* Select TCLKIN clock */
+# define CM_DPLL_DMTIMER1_CLKSEL_CLK_RC32K (3 << CM_DPLL_DMTIMER1MS_CLKSEL_SHIFT) /* Select CLK_RC32K clock */
+# define CM_DPLL_DMTIMER1_CLKSEL_CLK_32768 (4 << CM_DPLL_DMTIMER1MS_CLKSEL_SHIFT) /* Selects the CLK_32768 from 32KHz Crystal Osc */
+
+#endif /* __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_CM_H */
diff --git a/arch/arm/src/am335x/hardware/am335x_dcan.h b/arch/arm/src/am335x/hardware/am335x_dcan.h
new file mode 100644
index 00000000000..e8c6e803077
--- /dev/null
+++ b/arch/arm/src/am335x/hardware/am335x_dcan.h
@@ -0,0 +1,423 @@
+/********************************************************************************************
+ * arch/arm/src/am335x/hardware/am335x_cm.h
+ *
+ * Copyright (C) 2019 Petro Karashchenko. All rights reserved.
+ * Author: Petro Karashchenko
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ********************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_DCAN_H
+#define __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_DCAN_H
+
+/********************************************************************************************
+ * Included Files
+ ********************************************************************************************/
+
+#include
+#include
+
+/********************************************************************************************
+ * Pre-processor Definitions
+ ********************************************************************************************/
+
+/* Register offsets *****************************************************************/
+
+#define AM335X_DCAN_CTL_OFFSET 0x0000 /* CAN Control Register */
+#define AM335X_DCAN_ES_OFFSET 0x0004 /* Error and Status Register */
+#define AM335X_DCAN_ERRC_OFFSET 0x0008 /* Error Counter Register */
+#define AM335X_DCAN_BTR_OFFSET 0x000c /* Bit Timing Register */
+#define AM335X_DCAN_INT_OFFSET 0x0010 /* Interrupt Register */
+#define AM335X_DCAN_TEST_OFFSET 0x0014 /* Test Register */
+#define AM335X_DCAN_PERR_OFFSET 0x001c /* Parity Error Code Register */
+#define AM335X_DCAN_ABOTR_OFFSET 0x0080 /* Auto-Bus-On Time Register */
+#define AM335X_DCAN_TXRQ_X_OFFSET 0x0084 /* Transmission Request X Register */
+#define AM335X_DCAN_TXRQ12_OFFSET 0x0088 /* Transmission Request Register 12 */
+#define AM335X_DCAN_TXRQ34_OFFSET 0x008c /* Transmission Request Register 34 */
+#define AM335X_DCAN_TXRQ56_OFFSET 0x0090 /* Transmission Request Register 56 */
+#define AM335X_DCAN_TXRQ78_OFFSET 0x0094 /* Transmission Request Register 78 */
+#define AM335X_DCAN_NWDAT_X_OFFSET 0x0098 /* New Data X Register */
+#define AM335X_DCAN_NWDAT12_OFFSET 0x009c /* New Data Register 12 */
+#define AM335X_DCAN_NWDAT34_OFFSET 0x00a0 /* New Data Register 34 */
+#define AM335X_DCAN_NWDAT56_OFFSET 0x00a4 /* New Data Register 56 */
+#define AM335X_DCAN_NWDAT78_OFFSET 0x00a8 /* New Data Register 78 */
+#define AM335X_DCAN_INTPND_X_OFFSET 0x00ac /* Interrupt Pending X Register */
+#define AM335X_DCAN_INTPND12_OFFSET 0x00b0 /* Interrupt Pending Register 12 */
+#define AM335X_DCAN_INTPND34_OFFSET 0x00b4 /* Interrupt Pending Register 34 */
+#define AM335X_DCAN_INTPND56_OFFSET 0x00b8 /* Interrupt Pending Register 56 */
+#define AM335X_DCAN_INTPND78_OFFSET 0x00bc /* Interrupt Pending Register 78 */
+#define AM335X_DCAN_MSGVAL_X_OFFSET 0x00c0 /* Message Valid X Register */
+#define AM335X_DCAN_MSGVAL12_OFFSET 0x00c4 /* Message Valid Register 12 */
+#define AM335X_DCAN_MSGVAL34_OFFSET 0x00c8 /* Message Valid Register 34 */
+#define AM335X_DCAN_MSGVAL56_OFFSET 0x00cc /* Message Valid Register 56 */
+#define AM335X_DCAN_MSGVAL78_OFFSET 0x00d0 /* Message Valid Register 78 */
+#define AM335X_DCAN_INTMUX12_OFFSET 0x00d8 /* Interrupt Multiplexer Register 12 */
+#define AM335X_DCAN_INTMUX34_OFFSET 0x00dc /* Interrupt Multiplexer Register 34 */
+#define AM335X_DCAN_INTMUX56_OFFSET 0x00e0 /* Interrupt Multiplexer Register 56 */
+#define AM335X_DCAN_INTMUX78_OFFSET 0x00e4 /* Interrupt Multiplexer Register 78 */
+#define AM335X_DCAN_IF1CMD_OFFSET 0x0100 /* IF1 Command Registers */
+#define AM335X_DCAN_IF1MSK_OFFSET 0x0104 /* IF1 Mask Register */
+#define AM335X_DCAN_IF1ARB_OFFSET 0x0108 /* IF1 Arbitration Register */
+#define AM335X_DCAN_IF1MCTL_OFFSET 0x010c /* IF1 Message Control Register */
+#define AM335X_DCAN_IF1DATA_OFFSET 0x0110 /* IF1 Data A Register */
+#define AM335X_DCAN_IF1DATB_OFFSET 0x0114 /* IF1 Data B Register */
+#define AM335X_DCAN_IF2CMD_OFFSET 0x0120 /* IF2 Command Registers */
+#define AM335X_DCAN_IF2MSK_OFFSET 0x0124 /* IF2 Mask Register */
+#define AM335X_DCAN_IF2ARB_OFFSET 0x0128 /* IF2 Arbitration Register */
+#define AM335X_DCAN_IF2MCTL_OFFSET 0x012c /* IF2 Message Control Register */
+#define AM335X_DCAN_IF2DATA_OFFSET 0x0130 /* IF2 Data A Register */
+#define AM335X_DCAN_IF2DATB_OFFSET 0x0134 /* IF2 Data B Register */
+#define AM335X_DCAN_IF3OBS_OFFSET 0x0140 /* IF3 Observation Register */
+#define AM335X_DCAN_IF3MSK_OFFSET 0x0144 /* IF3 Mask Register */
+#define AM335X_DCAN_IF3ARB_OFFSET 0x0148 /* IF3 Arbitration Register */
+#define AM335X_DCAN_IF3MCTL_OFFSET 0x014c /* IF3 Message Control Register */
+#define AM335X_DCAN_IF3DATA_OFFSET 0x0150 /* IF3 Data A Register */
+#define AM335X_DCAN_IF3DATB_OFFSET 0x0154 /* IF3 Data B Register */
+#define AM335X_DCAN_IF3UPD12_OFFSET 0x0160 /* IF3 Update Enable Register 12 */
+#define AM335X_DCAN_IF3UPD34_OFFSET 0x0164 /* IF3 Update Enable Register 34 */
+#define AM335X_DCAN_IF3UPD56_OFFSET 0x0168 /* IF3 Update Enable Register 56 */
+#define AM335X_DCAN_IF3UPD78_OFFSET 0x016c /* IF3 Update Enable Register 78 */
+#define AM335X_DCAN_TIOC_OFFSET 0x01e0 /* CAN TX IO Control Register */
+#define AM335X_DCAN_RIOC_OFFSET 0x01e4 /* CAN RX IO Control Register */
+
+#define AM335X_DCAN_TXRQ_OFFSET(n) (0x0088 + ((((unsigned int)(n) - 1) >> 5) << 2))
+#define AM335X_DCAN_NWDAT_OFFSET(n) (0x009c + ((((unsigned int)(n) - 1) >> 5) << 2))
+#define AM335X_DCAN_INTPND_OFFSET(n) (0x00b0 + ((((unsigned int)(n) - 1) >> 5) << 2))
+#define AM335X_DCAN_MSGVAL_OFFSET(n) (0x00c4 + ((((unsigned int)(n) - 1) >> 5) << 2))
+#define AM335X_DCAN_INTMUX_OFFSET(n) (0x00d8 + ((((unsigned int)(n) - 1) >> 5) << 2))
+#define AM335X_DCAN_IFCMD_OFFSET(n) (0x0100 + ((unsigned int)(n) - 1) * 0x20)
+#define AM335X_DCAN_IFMSK_OFFSET(n) (0x0104 + ((unsigned int)(n) - 1) * 0x20)
+#define AM335X_DCAN_IFARB_OFFSET(n) (0x0108 + ((unsigned int)(n) - 1) * 0x20)
+#define AM335X_DCAN_IFMCTL_OFFSET(n) (0x010c + ((unsigned int)(n) - 1) * 0x20)
+#define AM335X_DCAN_IFDATA_OFFSET(n) (0x0110 + ((unsigned int)(n) - 1) * 0x20)
+#define AM335X_DCAN_IFDATB_OFFSET(n) (0x0114 + ((unsigned int)(n) - 1) * 0x20)
+#define AM335X_DCAN_IF3UPD_OFFSET(n) (0x0160 + ((((unsigned int)(n) - 1) >> 5) << 2))
+
+/* Register virtual addresses *******************************************************/
+
+#define AM335X_DCAN0_CTL (AM335X_DCAN0_VADDR + AM335X_DCAN_CTL_OFFSET)
+#define AM335X_DCAN0_ES (AM335X_DCAN0_VADDR + AM335X_DCAN_ES_OFFSET)
+#define AM335X_DCAN0_ERRC (AM335X_DCAN0_VADDR + AM335X_DCAN_ERRC_OFFSET)
+#define AM335X_DCAN0_BTR (AM335X_DCAN0_VADDR + AM335X_DCAN_BTR_OFFSET)
+#define AM335X_DCAN0_INT (AM335X_DCAN0_VADDR + AM335X_DCAN_INT_OFFSET)
+#define AM335X_DCAN0_TEST (AM335X_DCAN0_VADDR + AM335X_DCAN_TEST_OFFSET)
+#define AM335X_DCAN0_PERR (AM335X_DCAN0_VADDR + AM335X_DCAN_PERR_OFFSET)
+#define AM335X_DCAN0_ABOTR (AM335X_DCAN0_VADDR + AM335X_DCAN_ABOTR_OFFSET)
+#define AM335X_DCAN0_TXRQ_X (AM335X_DCAN0_VADDR + AM335X_DCAN_TXRQ_X_OFFSET)
+#define AM335X_DCAN0_TXRQ12 (AM335X_DCAN0_VADDR + AM335X_DCAN_TXRQ12_OFFSET)
+#define AM335X_DCAN0_TXRQ34 (AM335X_DCAN0_VADDR + AM335X_DCAN_TXRQ34_OFFSET)
+#define AM335X_DCAN0_TXRQ56 (AM335X_DCAN0_VADDR + AM335X_DCAN_TXRQ56_OFFSET)
+#define AM335X_DCAN0_TXRQ78 (AM335X_DCAN0_VADDR + AM335X_DCAN_TXRQ78_OFFSET)
+#define AM335X_DCAN0_NWDAT_X (AM335X_DCAN0_VADDR + AM335X_DCAN_NWDAT_X_OFFSET)
+#define AM335X_DCAN0_NWDAT12 (AM335X_DCAN0_VADDR + AM335X_DCAN_NWDAT12_OFFSET)
+#define AM335X_DCAN0_NWDAT34 (AM335X_DCAN0_VADDR + AM335X_DCAN_NWDAT34_OFFSET)
+#define AM335X_DCAN0_NWDAT56 (AM335X_DCAN0_VADDR + AM335X_DCAN_NWDAT56_OFFSET)
+#define AM335X_DCAN0_NWDAT78 (AM335X_DCAN0_VADDR + AM335X_DCAN_NWDAT78_OFFSET)
+#define AM335X_DCAN0_INTPND_X (AM335X_DCAN0_VADDR + AM335X_DCAN_INTPND_X_OFFSET)
+#define AM335X_DCAN0_INTPND12 (AM335X_DCAN0_VADDR + AM335X_DCAN_INTPND12_OFFSET)
+#define AM335X_DCAN0_INTPND34 (AM335X_DCAN0_VADDR + AM335X_DCAN_INTPND34_OFFSET)
+#define AM335X_DCAN0_INTPND56 (AM335X_DCAN0_VADDR + AM335X_DCAN_INTPND56_OFFSET)
+#define AM335X_DCAN0_INTPND78 (AM335X_DCAN0_VADDR + AM335X_DCAN_INTPND78_OFFSET)
+#define AM335X_DCAN0_MSGVAL_X (AM335X_DCAN0_VADDR + AM335X_DCAN_MSGVAL_X_OFFSET)
+#define AM335X_DCAN0_MSGVAL12 (AM335X_DCAN0_VADDR + AM335X_DCAN_MSGVAL12_OFFSET)
+#define AM335X_DCAN0_MSGVAL34 (AM335X_DCAN0_VADDR + AM335X_DCAN_MSGVAL34_OFFSET)
+#define AM335X_DCAN0_MSGVAL56 (AM335X_DCAN0_VADDR + AM335X_DCAN_MSGVAL56_OFFSET)
+#define AM335X_DCAN0_MSGVAL78 (AM335X_DCAN0_VADDR + AM335X_DCAN_MSGVAL78_OFFSET)
+#define AM335X_DCAN0_INTMUX12 (AM335X_DCAN0_VADDR + AM335X_DCAN_INTMUX12_OFFSET)
+#define AM335X_DCAN0_INTMUX34 (AM335X_DCAN0_VADDR + AM335X_DCAN_INTMUX34_OFFSET)
+#define AM335X_DCAN0_INTMUX56 (AM335X_DCAN0_VADDR + AM335X_DCAN_INTMUX56_OFFSET)
+#define AM335X_DCAN0_INTMUX78 (AM335X_DCAN0_VADDR + AM335X_DCAN_INTMUX78_OFFSET)
+#define AM335X_DCAN0_IF1CMD (AM335X_DCAN0_VADDR + AM335X_DCAN_IF1CMD_OFFSET)
+#define AM335X_DCAN0_IF1MSK (AM335X_DCAN0_VADDR + AM335X_DCAN_IF1MSK_OFFSET)
+#define AM335X_DCAN0_IF1ARB (AM335X_DCAN0_VADDR + AM335X_DCAN_IF1ARB_OFFSET)
+#define AM335X_DCAN0_IF1MCTL (AM335X_DCAN0_VADDR + AM335X_DCAN_IF1MCTL_OFFSET)
+#define AM335X_DCAN0_IF1DATA (AM335X_DCAN0_VADDR + AM335X_DCAN_IF1DATA_OFFSET)
+#define AM335X_DCAN0_IF1DATB (AM335X_DCAN0_VADDR + AM335X_DCAN_IF1DATB_OFFSET)
+#define AM335X_DCAN0_IF2CMD (AM335X_DCAN0_VADDR + AM335X_DCAN_IF2CMD_OFFSET)
+#define AM335X_DCAN0_IF2MSK (AM335X_DCAN0_VADDR + AM335X_DCAN_IF2MSK_OFFSET)
+#define AM335X_DCAN0_IF2ARB (AM335X_DCAN0_VADDR + AM335X_DCAN_IF2ARB_OFFSET)
+#define AM335X_DCAN0_IF2MCTL (AM335X_DCAN0_VADDR + AM335X_DCAN_IF2MCTL_OFFSET)
+#define AM335X_DCAN0_IF2DATA (AM335X_DCAN0_VADDR + AM335X_DCAN_IF2DATA_OFFSET)
+#define AM335X_DCAN0_IF2DATB (AM335X_DCAN0_VADDR + AM335X_DCAN_IF2DATB_OFFSET)
+#define AM335X_DCAN0_IF3OBS (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3OBS_OFFSET)
+#define AM335X_DCAN0_IF3MSK (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3MSK_OFFSET)
+#define AM335X_DCAN0_IF3ARB (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3ARB_OFFSET)
+#define AM335X_DCAN0_IF3MCTL (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3MCTL_OFFSET)
+#define AM335X_DCAN0_IF3DATA (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3DATA_OFFSET)
+#define AM335X_DCAN0_IF3DATB (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3DATB_OFFSET)
+#define AM335X_DCAN0_IF3UPD12 (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3UPD12_OFFSET)
+#define AM335X_DCAN0_IF3UPD34 (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3UPD34_OFFSET)
+#define AM335X_DCAN0_IF3UPD56 (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3UPD56_OFFSET)
+#define AM335X_DCAN0_IF3UPD78 (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3UPD78_OFFSET)
+#define AM335X_DCAN0_TIOC (AM335X_DCAN0_VADDR + AM335X_DCAN_TIOC_OFFSET)
+#define AM335X_DCAN0_RIOC (AM335X_DCAN0_VADDR + AM335X_DCAN_RIOC_OFFSET)
+
+#define AM335X_DCAN0_TXRQ(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_TXRQ_OFFSET(n))
+#define AM335X_DCAN0_NWDAT(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_NWDAT_OFFSET(n))
+#define AM335X_DCAN0_INTPND(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_INTPND_OFFSET(n))
+#define AM335X_DCAN0_MSGVAL(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_MSGVAL_OFFSET(n))
+#define AM335X_DCAN0_INTMUX(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_INTMUX_OFFSET(n))
+#define AM335X_DCAN0_IFCMD(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_IFCMD_OFFSET(n))
+#define AM335X_DCAN0_IFMSK(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_IFMSK_OFFSET(n))
+#define AM335X_DCAN0_IFARB(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_IFARB_OFFSET(n))
+#define AM335X_DCAN0_IFMCTL(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_IFMCTL_OFFSET(n))
+#define AM335X_DCAN0_IFDATA(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_IFDATA_OFFSET(n))
+#define AM335X_DCAN0_IFDATB(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_IFDATB_OFFSET(n))
+#define AM335X_DCAN0_IF3UPD(n) (AM335X_DCAN0_VADDR + AM335X_DCAN_IF3UPD_OFFSET(n))
+
+#define AM335X_DCAN1_CTL (AM335X_DCAN1_VADDR + AM335X_DCAN_CTL_OFFSET)
+#define AM335X_DCAN1_ES (AM335X_DCAN1_VADDR + AM335X_DCAN_ES_OFFSET)
+#define AM335X_DCAN1_ERRC (AM335X_DCAN1_VADDR + AM335X_DCAN_ERRC_OFFSET)
+#define AM335X_DCAN1_BTR (AM335X_DCAN1_VADDR + AM335X_DCAN_BTR_OFFSET)
+#define AM335X_DCAN1_INT (AM335X_DCAN1_VADDR + AM335X_DCAN_INT_OFFSET)
+#define AM335X_DCAN1_TEST (AM335X_DCAN1_VADDR + AM335X_DCAN_TEST_OFFSET)
+#define AM335X_DCAN1_PERR (AM335X_DCAN1_VADDR + AM335X_DCAN_PERR_OFFSET)
+#define AM335X_DCAN1_ABOTR (AM335X_DCAN1_VADDR + AM335X_DCAN_ABOTR_OFFSET)
+#define AM335X_DCAN1_TXRQ_X (AM335X_DCAN1_VADDR + AM335X_DCAN_TXRQ_X_OFFSET)
+#define AM335X_DCAN1_TXRQ12 (AM335X_DCAN1_VADDR + AM335X_DCAN_TXRQ12_OFFSET)
+#define AM335X_DCAN1_TXRQ34 (AM335X_DCAN1_VADDR + AM335X_DCAN_TXRQ34_OFFSET)
+#define AM335X_DCAN1_TXRQ56 (AM335X_DCAN1_VADDR + AM335X_DCAN_TXRQ56_OFFSET)
+#define AM335X_DCAN1_TXRQ78 (AM335X_DCAN1_VADDR + AM335X_DCAN_TXRQ78_OFFSET)
+#define AM335X_DCAN1_NWDAT_X (AM335X_DCAN1_VADDR + AM335X_DCAN_NWDAT_X_OFFSET)
+#define AM335X_DCAN1_NWDAT12 (AM335X_DCAN1_VADDR + AM335X_DCAN_NWDAT12_OFFSET)
+#define AM335X_DCAN1_NWDAT34 (AM335X_DCAN1_VADDR + AM335X_DCAN_NWDAT34_OFFSET)
+#define AM335X_DCAN1_NWDAT56 (AM335X_DCAN1_VADDR + AM335X_DCAN_NWDAT56_OFFSET)
+#define AM335X_DCAN1_NWDAT78 (AM335X_DCAN1_VADDR + AM335X_DCAN_NWDAT78_OFFSET)
+#define AM335X_DCAN1_INTPND_X (AM335X_DCAN1_VADDR + AM335X_DCAN_INTPND_X_OFFSET)
+#define AM335X_DCAN1_INTPND12 (AM335X_DCAN1_VADDR + AM335X_DCAN_INTPND12_OFFSET)
+#define AM335X_DCAN1_INTPND34 (AM335X_DCAN1_VADDR + AM335X_DCAN_INTPND34_OFFSET)
+#define AM335X_DCAN1_INTPND56 (AM335X_DCAN1_VADDR + AM335X_DCAN_INTPND56_OFFSET)
+#define AM335X_DCAN1_INTPND78 (AM335X_DCAN1_VADDR + AM335X_DCAN_INTPND78_OFFSET)
+#define AM335X_DCAN1_MSGVAL_X (AM335X_DCAN1_VADDR + AM335X_DCAN_MSGVAL_X_OFFSET)
+#define AM335X_DCAN1_MSGVAL12 (AM335X_DCAN1_VADDR + AM335X_DCAN_MSGVAL12_OFFSET)
+#define AM335X_DCAN1_MSGVAL34 (AM335X_DCAN1_VADDR + AM335X_DCAN_MSGVAL34_OFFSET)
+#define AM335X_DCAN1_MSGVAL56 (AM335X_DCAN1_VADDR + AM335X_DCAN_MSGVAL56_OFFSET)
+#define AM335X_DCAN1_MSGVAL78 (AM335X_DCAN1_VADDR + AM335X_DCAN_MSGVAL78_OFFSET)
+#define AM335X_DCAN1_INTMUX12 (AM335X_DCAN1_VADDR + AM335X_DCAN_INTMUX12_OFFSET)
+#define AM335X_DCAN1_INTMUX34 (AM335X_DCAN1_VADDR + AM335X_DCAN_INTMUX34_OFFSET)
+#define AM335X_DCAN1_INTMUX56 (AM335X_DCAN1_VADDR + AM335X_DCAN_INTMUX56_OFFSET)
+#define AM335X_DCAN1_INTMUX78 (AM335X_DCAN1_VADDR + AM335X_DCAN_INTMUX78_OFFSET)
+#define AM335X_DCAN1_IF1CMD (AM335X_DCAN1_VADDR + AM335X_DCAN_IF1CMD_OFFSET)
+#define AM335X_DCAN1_IF1MSK (AM335X_DCAN1_VADDR + AM335X_DCAN_IF1MSK_OFFSET)
+#define AM335X_DCAN1_IF1ARB (AM335X_DCAN1_VADDR + AM335X_DCAN_IF1ARB_OFFSET)
+#define AM335X_DCAN1_IF1MCTL (AM335X_DCAN1_VADDR + AM335X_DCAN_IF1MCTL_OFFSET)
+#define AM335X_DCAN1_IF1DATA (AM335X_DCAN1_VADDR + AM335X_DCAN_IF1DATA_OFFSET)
+#define AM335X_DCAN1_IF1DATB (AM335X_DCAN1_VADDR + AM335X_DCAN_IF1DATB_OFFSET)
+#define AM335X_DCAN1_IF2CMD (AM335X_DCAN1_VADDR + AM335X_DCAN_IF2CMD_OFFSET)
+#define AM335X_DCAN1_IF2MSK (AM335X_DCAN1_VADDR + AM335X_DCAN_IF2MSK_OFFSET)
+#define AM335X_DCAN1_IF2ARB (AM335X_DCAN1_VADDR + AM335X_DCAN_IF2ARB_OFFSET)
+#define AM335X_DCAN1_IF2MCTL (AM335X_DCAN1_VADDR + AM335X_DCAN_IF2MCTL_OFFSET)
+#define AM335X_DCAN1_IF2DATA (AM335X_DCAN1_VADDR + AM335X_DCAN_IF2DATA_OFFSET)
+#define AM335X_DCAN1_IF2DATB (AM335X_DCAN1_VADDR + AM335X_DCAN_IF2DATB_OFFSET)
+#define AM335X_DCAN1_IF3OBS (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3OBS_OFFSET)
+#define AM335X_DCAN1_IF3MSK (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3MSK_OFFSET)
+#define AM335X_DCAN1_IF3ARB (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3ARB_OFFSET)
+#define AM335X_DCAN1_IF3MCTL (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3MCTL_OFFSET)
+#define AM335X_DCAN1_IF3DATA (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3DATA_OFFSET)
+#define AM335X_DCAN1_IF3DATB (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3DATB_OFFSET)
+#define AM335X_DCAN1_IF3UPD12 (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3UPD12_OFFSET)
+#define AM335X_DCAN1_IF3UPD34 (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3UPD34_OFFSET)
+#define AM335X_DCAN1_IF3UPD56 (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3UPD56_OFFSET)
+#define AM335X_DCAN1_IF3UPD78 (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3UPD78_OFFSET)
+#define AM335X_DCAN1_TIOC (AM335X_DCAN1_VADDR + AM335X_DCAN_TIOC_OFFSET)
+#define AM335X_DCAN1_RIOC (AM335X_DCAN1_VADDR + AM335X_DCAN_RIOC_OFFSET)
+
+#define AM335X_DCAN1_TXRQ(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_TXRQ_OFFSET(n))
+#define AM335X_DCAN1_NWDAT(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_NWDAT_OFFSET(n))
+#define AM335X_DCAN1_INTPND(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_INTPND_OFFSET(n))
+#define AM335X_DCAN1_MSGVAL(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_MSGVAL_OFFSET(n))
+#define AM335X_DCAN1_INTMUX(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_INTMUX_OFFSET(n))
+#define AM335X_DCAN1_IFCMD(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_IFCMD_OFFSET(n))
+#define AM335X_DCAN1_IFMSK(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_IFMSK_OFFSET(n))
+#define AM335X_DCAN1_IFARB(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_IFARB_OFFSET(n))
+#define AM335X_DCAN1_IFMCTL(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_IFMCTL_OFFSET(n))
+#define AM335X_DCAN1_IFDATA(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_IFDATA_OFFSET(n))
+#define AM335X_DCAN1_IFDATB(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_IFDATB_OFFSET(n))
+#define AM335X_DCAN1_IF3UPD(n) (AM335X_DCAN1_VADDR + AM335X_DCAN_IF3UPD_OFFSET(n))
+
+/* Register bit field definitions ***************************************************/
+
+#define DCAN_CTL_INIT (1 << 0) /* Bit 0: Initialization mode */
+#define DCAN_CTL_IE0 (1 << 1) /* Bit 1: Interrupt line 0 enable */
+#define DCAN_CTL_SIE (1 << 2) /* Bit 2: Status change interrupt enable */
+#define DCAN_CTL_EIE (1 << 3) /* Bit 3: Error interrupt enable */
+#define DCAN_CTL_DAR (1 << 5) /* Bit 5: Disable automatic retransmission */
+#define DCAN_CTL_CCE (1 << 6) /* Bit 6: Configuration change enable */
+#define DCAN_CTL_TEST (1 << 7) /* Bit 7: Test mode enable */
+#define DCAN_CTL_IDS (1 << 8) /* Bit 8: Interruption debug support enable */
+#define DCAN_CTL_ABO (1 << 9) /* Bit 9: Auto-Bus-On enable */
+#define DCAN_CTL_PMD_SHIFT (10) /* Bits 10-13: Parity on/off. */
+#define DCAN_CTL_PMD_MASK (15 << DCAN_CTL_PMD_SHIFT)
+# define DCAN_CTL_PMD_OFF (5 << DCAN_CTL_PMD_SHIFT) /* Parity function disabled */
+# define DCAN_CTL_PMD_ON (10 << DCAN_CTL_PMD_SHIFT) /* Parity function enabled */
+#define DCAN_CTL_SWR (1 << 15) /* Bit 15: Software reset enable */
+#define DCAN_CTL_INITDBG (1 << 16) /* Bit 16: Internal init state while debug access */
+#define DCAN_CTL_IE1 (1 << 17) /* Bit 17: Interrupt line 1 enable */
+#define DCAN_CTL_DE1 (1 << 18) /* Bit 18: Enable DMA request line for IF1 */
+#define DCAN_CTL_DE2 (1 << 19) /* Bit 19: Enable DMA request line for IF2 */
+#define DCAN_CTL_DE3 (1 << 20) /* Bit 20: Enable DMA request line for IF3 */
+#define DCAN_CTL_PDR (1 << 24) /* Bit 24: Request for local low power-down mode */
+#define DCAN_CTL_WUBA (1 << 25) /* Bit 25: Automatic wake up on bus activity when in local power-down mode */
+
+#define DCAN_ES_LEC_SHIFT (0) /* Bits 0-2: Last error code. */
+#define DCAN_ES_LEC_MASK (7 << DCAN_ES_LEC_SHIFT)
+# define DCAN_ES_LEC_NO_ERROR (0 << DCAN_ES_LEC_SHIFT) /* No error */
+# define DCAN_ES_LEC_STUFF_ERROR (1 << DCAN_ES_LEC_SHIFT) /* Stuff error */
+# define DCAN_ES_LEC_FORM_ERROR (2 << DCAN_ES_LEC_SHIFT) /* Form error */
+# define DCAN_ES_LEC_ACK_ERROR (3 << DCAN_ES_LEC_SHIFT) /* Ack error */
+# define DCAN_ES_LEC_BIT1_ERROR (4 << DCAN_ES_LEC_SHIFT) /* Bit1 error */
+# define DCAN_ES_LEC_BIT0_ERROR (5 << DCAN_ES_LEC_SHIFT) /* Bit0 error */
+# define DCAN_ES_LEC_CRC_ERROR (6 << DCAN_ES_LEC_SHIFT) /* CRC error */
+# define DCAN_ES_LEC_NO_EVENT (7 << DCAN_ES_LEC_SHIFT) /* No CAN bus event since last read */
+#define DCAN_ES_TX_OK (1 << 3) /* Bit 3: Transmitted a message successfully */
+#define DCAN_ES_RX_OK (1 << 4) /* Bit 4: Received a message successfully */
+#define DCAN_ES_EPASSIVE (1 << 5) /* Bit 5: Error passive state */
+#define DCAN_ES_EWARN (1 << 6) /* Bit 6: Warning state */
+#define DCAN_ES_BUSOFF (1 << 7) /* Bit 7: Bus-Off state */
+#define DCAN_ES_PER (1 << 8) /* Bit 8: Parity error detected */
+#define DCAN_ES_WKUP_PND (1 << 9) /* Bit 9: Wake up pending */
+#define DCAN_ES_PDA (1 << 10) /* Bit 10: Local power-down mode acknowledge */
+
+#define DCAN_ERRC_TEC_SHIFT (0) /* Bits 10-13: Parity on/off. */
+#define DCAN_ERRC_TEC_MASK (255 << DCAN_ERRC_TEC_SHIFT)
+#define DCAN_ERRC_REC_SHIFT (8) /* Bits 10-13: Parity on/off. */
+#define DCAN_ERRC_REC_MASK (255 << DCAN_ERRC_REC_SHIFT)
+#define DCAN_ERRC_RP (1 << 15) /* Bit 15: Receive error passive */
+
+#define DCAN_BTR_BRP_SHIFT (0) /* Bits 0-5: Baud rate prescaler */
+#define DCAN_BTR_BRP_MASK (63 << DCAN_BTR_BRP_SHIFT)
+#define DCAN_BTR_SJW_SHIFT (6) /* Bits 6-7: Synchronization Jump Width */
+#define DCAN_BTR_SJW_MASK (3 << DCAN_BTR_SJW_SHIFT)
+#define DCAN_BTR_TSEG1_SHIFT (8) /* Bits 8-11: Time segment before the sample point */
+#define DCAN_BTR_TSEG1_MASK (15 << DCAN_BTR_TSEG1_SHIFT)
+#define DCAN_BTR_TSEG2_SHIFT (12) /* Bits 12-14: Time segment after the sample point */
+#define DCAN_BTR_TSEG2_MASK (7 << DCAN_BTR_TSEG2_SHIFT)
+#define DCAN_BTR_BRPE_SHIFT (16) /* Bits 16-19: Baud rate prescaler extension */
+#define DCAN_BTR_BRPE_MASK (15 << DCAN_BTR_BRPE_SHIFT)
+
+#define DCAN_INT_LINE0_SHIFT (0) /* Bits 0-15: Interrupt Line 0 Identifier */
+#define DCAN_INT_LINE0_MASK (65535 << DCAN_INT_LINE0_SHIFT)
+#define DCAN_INT_LINE1_SHIFT (16) /* Bits 16-23: Interrupt Line 1 Identifier */
+#define DCAN_INT_LINE1_MASK (255 << DCAN_INT_LINE1_SHIFT)
+
+#define DCAN_TEST_SILENT (1 << 3) /* Bit 3: Silent mode */
+#define DCAN_TEST_LBACK (1 << 4) /* Bit 4: Loopback mode */
+#define DCAN_TEST_TX_SHIFT (5) /* Bits 5-6: Control of CAN_TX pin */
+#define DCAN_TEST_TX_MASK (3 << DCAN_TEST_TX_SHIFT)
+# define DCAN_TEST_TX_NORMAL (0 << DCAN_TEST_TX_SHIFT) /* Normal operation */
+# define DCAN_TEST_TX_SAMLE (1 << DCAN_TEST_TX_SHIFT) /* Sample point can be monitored at CAN_TX pin */
+# define DCAN_TEST_TX_DOMINANT (2 << DCAN_TEST_TX_SHIFT) /* CAN_TX pin drives a dominant value */
+# define DCAN_TEST_TX_RECESSIVE (3 << DCAN_TEST_TX_SHIFT) /* CAN_TX pin drives a recessive value */
+#define DCAN_TEST_RX (1 << 7) /* Bit 7: Receive pin monitoring */
+#define DCAN_TEST_EXL (1 << 8) /* Bit 8: External loopback mode */
+#define DCAN_TEST_RDA (1 << 9) /* Bit 9: RAM direct access enable */
+
+#define DCAN_PERR_MSG_NUM_SHIFT (0) /* Bits 0-7: Message number */
+#define DCAN_PERR_MSG_NUM_MASK (255 << DCAN_PERR_MSG_NUM_SHIFT)
+#define DCAN_PERR_WORD_NUM_SHIFT (8) /* Bits 8-10: Word number where parity error has been detected */
+#define DCAN_PERR_WORD_NUM_MASK (7 << DCAN_PERR_WORD_NUM_SHIFT)
+
+#define DCAN_TXRQ(n) (1 << (((unsigned int)(n) - 1) & 0x1f)) /* Bit 0-31: Transmission request bits (for all message objects) */
+
+#define DCAN_NWDAT(n) (1 << (((unsigned int)(n) - 1) & 0x1f)) /* Bit 0-31: New Data Bits (for all message objects) */
+
+#define DCAN_INTPND(n) (1 << (((unsigned int)(n) - 1) & 0x1f)) /* Bit 0-31: Interrupt Pending Bits (for all message objects) */
+
+#define DCAN_MSGVAL(n) (1 << (((unsigned int)(n) - 1) & 0x1f)) /* Bit 0-31: Message valid bits (for all message objects) */
+
+#define DCAN_INTMUX_LAST (1 << 0) /* Bit 0: Last implemented message object */
+#define DCAN_INTMUX(n) (1 << ((unsigned int)(n) & 0x1f)) /* Bit n: Message object number n */
+
+#define DCAN_IFCMD_MSG_NUM_SHIFT (0) /* Bits 0-7: Number of message object in message RAM which is used for data transfer */
+#define DCAN_IFCMD_MSG_NUM_MASK (0xff << DCAN_IFCMD_MSG_NUM_SHIFT)
+#define DCAN_IFCMD_DMA_ACTIVE (1 << 14) /* Bit 14: Activation of DMA feature for subsequent internal IF update */
+#define DCAN_IFCMD_BUSY (1 << 15) /* Bit 15: Busy flag */
+#define DCAN_IFCMD_DATA_B (1 << 16) /* Bit 16: Access Data Bytes 4 to 7 */
+#define DCAN_IFCMD_DATA_A (1 << 17) /* Bit 17: Access Data Bytes 0 to 3 */
+#define DCAN_IFCMD_TX_RQST_NEWDAT (1 << 18) /* Bit 18: Access transmission request bit */
+#define DCAN_IFCMD_CLR_INTPND (1 << 19) /* Bit 19: Clear interrupt pending bit */
+#define DCAN_IFCMD_CONTROL (1 << 20) /* Bit 20: Access control bits */
+#define DCAN_IFCMD_ARB (1 << 21) /* Bit 21: Access arbitration bits */
+#define DCAN_IFCMD_MASK (1 << 22) /* Bit 22: Access mask bits */
+#define DCAN_IFCMD_WR_RD (1 << 23) /* Bit 23: Write/Read direction */
+
+#define DCAN_IFMSK_MSK_SHIFT (0) /* Bits 0-28: Message identifier mask */
+#define DCAN_IFMSK_MSK_MASK (0x1fffffff << DCAN_IFCMD_MSK_SHIFT)
+#define DCAN_IFMSK_MDIR (1 << 30) /* Bit 30: Mask message direction */
+#define DCAN_IFMSK_MXTD (1 << 31) /* Bit 31: Mask extended identifier */
+
+#define DCAN_IFARB_ID_SHIFT (0) /* Bits 0-28: Message identifier */
+#define DCAN_IFARB_ID_MASK (0x1fffffff << DCAN_IFCMD_MSK_SHIFT)
+#define DCAN_IFARB_DIR (1 << 29) /* Bit 29: Message direction */
+#define DCAN_IFARB_XTD (1 << 30) /* Bit 30: Extended identifier */
+#define DCAN_IFARB_MSG_VAL (1 << 31) /* Bit 31: Message valid */
+
+#define DCAN_IFMCTL_DLC_SHIFT (0) /* Bits 0-3: Data length code */
+#define DCAN_IFMCTL_DLC_MASK (15 << DCAN_IFMCTL_DLC_SHIFT)
+#define DCAN_IFMCTL_EOB (1 << 7) /* Bit 7: Data frame has 0 to 8 data bits. */
+#define DCAN_IFMCTL_TX_RQST (1 << 8) /* Bit 8: Transmit request */
+#define DCAN_IFMCTL_RMT_EN (1 << 9) /* Bit 9: Remote enable */
+#define DCAN_IFMCTL_RX_IE (1 << 10) /* Bit 10: Receive interrupt enable */
+#define DCAN_IFMCTL_TX_IE (1 << 11) /* Bit 11: Transmit interrupt enable */
+#define DCAN_IFMCTL_UMASK (1 << 12) /* Bit 12: Use acceptance mask */
+#define DCAN_IFMCTL_INTPND (1 << 13) /* Bit 13: Interrupt pending */
+#define DCAN_IFMCTL_MSGLST (1 << 14) /* Bit 14: Message lost (only valid for message objects with direction Receive) */
+#define DCAN_IFMCTL_NEWDAT (1 << 15) /* Bit 15: New data */
+
+#define DCAN_IF3OBS_MASK (1 << 0) /* Bit 0: Mask data read observation */
+#define DCAN_IF3OBS_ARB (1 << 1) /* Bit 1: Arbitration data read observation */
+#define DCAN_IF3OBS_CTRL (1 << 2) /* Bit 2: Control read observation */
+#define DCAN_IF3OBS_DATAA (1 << 3) /* Bit 3: Data A read observation */
+#define DCAN_IF3OBS_DATAB (1 << 4) /* Bit 4: Data B read observation */
+#define DCAN_IF3OBS_SM (1 << 8) /* Bit 8: Status of Mask data read access */
+#define DCAN_IF3OBS_SA (1 << 9) /* Bit 9: Status of Arbitration data read access */
+#define DCAN_IF3OBS_SC (1 << 10) /* Bit 10: Status of control bits read access */
+#define DCAN_IF3OBS_SDA (1 << 11) /* Bit 11: Status of Data A read access */
+#define DCAN_IF3OBS_SDB (1 << 12) /* Bit 12: Status of Data B read access */
+#define DCAN_IF3OBS_UPD (1 << 15) /* Bit 15: Update Data*/
+
+#define DCAN_IF3UPD(n) (1 << (((unsigned int)(n) - 1) & 0x1f)) /* Bit 0-31: IF3 Update Enabled (for all message objects) */
+
+#define DCAN_TIOC_IN (1 << 0) /* Bit 0: CAN_TX data in */
+#define DCAN_TIOC_OUT (1 << 1) /* Bit 1: CAN_TX data out write */
+#define DCAN_TIOC_DIR (1 << 2) /* Bit 2: CAN_TX data direction */
+#define DCAN_TIOC_FUNC (1 << 3) /* Bit 3: CAN_TX function */
+#define DCAN_TIOC_OD (1 << 16) /* Bit 16: CAN_TX open drain enable */
+#define DCAN_TIOC_PD (1 << 17) /* Bit 17: CAN_TX pull disable */
+#define DCAN_TIOC_PU (1 << 18) /* Bit 18: CAN_TX pull up/pull down select */
+
+#define DCAN_RIOC_IN (1 << 0) /* Bit 0: CAN_RX data in */
+#define DCAN_RIOC_OUT (1 << 1) /* Bit 1: CAN_RX data out write */
+#define DCAN_RIOC_DIR (1 << 2) /* Bit 2: CAN_RX data direction */
+#define DCAN_RIOC_FUNC (1 << 3) /* Bit 3: CAN_RX function */
+#define DCAN_RIOC_OD (1 << 16) /* Bit 16: CAN_RX open drain enable */
+#define DCAN_RIOC_PD (1 << 17) /* Bit 17: CAN_RX pull disable */
+#define DCAN_RIOC_PU (1 << 18) /* Bit 18: CAN_RX pull up/pull down select */
+
+#endif /* __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_DCAN_H */
diff --git a/arch/arm/src/am335x/hardware/am335x_i2c.h b/arch/arm/src/am335x/hardware/am335x_i2c.h
new file mode 100644
index 00000000000..5011f94da83
--- /dev/null
+++ b/arch/arm/src/am335x/hardware/am335x_i2c.h
@@ -0,0 +1,299 @@
+/************************************************************************************
+ * arch/arm/src/am335x/hardware/am335x_i2c.h
+ *
+ * Copyright (C) 2019 Petro Karashchenko. All rights reserved.
+ * Author: Petro Karashchenko
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_I2C_H
+#define __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_I2C_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include
+#include "hardware/am335x_memorymap.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register offsets *****************************************************************/
+
+#define AM335X_I2C_SYSC_OFFSET 0x0010
+#define AM335X_I2C_IRQ_STAT_RAW_OFFSET 0x0024
+#define AM335X_I2C_IRQ_STAT_OFFSET 0x0028
+#define AM335X_I2C_IRQ_EN_SET_OFFSET 0x002c
+#define AM335X_I2C_IRQ_EN_CLR_OFFSET 0x0030
+#define AM335X_I2C_WE_OFFSET 0x0034
+#define AM335X_I2C_DMA_RX_EN_SET_OFFSET 0x0038
+#define AM335X_I2C_DMA_TX_EN_SET_OFFSET 0x003c
+#define AM335X_I2C_DMA_RX_EN_CLR_OFFSET 0x0040
+#define AM335X_I2C_DMA_TX_EN_CLR_OFFSET 0x0044
+#define AM335X_I2C_DMA_RX_WAKE_EN_OFFSET 0x0048
+#define AM335X_I2C_DMA_TX_WAKE_EN_OFFSET 0x004c
+#define AM335X_I2C_SYSS_OFFSET 0x0090
+#define AM335X_I2C_BUF_OFFSET 0x0094
+#define AM335X_I2C_CNT_OFFSET 0x0098
+#define AM335X_I2C_DATA_OFFSET 0x009c
+#define AM335X_I2C_CON_OFFSET 0x00a4
+#define AM335X_I2C_OA_OFFSET 0x00a8
+#define AM335X_I2C_SA_OFFSET 0x00ac
+#define AM335X_I2C_PSC_OFFSET 0x00b0
+#define AM335X_I2C_SCLL_OFFSET 0x00b4
+#define AM335X_I2C_SCLH_OFFSET 0x00b8
+#define AM335X_I2C_SYSTEST_OFFSET 0x00bc
+#define AM335X_I2C_BUFSTAT_OFFSET 0x00c0
+#define AM335X_I2C_OA1_OFFSET 0x00c4
+#define AM335X_I2C_OA2_OFFSET 0x00c8
+#define AM335X_I2C_OA3_OFFSET 0x00cc
+#define AM335X_I2C_ACTOA_OFFSET 0x00d0
+#define AM335X_I2C_SBLOCK_OFFSET 0x00d4
+
+/* Register virtual addresses *******************************************************/
+
+#define AM335X_I2C0_SYSC (AM335X_I2C0_VADDR + AM335X_I2C_SYSC_OFFSET)
+#define AM335X_I2C0_IRQ_STAT_RAW (AM335X_I2C0_VADDR + AM335X_I2C_IRQ_STAT_RAW_OFFSET)
+#define AM335X_I2C0_IRQ_STAT (AM335X_I2C0_VADDR + AM335X_I2C_IRQ_STAT_OFFSET)
+#define AM335X_I2C0_IRQ_EN_SET (AM335X_I2C0_VADDR + AM335X_I2C_IRQ_EN_SET_OFFSET)
+#define AM335X_I2C0_IRQ_EN_CLR (AM335X_I2C0_VADDR + AM335X_I2C_IRQ_EN_CLR_OFFSET)
+#define AM335X_I2C0_WE (AM335X_I2C0_VADDR + AM335X_I2C_WE_OFFSET)
+#define AM335X_I2C0_DMA_RX_EN_SET (AM335X_I2C0_VADDR + AM335X_I2C_DMA_RX_EN_SET_OFFSET)
+#define AM335X_I2C0_DMA_TX_EN_SET (AM335X_I2C0_VADDR + AM335X_I2C_DMA_TX_EN_SET_OFFSET)
+#define AM335X_I2C0_DMA_RX_EN_CLR (AM335X_I2C0_VADDR + AM335X_I2C_DMA_RX_EN_CLR_OFFSET)
+#define AM335X_I2C0_DMA_TX_EN_CLR (AM335X_I2C0_VADDR + AM335X_I2C_DMA_TX_EN_CLR_OFFSET)
+#define AM335X_I2C0_DMA_RX_WAKE_EN (AM335X_I2C0_VADDR + AM335X_I2C_DMA_RX_WAKE_EN_OFFSET)
+#define AM335X_I2C0_DMA_TX_WAKE_EN (AM335X_I2C0_VADDR + AM335X_I2C_DMA_TX_WAKE_EN_OFFSET)
+#define AM335X_I2C0_SYSS (AM335X_I2C0_VADDR + AM335X_I2C_SYSS_OFFSET)
+#define AM335X_I2C0_BUF (AM335X_I2C0_VADDR + AM335X_I2C_BUF_OFFSET)
+#define AM335X_I2C0_CNT (AM335X_I2C0_VADDR + AM335X_I2C_CNT_OFFSET)
+#define AM335X_I2C0_DATA (AM335X_I2C0_VADDR + AM335X_I2C_DATA_OFFSET)
+#define AM335X_I2C0_CON (AM335X_I2C0_VADDR + AM335X_I2C_CON_OFFSET)
+#define AM335X_I2C0_OA (AM335X_I2C0_VADDR + AM335X_I2C_OA_OFFSET)
+#define AM335X_I2C0_SA (AM335X_I2C0_VADDR + AM335X_I2C_SA_OFFSET)
+#define AM335X_I2C0_PSC (AM335X_I2C0_VADDR + AM335X_I2C_PSC_OFFSET)
+#define AM335X_I2C0_SCLL (AM335X_I2C0_VADDR + AM335X_I2C_SCLL_OFFSET)
+#define AM335X_I2C0_SCLH (AM335X_I2C0_VADDR + AM335X_I2C_SCLH_OFFSET)
+#define AM335X_I2C0_SYSTEST (AM335X_I2C0_VADDR + AM335X_I2C_SYSTEST_OFFSET)
+#define AM335X_I2C0_BUFSTAT (AM335X_I2C0_VADDR + AM335X_I2C_BUFSTAT_OFFSET)
+#define AM335X_I2C0_OA1 (AM335X_I2C0_VADDR + AM335X_I2C_OA1_OFFSET)
+#define AM335X_I2C0_OA2 (AM335X_I2C0_VADDR + AM335X_I2C_OA2_OFFSET)
+#define AM335X_I2C0_OA3 (AM335X_I2C0_VADDR + AM335X_I2C_OA3_OFFSET)
+#define AM335X_I2C0_ACTOA (AM335X_I2C0_VADDR + AM335X_I2C_ACTOA_OFFSET)
+#define AM335X_I2C0_SBLOCK (AM335X_I2C0_VADDR + AM335X_I2C_SBLOCK_OFFSET)
+
+#define AM335X_I2C1_SYSC (AM335X_I2C1_VADDR + AM335X_I2C_SYSC_OFFSET)
+#define AM335X_I2C1_IRQ_STAT_RAW (AM335X_I2C1_VADDR + AM335X_I2C_IRQ_STAT_RAW_OFFSET)
+#define AM335X_I2C1_IRQ_STAT (AM335X_I2C1_VADDR + AM335X_I2C_IRQ_STAT_OFFSET)
+#define AM335X_I2C1_IRQ_EN_SET (AM335X_I2C1_VADDR + AM335X_I2C_IRQ_EN_SET_OFFSET)
+#define AM335X_I2C1_IRQ_EN_CLR (AM335X_I2C1_VADDR + AM335X_I2C_IRQ_EN_CLR_OFFSET)
+#define AM335X_I2C1_WE (AM335X_I2C1_VADDR + AM335X_I2C_WE_OFFSET)
+#define AM335X_I2C1_DMA_RX_EN_SET (AM335X_I2C1_VADDR + AM335X_I2C_DMA_RX_EN_SET_OFFSET)
+#define AM335X_I2C1_DMA_TX_EN_SET (AM335X_I2C1_VADDR + AM335X_I2C_DMA_TX_EN_SET_OFFSET)
+#define AM335X_I2C1_DMA_RX_EN_CLR (AM335X_I2C1_VADDR + AM335X_I2C_DMA_RX_EN_CLR_OFFSET)
+#define AM335X_I2C1_DMA_TX_EN_CLR (AM335X_I2C1_VADDR + AM335X_I2C_DMA_TX_EN_CLR_OFFSET)
+#define AM335X_I2C1_DMA_RX_WAKE_EN (AM335X_I2C1_VADDR + AM335X_I2C_DMA_RX_WAKE_EN_OFFSET)
+#define AM335X_I2C1_DMA_TX_WAKE_EN (AM335X_I2C1_VADDR + AM335X_I2C_DMA_TX_WAKE_EN_OFFSET)
+#define AM335X_I2C1_SYSS (AM335X_I2C1_VADDR + AM335X_I2C_SYSS_OFFSET)
+#define AM335X_I2C1_BUF (AM335X_I2C1_VADDR + AM335X_I2C_BUF_OFFSET)
+#define AM335X_I2C1_CNT (AM335X_I2C1_VADDR + AM335X_I2C_CNT_OFFSET)
+#define AM335X_I2C1_DATA (AM335X_I2C1_VADDR + AM335X_I2C_DATA_OFFSET)
+#define AM335X_I2C1_CON (AM335X_I2C1_VADDR + AM335X_I2C_CON_OFFSET)
+#define AM335X_I2C1_OA (AM335X_I2C1_VADDR + AM335X_I2C_OA_OFFSET)
+#define AM335X_I2C1_SA (AM335X_I2C1_VADDR + AM335X_I2C_SA_OFFSET)
+#define AM335X_I2C1_PSC (AM335X_I2C1_VADDR + AM335X_I2C_PSC_OFFSET)
+#define AM335X_I2C1_SCLL (AM335X_I2C1_VADDR + AM335X_I2C_SCLL_OFFSET)
+#define AM335X_I2C1_SCLH (AM335X_I2C1_VADDR + AM335X_I2C_SCLH_OFFSET)
+#define AM335X_I2C1_SYSTEST (AM335X_I2C1_VADDR + AM335X_I2C_SYSTEST_OFFSET)
+#define AM335X_I2C1_BUFSTAT (AM335X_I2C1_VADDR + AM335X_I2C_BUFSTAT_OFFSET)
+#define AM335X_I2C1_OA1 (AM335X_I2C1_VADDR + AM335X_I2C_OA1_OFFSET)
+#define AM335X_I2C1_OA2 (AM335X_I2C1_VADDR + AM335X_I2C_OA2_OFFSET)
+#define AM335X_I2C1_OA3 (AM335X_I2C1_VADDR + AM335X_I2C_OA3_OFFSET)
+#define AM335X_I2C1_ACTOA (AM335X_I2C1_VADDR + AM335X_I2C_ACTOA_OFFSET)
+#define AM335X_I2C1_SBLOCK (AM335X_I2C1_VADDR + AM335X_I2C_SBLOCK_OFFSET)
+
+#define AM335X_I2C2_SYSC (AM335X_I2C2_VADDR + AM335X_I2C_SYSC_OFFSET)
+#define AM335X_I2C2_IRQ_STAT_RAW (AM335X_I2C2_VADDR + AM335X_I2C_IRQ_STAT_RAW_OFFSET)
+#define AM335X_I2C2_IRQ_STAT (AM335X_I2C2_VADDR + AM335X_I2C_IRQ_STAT_OFFSET)
+#define AM335X_I2C2_IRQ_EN_SET (AM335X_I2C2_VADDR + AM335X_I2C_IRQ_EN_SET_OFFSET)
+#define AM335X_I2C2_IRQ_EN_CLR (AM335X_I2C2_VADDR + AM335X_I2C_IRQ_EN_CLR_OFFSET)
+#define AM335X_I2C2_WE (AM335X_I2C2_VADDR + AM335X_I2C_WE_OFFSET)
+#define AM335X_I2C2_DMA_RX_EN_SET (AM335X_I2C2_VADDR + AM335X_I2C_DMA_RX_EN_SET_OFFSET)
+#define AM335X_I2C2_DMA_TX_EN_SET (AM335X_I2C2_VADDR + AM335X_I2C_DMA_TX_EN_SET_OFFSET)
+#define AM335X_I2C2_DMA_RX_EN_CLR (AM335X_I2C2_VADDR + AM335X_I2C_DMA_RX_EN_CLR_OFFSET)
+#define AM335X_I2C2_DMA_TX_EN_CLR (AM335X_I2C2_VADDR + AM335X_I2C_DMA_TX_EN_CLR_OFFSET)
+#define AM335X_I2C2_DMA_RX_WAKE_EN (AM335X_I2C2_VADDR + AM335X_I2C_DMA_RX_WAKE_EN_OFFSET)
+#define AM335X_I2C2_DMA_TX_WAKE_EN (AM335X_I2C2_VADDR + AM335X_I2C_DMA_TX_WAKE_EN_OFFSET)
+#define AM335X_I2C2_SYSS (AM335X_I2C2_VADDR + AM335X_I2C_SYSS_OFFSET)
+#define AM335X_I2C2_BUF (AM335X_I2C2_VADDR + AM335X_I2C_BUF_OFFSET)
+#define AM335X_I2C2_CNT (AM335X_I2C2_VADDR + AM335X_I2C_CNT_OFFSET)
+#define AM335X_I2C2_DATA (AM335X_I2C2_VADDR + AM335X_I2C_DATA_OFFSET)
+#define AM335X_I2C2_CON (AM335X_I2C2_VADDR + AM335X_I2C_CON_OFFSET)
+#define AM335X_I2C2_OA (AM335X_I2C2_VADDR + AM335X_I2C_OA_OFFSET)
+#define AM335X_I2C2_SA (AM335X_I2C2_VADDR + AM335X_I2C_SA_OFFSET)
+#define AM335X_I2C2_PSC (AM335X_I2C2_VADDR + AM335X_I2C_PSC_OFFSET)
+#define AM335X_I2C2_SCLL (AM335X_I2C2_VADDR + AM335X_I2C_SCLL_OFFSET)
+#define AM335X_I2C2_SCLH (AM335X_I2C2_VADDR + AM335X_I2C_SCLH_OFFSET)
+#define AM335X_I2C2_SYSTEST (AM335X_I2C2_VADDR + AM335X_I2C_SYSTEST_OFFSET)
+#define AM335X_I2C2_BUFSTAT (AM335X_I2C2_VADDR + AM335X_I2C_BUFSTAT_OFFSET)
+#define AM335X_I2C2_OA1 (AM335X_I2C2_VADDR + AM335X_I2C_OA1_OFFSET)
+#define AM335X_I2C2_OA2 (AM335X_I2C2_VADDR + AM335X_I2C_OA2_OFFSET)
+#define AM335X_I2C2_OA3 (AM335X_I2C2_VADDR + AM335X_I2C_OA3_OFFSET)
+#define AM335X_I2C2_ACTOA (AM335X_I2C2_VADDR + AM335X_I2C_ACTOA_OFFSET)
+#define AM335X_I2C2_SBLOCK (AM335X_I2C2_VADDR + AM335X_I2C_SBLOCK_OFFSET)
+
+/* Register bit field definitions ***************************************************/
+
+#define I2C_SYSC_AUTOIDLE (1 << 0) /* Bit 0: Autoidle */
+#define I2C_SYSC_SRST (1 << 1) /* Bit 1: SoftReset */
+#define I2C_SYSC_WAKEUP (1 << 2) /* Bit 2: Enable Wakeup control */
+#define I2C_SYSC_IDLE_SHIFT (3) /* Bits 3-4: Idle Mode selection */
+#define I2C_SYSC_IDLE_MASK (3 << I2C_SYSC_IDLE_SHIFT)
+# define I2C_SYSC_IDLE_FORCE (0 << I2C_SYSC_IDLE_SHIFT) /* Force-idle mode */
+# define I2C_SYSC_IDLE_NO (1 << I2C_SYSC_IDLE_SHIFT) /* No-idle mode */
+# define I2C_SYSC_IDLE_SMART (2 << I2C_SYSC_IDLE_SHIFT) /* Smart-idle mode */
+# define I2C_SYSC_IDLE_SMART_WKUP (3 << I2C_SYSC_IDLE_SHIFT) /* Smart-idle Wakeup mode */
+#define I2C_SYSC_CLK_SHIFT (8) /* Bits 8-9: Clock Activity selection */
+#define I2C_SYSC_CLK_MASK (3 << I2C_SYSC_CLK_SHIFT)
+# define I2C_SYSC_CLK_NONE (0 << I2C_SYSC_CLK_SHIFT) /* Both clocks can be cut off */
+# define I2C_SYSC_CLK_OCP (1 << I2C_SYSC_CLK_SHIFT) /* Only Interface/OCP clock must be kept active */
+# define I2C_SYSC_CLK_FUNC (2 << I2C_SYSC_CLK_SHIFT) /* Only functions clock must be kept active */
+# define I2C_SYSC_CLK_BOTH (3 << I2C_SYSC_CLK_SHIFT) /* Both clocks must be kept active */
+
+#define I2C_IRQ_AL (1 << 0) /* Bit 0: Arbitration lost */
+#define I2C_IRQ_NACK (1 << 1) /* Bit 1: No acknowledgment */
+#define I2C_IRQ_ARDY (1 << 2) /* Bit 2: Register access ready */
+#define I2C_IRQ_RRDY (1 << 3) /* Bit 3: Receive data ready */
+#define I2C_IRQ_XRDY (1 << 4) /* Bit 4: Transmit data ready */
+#define I2C_IRQ_GC (1 << 5) /* Bit 5: General call */
+#define I2C_IRQ_STC (1 << 6) /* Bit 6: Start Condition */
+#define I2C_IRQ_AERR (1 << 7) /* Bit 7: Access Error */
+#define I2C_IRQ_BF (1 << 8) /* Bit 8: Bus Free */
+#define I2C_IRQ_AAS (1 << 9) /* Bit 9: Address recognized as slave */
+#define I2C_IRQ_XUDF (1 << 10) /* Bit 10: Transmit underflow */
+#define I2C_IRQ_ROVR (1 << 11) /* Bit 11: Receive overrun */
+#define I2C_IRQ_BB (1 << 12) /* Bit 12: Bus busy */
+#define I2C_IRQ_RDR (1 << 13) /* Bit 13: Receive draining IRQ */
+#define I2C_IRQ_XDR (1 << 14) /* Bit 14: Transmit draining IRQ */
+
+#define I2C_WE_AL (1 << 0) /* Bit 0: Arbitration lost */
+#define I2C_WE_NACK (1 << 1) /* Bit 1: No acknowledgment */
+#define I2C_WE_ARDY (1 << 2) /* Bit 2: Register access ready */
+#define I2C_WE_DRDY (1 << 3) /* Bit 3: Receive/Transmit data ready */
+#define I2C_WE_GC (1 << 5) /* Bit 5: General call */
+#define I2C_WE_STC (1 << 6) /* Bit 6: Start Condition */
+#define I2C_WE_BF (1 << 8) /* Bit 8: Bus Free */
+#define I2C_WE_AAS (1 << 9) /* Bit 9: Address recognized as slave */
+#define I2C_WE_XUDF (1 << 10) /* Bit 10: Transmit underflow */
+#define I2C_WE_ROVR (1 << 11) /* Bit 11: Receive overrun */
+#define I2C_WE_RDR (1 << 13) /* Bit 13: Receive draining IRQ */
+#define I2C_WE_XDR (1 << 14) /* Bit 14: Transmit draining IRQ */
+
+#define I2C_DMA_ENABLE (1 << 0) /* Bit 0: DMA channel enable */
+
+#define I2C_SYSS_RST_DONE (1 << 0) /* Bit 0: Reset done */
+
+#define I2C_BUF_TXTRSH_SHIFT (0) /* Bits 0-5: Threshold value for FIFO buffer in TX mode */
+#define I2C_BUF_TXTRSH_MASK (63 << I2C_BUF_TXTRSH_SHIFT)
+#define I2C_BUF_TXFIFO_CLR (1 << 6) /* Bit 6: Transmit FIFO clear */
+#define I2C_BUF_XDMA_EN (1 << 7) /* Bit 7: Transmit DMA channel enable */
+#define I2C_BUF_RXTRSH_SHIFT (8) /* Bits 8-13: Threshold value for FIFO buffer in RX mode */
+#define I2C_BUF_RXTRSH_MASK (63 << I2C_BUF_RXTRSH_SHIFT)
+#define I2C_BUF_RXFIFO_CLR (1 << 14) /* Bit 14: Receive FIFO clear */
+#define I2C_BUF_RDMA_EN (1 << 15) /* Bit 15: Receive DMA channel enable */
+
+#define I2C_CNT_SHIFT (0) /* Bits 0-15: Data count */
+#define I2C_CNT_MASK (65535 << I2C_CNT_SHIFT)
+
+#define I2C_DATA_SHIFT (0) /* Bits 0-7: Transmit/Receive data FIFO endpoint */
+#define I2C_DATA_MASK (255 << I2C_DATA_SHIFT)
+
+#define I2C_CON_STT (1 << 0) /* Bit 0: Start condition (I2C master mode only) */
+#define I2C_CON_STP (1 << 1) /* Bit 1: Stop condition (I2C master mode only) */
+#define I2C_CON_XOA3 (1 << 4) /* Bit 4: Expand own address 3 */
+#define I2C_CON_XOA2 (1 << 5) /* Bit 5: Expand own address 2 */
+#define I2C_CON_XOA1 (1 << 6) /* Bit 6: Expand own address 1 */
+#define I2C_CON_XOA0 (1 << 7) /* Bit 7: Expand own address 0 */
+#define I2C_CON_XSA (1 << 8) /* Bit 8: Expand slave address */
+#define I2C_CON_TRX (1 << 9) /* Bit 9: Transmitter/receiver mode (I2C master mode only) */
+#define I2C_CON_MST (1 << 10) /* Bit 10: Master/slave mode */
+#define I2C_CON_STB (1 << 11) /* Bit 11: Start byte mode (I2C master mode only) */
+#define I2C_CON_OPMODE_SHIFT (1 << 12) /* Bits 12-13: Operation mode selection */
+#define I2C_CON_OPMODE_MASK (3 << I2C_CON_OPMODE_SHIFT)
+# define I2C_CON_OPMODE_FAST (0 << I2C_CON_OPMODE_SHIFT)
+#define I2C_CON_EN (1 << 15) /* Bit 15: I2C module enable */
+
+#define I2C_SA_SHIFT (0) /* Bits 0-9: Slave address */
+#define I2C_SA_MASK (0x3ff << I2C_SA_SHIFT)
+
+#define I2C_PSC_SHIFT (0) /* Bits 0-7: Fast/Standard mode prescale sampling clock divider */
+#define I2C_PSC_MASK (255 << I2C_PSC_SHIFT)
+
+#define I2C_SCLL_SHIFT (0) /* Bits 0-7: Fast/Standard mode SCL low time */
+#define I2C_SCLL_MASK (255 << I2C_SCLL_SHIFT)
+
+#define I2C_SCLH_SHIFT (0) /* Bits 0-7: Fast/Standard mode SCL high time. */
+#define I2C_SCLH_MASK (255 << I2C_SCLH_SHIFT)
+
+#define I2C_SYSTEST_SDA_O (1 << 0) /* Bit 0: SDA line drive output value */
+#define I2C_SYSTEST_SDA_I (1 << 1) /* Bit 1: SDA line sense input value */
+#define I2C_SYSTEST_SCL_O (1 << 2) /* Bit 2: SCL line drive output value */
+#define I2C_SYSTEST_SCL_I (1 << 3) /* Bit 3: SCL line sense input value */
+#define I2C_SYSTEST_SDA_O_FUNC (1 << 5) /* Bit 5: SDA line output value (functional mode) */
+#define I2C_SYSTEST_SDA_I_FUNC (1 << 6) /* Bit 6: SDA line input value (functional mode) */
+#define I2C_SYSTEST_SCL_O_FUNC (1 << 7) /* Bit 7: SCL line output value (functional mode) */
+#define I2C_SYSTEST_SCL_I_FUNC (1 << 8) /* Bit 8: SCL line input value (functional mode) */
+#define I2C_SYSTEST_SSB (1 << 11) /* Bit 11: Set status bits */
+#define I2C_SYSTEST_TMODE_SHIFT (12) /* Bits 12-13: Test mode select */
+#define I2C_SYSTEST_TMODE_MASK (3 << I2C_SYSTEST_TMODE_SHIFT)
+# define I2C_SYSTEST_TMODE_FUNC (0 << I2C_SYSTEST_TMODE_SHIFT) /* Functional mode */
+# define I2C_SYSTEST_TMODE_SCL (2 << I2C_SYSTEST_TMODE_SHIFT) /* Test of SCL counters (SCLL, SCLH, PSC) */
+# define I2C_SYSTEST_TMODE_LOOPBACK (3 << I2C_SYSTEST_TMODE_SHIFT) /* Loop back mode select + SDA/SCL IO mode select */
+#define I2C_SYSTEST_FREE (1 << 14) /* Bit 14: Free running mode (on breakpoint) */
+#define I2C_SYSTEST_ST_EN (1 << 15) /* Bit 15: System test enable */
+
+#define I2C_BUFSTAT_TXSTAT_SHIFT (0) /* Bits 0-5: TX buffer status */
+#define I2C_BUFSTAT_TXSTAT_MASK (63 << I2C_BUFSTAT_TXSTAT_SHIFT)
+#define I2C_BUFSTAT_RXSTAT_SHIFT (8) /* Bits 8-13: RX buffer status */
+#define I2C_BUFSTAT_RXSTAT_MASK (63 << I2C_BUFSTAT_RXSTAT_SHIFT)
+#define I2C_BUFSTAT_FIFODEPTH_SHIFT (14) /* Bits 14-15: Internal FIFO buffers depth */
+#define I2C_BUFSTAT_FIFODEPTH_MASK (3 << I2C_BUFSTAT_FIFODEPTH_SHIFT)
+
+#define I2C_OA_SHIFT (0) /* Bits 0-9: Own address */
+#define I2C_OA_MASK (0x3ff << I2C_OA_SHIFT)
+
+#define I2C_OA0_SELECT (1 << 0) /* Bit 0: Own address 0 */
+#define I2C_OA1_SELECT (1 << 1) /* Bit 1: Own address 1 */
+#define I2C_OA2_SELECT (1 << 2) /* Bit 2: Own address 2 */
+#define I2C_OA3_SELECT (1 << 3) /* Bit 3: Own address 3 */
+
+#endif /* __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_I2C_H */
diff --git a/arch/arm/src/am335x/hardware/am335x_lcd.h b/arch/arm/src/am335x/hardware/am335x_lcd.h
new file mode 100644
index 00000000000..a3ef1736a05
--- /dev/null
+++ b/arch/arm/src/am335x/hardware/am335x_lcd.h
@@ -0,0 +1,293 @@
+/************************************************************************************
+ * arch/arm/src/am335x/hardware/am335x_lcd.h
+ *
+ * Copyright (C) 2019 Petro Karashchenko. All rights reserved.
+ * Author: Petro Karashchenko
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_LCD_H
+#define __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_LCD_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include
+#include "hardware/am335x_memorymap.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register offsets *****************************************************************/
+
+#define AM335X_LCD_PID_OFFSET 0x0000
+#define AM335X_LCD_CTRL_OFFSET 0x0004
+#define AM335X_LCD_LIDD_CTRL_OFFSET 0x000c
+#define AM335X_LCD_LIDD_CS0_CONF_OFFSET 0x0010
+#define AM335X_LCD_LIDD_CS0_ADDR_OFFSET 0x0014
+#define AM335X_LCD_LIDD_CS0_DATA_OFFSET 0x0018
+#define AM335X_LCD_LIDD_CS1_CONF_OFFSET 0x001c
+#define AM335X_LCD_LIDD_CS1_ADDR_OFFSET 0x0020
+#define AM335X_LCD_LIDD_CS1_DATA_OFFSET 0x0024
+#define AM335X_LCD_RASTER_CTRL_OFFSET 0x0028
+#define AM335X_LCD_RASTER_TIMING_0_OFFSET 0x002c
+#define AM335X_LCD_RASTER_TIMING_1_OFFSET 0x0030
+#define AM335X_LCD_RASTER_TIMING_2_OFFSET 0x0034
+#define AM335X_LCD_RASTER_SUBPANEL_OFFSET 0x0038
+#define AM335X_LCD_RASTER_SUBPANEL2_OFFSET 0x003c
+#define AM335X_LCD_DMA_CTRL_OFFSET 0x0040
+#define AM335X_LCD_DMA_FB0_BASE_OFFSET 0x0044
+#define AM335X_LCD_DMA_FB0_CEIL_OFFSET 0x0048
+#define AM335X_LCD_DMA_FB1_BASE_OFFSET 0x004c
+#define AM335X_LCD_DMA_FB1_CEIL_OFFSET 0x0050
+#define AM335X_LCD_SYSC_OFFSET 0x0054
+#define AM335X_LCD_IRQ_STAT_RAW_OFFSET 0x0058
+#define AM335X_LCD_IRQ_STAT_OFFSET 0x005c
+#define AM335X_LCD_IRQ_EN_SET_OFFSET 0x0060
+#define AM335X_LCD_IRQ_EN_CLEAR_OFFSET 0x0064
+#define AM335X_LCD_END_INT_OFFSET 0x0068
+#define AM335X_LCD_CLKC_ENABLE_OFFSET 0x006c
+#define AM335X_LCD_CLKC_RESET_OFFSET 0x0070
+
+#define AM335X_LCD_LIDD_CS_CONF_OFFSET(n) (0x0010 + (unsigned int)(n) * 0x0c)
+#define AM335X_LCD_LIDD_CS_ADDR_OFFSET(n) (0x0014 + (unsigned int)(n) * 0x0c)
+#define AM335X_LCD_LIDD_CS_DATA_OFFSET(n) (0x0018 + (unsigned int)(n) * 0x0c)
+#define AM335X_LCD_DMA_FB_BASE_OFFSET(n) (0x0044 + (unsigned int)(n) * 0x08)
+#define AM335X_LCD_DMA_FB_CEIL_OFFSET(n) (0x0048 + (unsigned int)(n) * 0x08)
+
+/* Register virtual addresses *******************************************************/
+
+#define AM335X_LCD_PID (AM335X_LCD_VADDR + AM335X_LCD_PID_OFFSET)
+#define AM335X_LCD_CTRL (AM335X_LCD_VADDR + AM335X_LCD_CTRL_OFFSET)
+#define AM335X_LCD_LIDD_CTRL (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CTRL_OFFSET)
+#define AM335X_LCD_LIDD_CS0_CONF (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CS0_CONF_OFFSET)
+#define AM335X_LCD_LIDD_CS0_ADDR (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CS0_ADDR_OFFSET)
+#define AM335X_LCD_LIDD_CS0_DATA (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CS0_DATA_OFFSET)
+#define AM335X_LCD_LIDD_CS1_CONF (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CS1_CONF_OFFSET)
+#define AM335X_LCD_LIDD_CS1_ADDR (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CS1_ADDR_OFFSET)
+#define AM335X_LCD_LIDD_CS1_DATA (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CS1_DATA_OFFSET)
+#define AM335X_LCD_RASTER_CTRL (AM335X_LCD_VADDR + AM335X_LCD_RASTER_CTRL_OFFSET)
+#define AM335X_LCD_RASTER_TIMING_0 (AM335X_LCD_VADDR + AM335X_LCD_RASTER_TIMING_0_OFFSET)
+#define AM335X_LCD_RASTER_TIMING_1 (AM335X_LCD_VADDR + AM335X_LCD_RASTER_TIMING_1_OFFSET)
+#define AM335X_LCD_RASTER_TIMING_2 (AM335X_LCD_VADDR + AM335X_LCD_RASTER_TIMING_2_OFFSET)
+#define AM335X_LCD_RASTER_SUBPANEL (AM335X_LCD_VADDR + AM335X_LCD_RASTER_SUBPANEL_OFFSET)
+#define AM335X_LCD_RASTER_SUBPANEL2 (AM335X_LCD_VADDR + AM335X_LCD_RASTER_SUBPANEL2_OFFSET)
+#define AM335X_LCD_DMA_CTRL (AM335X_LCD_VADDR + AM335X_LCD_DMA_CTRL_OFFSET)
+#define AM335X_LCD_DMA_FB0_BASE (AM335X_LCD_VADDR + AM335X_LCD_DMA_FB0_BASE_OFFSET)
+#define AM335X_LCD_DMA_FB0_CEIL (AM335X_LCD_VADDR + AM335X_LCD_DMA_FB0_CEIL_OFFSET)
+#define AM335X_LCD_DMA_FB1_BASE (AM335X_LCD_VADDR + AM335X_LCD_DMA_FB1_BASE_OFFSET)
+#define AM335X_LCD_DMA_FB1_CEIL (AM335X_LCD_VADDR + AM335X_LCD_DMA_FB1_CEIL_OFFSET)
+#define AM335X_LCD_SYSC (AM335X_LCD_VADDR + AM335X_LCD_SYSC_OFFSET)
+#define AM335X_LCD_IRQ_STAT_RAW (AM335X_LCD_VADDR + AM335X_LCD_IRQ_STAT_RAW_OFFSET)
+#define AM335X_LCD_IRQ_STAT (AM335X_LCD_VADDR + AM335X_LCD_IRQ_STAT_OFFSET)
+#define AM335X_LCD_IRQ_EN_SET (AM335X_LCD_VADDR + AM335X_LCD_IRQ_EN_SET_OFFSET)
+#define AM335X_LCD_IRQ_EN_CLEAR (AM335X_LCD_VADDR + AM335X_LCD_IRQ_EN_CLEAR_OFFSET)
+#define AM335X_LCD_END_INT (AM335X_LCD_VADDR + AM335X_LCD_END_INT_OFFSET)
+#define AM335X_LCD_CLKC_ENABLE (AM335X_LCD_VADDR + AM335X_LCD_CLKC_ENABLE_OFFSET)
+#define AM335X_LCD_CLKC_RESET (AM335X_LCD_VADDR + AM335X_LCD_CLKC_RESET_OFFSET)
+
+#define AM335X_LCD_LIDD_CS_CONF(n) (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CS_CONF_OFFSET(n))
+#define AM335X_LCD_LIDD_CS_ADDR(n) (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CS_ADDR_OFFSET(n))
+#define AM335X_LCD_LIDD_CS_DATA(n) (AM335X_LCD_VADDR + AM335X_LCD_LIDD_CS_DATA_OFFSET(n))
+#define AM335X_LCD_DMA_FB_BASE(n) (AM335X_LCD_VADDR + AM335X_LCD_DMA_FB_BASE_OFFSET(n))
+#define AM335X_LCD_DMA_FB_CEIL(n) (AM335X_LCD_VADDR + AM335X_LCD_DMA_FB_CEIL_OFFSET(n))
+
+/* Register bit field definitions ***************************************************/
+
+#define LCD_CTRL_MODE_SEL (1 << 0) /* Bit 0: LCD Mode select */
+# define LCD_CTRL_MODE_LIDD (0)
+# define LCD_CTRL_MODE_RASTER LCD_CTRL_MODE_SEL
+#define LCD_CTRL_AUTO_UFLOW_RESTART (1 << 1) /* Bit 1: Underflow restart selection */
+#define LCD_CTRL_CLKDIV_SHIFT (8) /* Bits 8-15: Clock divisor */
+#define LCD_CTRL_CLKDIV_MASK (255 << LCD_CTRL_CLKDIV_SHIFT)
+
+#define LCD_LIDD_CTRL_MODE_SEL_SHIFT (0) /* Bits 0-2: LIDD Mode Select */
+#define LCD_LIDD_CTRL_MODE_SEL_MASK (7 << LCD_LIDD_CTRL_MODE_SEL_SHIFT)
+# define LCD_LIDD_CTRL_SYNC_MPU68 (0 << LCD_LIDD_CTRL_MODE_SEL_SHIFT) /* Sync MPU68 */
+# define LCD_LIDD_CTRL_ASYNC_MPU68 (1 << LCD_LIDD_CTRL_MODE_SEL_SHIFT) /* Async MPU68 */
+# define LCD_LIDD_CTRL_SYNC_MPU80 (2 << LCD_LIDD_CTRL_MODE_SEL_SHIFT) /* Sync MPU80 */
+# define LCD_LIDD_CTRL_ASYNC_MPU80 (3 << LCD_LIDD_CTRL_MODE_SEL_SHIFT) /* Async MPU80 */
+# define LCD_LIDD_CTRL_HITACHI (4 << LCD_LIDD_CTRL_MODE_SEL_SHIFT) /* Hitachi (Async) */
+#define LCD_LIDD_CTRL_ALEPOL (1 << 3) /* Bit 3: Address Latch Enable (ALE) Polarity Control */
+#define LCD_LIDD_CTRL_RS_EN_POL (1 << 4) /* Bit 4: Read Strobe/Direction Polarity Control */
+#define LCD_LIDD_CTRL_WS_DIR_POL (1 << 5) /* Bit 5: Write Strobe/Direction Polarity Control */
+#define LCD_LIDD_CTRL_CS0_E0_POL (1 << 6) /* Bit 6: Chip Select 0/Enable 0 (Secondary) Polarity Control */
+#define LCD_LIDD_CTRL_CS1_E1_POL (1 << 7) /* Bit 7: Chip Select 1/Enable 1 (Secondary) Polarity Control */
+#define LCD_LIDD_CTRL_DMA_EN (1 << 8) /* Bit 8: LIDD DMA Enable */
+#define LCD_LIDD_CTRL_DMA_CS0_CS1 (1 << 9) /* Bit 9: CS0/CS1 Select for LIDD DMA writes */
+
+#define LCD_LIDD_CS_CONF_TA_SHIFT (0) /* Bits 0-1: Turn-around Access */
+#define LCD_LIDD_CS_CONF_TA_MASK (3 << LCD_LIDD_CS0_CONF_TA_SHIFT)
+#define LCD_LIDD_CS_CONF_R_HOLD_SHIFT (2) /* Bits 2-5: Read Strobe Hold cycles */
+#define LCD_LIDD_CS_CONF_R_HOLD_MASK (15 << LCD_LIDD_CS0_CONF_R_HOLD_SHIFT)
+#define LCD_LIDD_CS_CONF_R_STROBE_SHIFT (6) /* Bits 6-11: Read Strobe Duration cycles */
+#define LCD_LIDD_CS_CONF_R_STROBE_MASK (63 << LCD_LIDD_CS0_CONF_R_STROBE_SHIFT)
+#define LCD_LIDD_CS_CONF_R_SU_SHIFT (12) /* Bits 12-16: Read Strobe Set-Up cycles */
+#define LCD_LIDD_CS_CONF_R_SU_MASK (31 << LCD_LIDD_CS0_CONF_R_SU_SHIFT)
+#define LCD_LIDD_CS_CONF_W_HOLD_SHIFT (17) /* Bits 17-20: Write Strobe Hold cycles */
+#define LCD_LIDD_CS_CONF_W_HOLD_MASK (15 << LCD_LIDD_CS0_CONF_W_HOLD_SHIFT)
+#define LCD_LIDD_CS_CONF_W_STROBE_SHIFT (21) /* Bits 21-26: Write Strobe Duration cycles */
+#define LCD_LIDD_CS_CONF_W_STROBE_MASK (63 << LCD_LIDD_CS0_CONF_W_STROBE_SHIFT)
+#define LCD_LIDD_CS_CONF_W_SU_SHIFT (27) /* Bits 27-31: Write Strobe Set-Up cycles */
+#define LCD_LIDD_CS_CONF_W_SU_MASK (31 << LCD_LIDD_CS0_CONF_W_SU_SHIFT)
+
+#define LCD_LIDD_CS_ADDR_SHIFT (0) /* Bits 0-15: Address index */
+#define LCD_LIDD_CS_ADDR_MASK (0xffff << LCD_LIDD_CS_ADDR_SHIFT)
+
+#define LCD_LIDD_CS_DATA_SHIFT (0) /* Bits 0-15: Data */
+#define LCD_LIDD_CS_DATA_MASK (0xffff << LCD_LIDD_CS_DATA_SHIFT)
+
+#define LCD_RASTER_CTRL_LCD_EN (1 << 0) /* Bit 0: LCD Controller Enable */
+#define LCD_RASTER_CTRL_LCD_BW (1 << 1) /* Bit 1: Only Applies for Passive Matrix Panels LCD Monochrome */
+#define LCD_RASTER_CTRL_LCD_TFT (1 << 7) /* Bit 7: Active/Passive or display operation selection */
+#define LCD_RASTER_CTRL_RD_ORDER (1 << 8) /* Bit 8: Raster Data Order Select */
+#define LCD_RASTER_CTRL_MONO_8B (1 << 9) /* Bit 9: Mono 8 bit */
+#define LCD_RASTER_CTRL_REQDLY_SHIFT (12) /* Bits 12-19: Palette Loading Delay When loading the Palette from DDR */
+#define LCD_RASTER_CTRL_REQDLY_MASK (255 << LCD_RASTER_CTRL_REQDLY_SHIFT)
+#define LCD_RASTER_CTRL_PALMODE_SHIFT (20) /* Bits 20-21: Palette Loading Mode */
+#define LCD_RASTER_CTRL_PALMODE_MASK (3 << LCD_RASTER_CTRL_PALMODE_SHIFT)
+# define LCD_RASTER_CTRL_PALETTE_DATA (0 << LCD_RASTER_CTRL_PALMODE_SHIFT) /* Palette and data loading */
+# define LCD_RASTER_CTRL_PALETTE (1 << LCD_RASTER_CTRL_PALMODE_SHIFT) /* Palette loading only */
+# define LCD_RASTER_CTRL_DATA (2 << LCD_RASTER_CTRL_PALMODE_SHIFT) /* Data loading only For Raw Data (12/16/24 bpp) framebuffers, no palette lookup is employed */
+#define LCD_RASTER_CTRL_NIB_MODE (1 << 22) /* Bit 22: Nibble Mode */
+#define LCD_RASTER_CTRL_TFT_MAP (1 << 23) /* Bit 23: TFT Mode Alternate Signal Mapping for Palettized framebuffer */
+#define LCD_RASTER_CTRL_STN565 (1 << 24) /* Bit 24: Selects whether the framebuffer format is 16 bpp 565 or 12 bpp. */
+#define LCD_RASTER_CTRL_TFT24 (1 << 25) /* Bit 25: 24 bit mode */
+#define LCD_RASTER_CTRL_TFT24_UNPACKED (1 << 26) /* Bit 26: 24 bit Mode Packing */
+
+#define LCD_RASTER_TIMING_0_PPLMSB (1 << 3) /* Bit 3: Pixels-per-line MSB[10] */
+#define LCD_RASTER_TIMING_0_PPLLSB_SHIFT (4) /* Bits 4-9: Pixels-per-line LSB */
+#define LCD_RASTER_TIMING_0_PPLLSB_MASK (63 << LCD_RASTER_TIMING_0_PPLLSB_SHIFT)
+#define LCD_RASTER_TIMING_0_HSW_SHIFT (10) /* Bits 10-15: Horizontal Sync Pulse Width Lowbits*/
+#define LCD_RASTER_TIMING_0_HSW_MASK (63 << LCD_RASTER_TIMING_0_HSW_SHIFT)
+#define LCD_RASTER_TIMING_0_HFP_SHIFT (16) /* Bits 16-23: Horizontal Front Porch Lowbits */
+#define LCD_RASTER_TIMING_0_HFP_MASK (255 << LCD_RASTER_TIMING_0_HFP_SHIFT)
+#define LCD_RASTER_TIMING_0_HBP_SHIFT (24) /* Bits 24-31: Horizontal Back Porch Lowbits */
+#define LCD_RASTER_TIMING_0_HBP_MASK (255 << LCD_RASTER_TIMING_0_HBP_SHIFT)
+
+#define LCD_RASTER_TIMING_1_LPP_SHIFT (0) /* Bits 0-9: Lines Per Panel */
+#define LCD_RASTER_TIMING_1_LPP_MASK (255 << LCD_RASTER_TIMING_1_LPP_SHIFT)
+#define LCD_RASTER_TIMING_1_VSW_SHIFT (10) /* Bits 10-15: Vertical Sync Width Pulse */
+#define LCD_RASTER_TIMING_1_VSW_MASK (255 << LCD_RASTER_TIMING_1_VSW_SHIFT)
+#define LCD_RASTER_TIMING_1_VFP_SHIFT (16) /* Bits 16-23: Vertical Front Porch */
+#define LCD_RASTER_TIMING_1_VFP_MASK (255 << LCD_RASTER_TIMING_1_VFP_SHIFT)
+#define LCD_RASTER_TIMING_1_VBP_SHIFT (24) /* Bits 24-31: Vertical Back Porch */
+#define LCD_RASTER_TIMING_1_VBP_MASK (255 << LCD_RASTER_TIMING_1_VBP_SHIFT)
+
+#define LCD_RASTER_TIMING_2_HFP_HBITS_SHIFT (0) /* Bits 0-1: Bits 9:8 of the horizontal front porch field */
+#define LCD_RASTER_TIMING_2_HFP_HBITS_MASK (3 << LCD_RASTER_TIMING_2_HFP_HBITS_SHIFT)
+#define LCD_RASTER_TIMING_2_HBP_HBITS_SHIFT (4) /* Bits 4-5: Bits 9:8 of the horizontal back porch field */
+#define LCD_RASTER_TIMING_2_HBP_HBITS_MASK (3 << LCD_RASTER_TIMING_2_HBP_HBITS_SHIFT)
+#define LCD_RASTER_TIMING_2_ACB_SHIFT (8) /* Bits 8-15: AC Bias Pin Frequency */
+#define LCD_RASTER_TIMING_2_ACB_MASK (255 << LCD_RASTER_TIMING_2_ACB_SHIFT)
+#define LCD_RASTER_TIMING_2_ACBI_SHIFT (16) /* Bits 16-19: AC Bias Pins Transitions per Interrupt */
+#define LCD_RASTER_TIMING_2_ACBI_MASK (15 << LCD_RASTER_TIMING_2_ACBI_SHIFT)
+#define LCD_RASTER_TIMING_2_IVS (1 << 20) /* Bit 20: Invert Vsync */
+#define LCD_RASTER_TIMING_2_IHS (1 << 21) /* Bit 21: Invert Hsync */
+#define LCD_RASTER_TIMING_2_IPC (1 << 22) /* Bit 22: Invert Pixel Clock */
+#define LCD_RASTER_TIMING_2_IEO (1 << 23) /* Bit 23: Invert Output Enable */
+#define LCD_RASTER_TIMING_2_PHSVS_RF (1 << 24) /* Bit 24: Program HSYNC/VSYNC Rise or Fall */
+#define LCD_RASTER_TIMING_2_PHSVS_ON (1 << 25) /* Bit 25: Hsync/Vsync Pixel Clock Control On/Off */
+#define LCD_RASTER_TIMING_2_LPP_B10_SHIFT (26) /* Bit 26: Lines Per Panel Bit 10 */
+#define LCD_RASTER_TIMING_2_LPP_B10_MASK (1 << LCD_RASTER_TIMING_2_LPP_B10_SHIFT)
+#define LCD_RASTER_TIMING_2_HSW_HBITS_SHIFT (27) /* Bits 27-30: Bits 9 to 6 of the horizontal sync width field */
+#define LCD_RASTER_TIMING_2_HSW_HBITS_MASK (15 << LCD_RASTER_TIMING_2_HSW_HBITS_SHITF)
+
+#define LCD_RASTER_SUBPANEL_DPDLSB_SHIFT (0) /* Bits 0-15: Default Pixel Data LSB */
+#define LCD_RASTER_SUBPANEL_DPDLSB_MASK (65535 << LCD_RASTER_SUBPANEL_DPDLSB_SHIFT)
+#define LCD_RASTER_SUBPANEL_LPPT_SHIFT (16) /* Bits 16-25: Line Per Panel Threshold */
+#define LCD_RASTER_SUBPANEL_LPPT_MASK (1023 << LCD_RASTER_SUBPANEL_LPPT_SHIFT)
+#define LCD_RASTER_SUBPANEL_HOLS (1 << 29) /* Bit 29: High or Low Signal */
+#define LCD_RASTER_SUBPANEL_SPEN (1 << 31) /* Bit 31: Sub Panel Enable */
+
+#define LCD_RASTER_SUBPANEL2_DPDMSB_SHIFT (0) /* Bits 0-7: Default Pixel Data MSB */
+#define LCD_RASTER_SUBPANEL2_DPDMSB_MASK (255 << LCD_RASTER_SUBPANEL2_DPDMSB_SHIFT)
+#define LCD_RASTER_SUBPANEL2_LPPT_B10 (1 << 8) /* Bit 8: Lines Per Panel Threshold Bit 10 */
+
+#define LCD_DMA_CTRL_FRAME_MODE (1 << 0) /* Bit 0: Frame Mode */
+#define LCD_DMA_CTRL_BE (1 << 1) /* Bit 1: Big Endian Enable */
+#define LCD_DMA_CTRL_BYTE_SWAP (1 << 3) /* Bit 3: Bytelane Ordering */
+#define LCD_DMA_CTRL_BURST_SIZE_SHIFT (4) /* Bits 4-6: Burst Size setting for DMA transfers */
+#define LCD_DMA_CTRL_BURST_SIZE_MASK (7 << LCD_DMA_CTRL_BURST_SIZE_SHIFT)
+# define LCD_DMA_CTRL_BURST_SIZE_1 (0 << LCD_DMA_CTRL_BURST_SIZE_SHIFT) /* Burst size of 1 */
+# define LCD_DMA_CTRL_BURST_SIZE_2 (1 << LCD_DMA_CTRL_BURST_SIZE_SHIFT) /* Burst size of 2 */
+# define LCD_DMA_CTRL_BURST_SIZE_4 (2 << LCD_DMA_CTRL_BURST_SIZE_SHIFT) /* Burst size of 4 */
+# define LCD_DMA_CTRL_BURST_SIZE_8 (3 << LCD_DMA_CTRL_BURST_SIZE_SHIFT) /* Burst size of 8 */
+# define LCD_DMA_CTRL_BURST_SIZE_16 (4 << LCD_DMA_CTRL_BURST_SIZE_SHIFT) /* Burst size of 6 */
+#define LCD_DMA_CTRL_TH_FIFO_RDY_SHIFT (8) /* Bits 8-10: DMA FIFO threshold */
+#define LCD_DMA_CTRL_TH_FIFO_RDY_MASK (7 << LCD_DMA_CTRL_TH_FIFO_RDY_SHIFT)
+# define LCD_DMA_CTRL_TH_FIFO_RDY_8 (0 << LCD_DMA_CTRL_TH_FIFO_RDY_MASK) /* 8 words have been loaded */
+# define LCD_DMA_CTRL_TH_FIFO_RDY_16 (1 << LCD_DMA_CTRL_TH_FIFO_RDY_MASK) /* 16 words have been loaded */
+# define LCD_DMA_CTRL_TH_FIFO_RDY_32 (2 << LCD_DMA_CTRL_TH_FIFO_RDY_MASK) /* 32 words have been loaded */
+# define LCD_DMA_CTRL_TH_FIFO_RDY_64 (3 << LCD_DMA_CTRL_TH_FIFO_RDY_MASK) /* 64 words have been loaded */
+# define LCD_DMA_CTRL_TH_FIFO_RDY_128 (4 << LCD_DMA_CTRL_TH_FIFO_RDY_MASK) /* 128 words have been loaded */
+# define LCD_DMA_CTRL_TH_FIFO_RDY_256 (5 << LCD_DMA_CTRL_TH_FIFO_RDY_MASK) /* 256 words have been loaded */
+# define LCD_DMA_CTRL_TH_FIFO_RDY_512 (6 << LCD_DMA_CTRL_TH_FIFO_RDY_MASK) /* 512 words have been loaded */
+#define LCD_DMA_CTRL_MASTER_PRIO_SHIFT (16) /* Bits 16-18: Priority for the L3 OCP Master Bus */
+#define LCD_DMA_CTRL_MASTER_PRIO_MASK (7 << LCD_DMA_CTRL_MASTER_PRIO_SHIFT)
+
+#define LCD_DMA_FB_BASE_SHIFT (2) /* Bits 2-31: Frame Buffer Base Address pointer */
+#define LCD_DMA_FB_BASE_MASK (0x3fffffff << LCD_DMA_FB_BASE_SHIFT)
+
+#define LCD_DMA_FB_CEIL_SHIFT (2) /* Bits 2-31: Frame Buffer Ceiling Address pointer */
+#define LCD_DMA_FB_CEIL_MASK (0x3fffffff << LCD_DMA_FB_BASE_SHIFT)
+
+#define LCD_SYSC_IDLE_SHIFT (2) /* Bits 2-3: Configuration of the local target state management mode */
+#define LCD_SYSC_IDLE_MASK (3 << LCD_SYSC_IDLE_SHIFT)
+# define LCD_SYSC_IDLE_FORCE (0 << LCD_SYSC_IDLE_SHIFT) /* Force-idle mode */
+# define LCD_SYSC_IDLE_NO (1 << LCD_SYSC_IDLE_SHIFT) /* No-idle mode */
+# define LCD_SYSC_IDLE_SMART (2 << LCD_SYSC_IDLE_SHIFT) /* Smart-idle mode */
+#define LCD_SYSC_STANDBY_SHIFT (4) /* Bits 4-5: Configuration of the local initiator state management mode */
+#define LCD_SYSC_STANDBY_MASK (3 << LCD_SYSC_STANDBY_SHIFT)
+# define LCD_SYSC_STANDBY_FORCE (0 << LCD_SYSC_STANDBY_SHIFT) /* Force-standby mode */
+# define LCD_SYSC_STANDBY_NO (1 << LCD_SYSC_STANDBY_SHIFT) /* No-standby mode */
+# define LCD_SYSC_STANDBY_SMART (2 << LCD_SYSC_STANDBY_SHIFT) /* Smart-standby mode */
+
+#define LCD_IRQ_DONE (1 << 0) /* Bit 0: Raster or LIDD Frame Done */
+#define LCD_IRQ_RR_DONE (1 << 1) /* Bit 1: Raster Mode Frame Done */
+#define LCD_IRQ_SYNC (1 << 2) /* Bit 2: Frame Synchronization Lost */
+#define LCD_IRQ_ACB (1 << 3) /* Bit 3: For Passive Matrix Panels Only AC Bias Count */
+#define LCD_IRQ_FUF (1 << 5) /* Bit 5: DMA FIFO Underflow */
+#define LCD_IRQ_PL (1 << 6) /* Bit 6: DMA Palette Loaded */
+#define LCD_IRQ_EOF0 (1 << 8) /* Bit 8: DMA End-of-Frame 0 */
+#define LCD_IRQ_EOF1 (1 << 9) /* Bit 9: DMA End-of-Frame 1 */
+
+#define LCD_CLKC_ENABLE_CORE (1 << 0) /* Bit 0: Software Clock Enable for the DMA submodule */
+#define LCD_CLKC_ENABLE_LIDD (1 << 1) /* Bit 1: Software Clock Enable for the LIDD submodule */
+#define LCD_CLKC_ENABLE_DMA (1 << 2) /* Bit 2: Software Clock Enable for the Core */
+
+#define LCD_CLKC_RESET_CORE (1 << 0) /* Bit 0: Software Reset for the Core */
+#define LCD_CLKC_RESET_LIDD (1 << 1) /* Bit 1: Software Reset for the LIDD submodule */
+#define LCD_CLKC_RESET_DMA (1 << 2) /* Bit 2: Software Reset for the DMA submodule */
+#define LCD_CLKC_RESET_MAIN (1 << 3) /* Bit 3: Software Reset for the entire LCD module */
+
+#endif /* __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_LCD_H */
diff --git a/arch/arm/src/am335x/hardware/am335x_mcspi.h b/arch/arm/src/am335x/hardware/am335x_mcspi.h
new file mode 100644
index 00000000000..02ad9f16f47
--- /dev/null
+++ b/arch/arm/src/am335x/hardware/am335x_mcspi.h
@@ -0,0 +1,322 @@
+/************************************************************************************
+ * arch/arm/src/am335x/hardware/am335x_mcspi.h
+ *
+ * Copyright (C) 2019 Petro Karashchenko. All rights reserved.
+ * Author: Petro Karashchenko
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_MCSPI_H
+#define __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_MCSPI_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include
+#include "hardware/am335x_memorymap.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register offsets *****************************************************************/
+
+#define AM335X_MCSPI_SYSC_OFFSET 0x0110
+#define AM335X_MCSPI_SYSS_OFFSET 0x0114
+#define AM335X_MCSPI_IRQ_STAT_OFFSET 0x0118
+#define AM335X_MCSPI_IRQ_EN_OFFSET 0x011c
+#define AM335X_MCSPI_SYST_OFFSET 0x0124
+#define AM335X_MCSPI_MODUL_CTRL_OFFSET 0x0128
+#define AM335X_MCSPI_CH0_CONF_OFFSET 0x012c
+#define AM335X_MCSPI_CH0_STAT_OFFSET 0x0130
+#define AM335X_MCSPI_CH0_CTRL_OFFSET 0x0134
+#define AM335X_MCSPI_TX0_OFFSET 0x0138
+#define AM335X_MCSPI_RX0_OFFSET 0x013c
+#define AM335X_MCSPI_CH1_CONF_OFFSET 0x0140
+#define AM335X_MCSPI_CH1_STAT_OFFSET 0x0144
+#define AM335X_MCSPI_CH1_CTRL_OFFSET 0x0148
+#define AM335X_MCSPI_TX1_OFFSET 0x014c
+#define AM335X_MCSPI_RX1_OFFSET 0x0150
+#define AM335X_MCSPI_CH2_CONF_OFFSET 0x0154
+#define AM335X_MCSPI_CH2_STAT_OFFSET 0x0158
+#define AM335X_MCSPI_CH2_CTRL_OFFSET 0x015c
+#define AM335X_MCSPI_TX2_OFFSET 0x0160
+#define AM335X_MCSPI_RX2_OFFSET 0x0164
+#define AM335X_MCSPI_CH3_CONF_OFFSET 0x0168
+#define AM335X_MCSPI_CH3_STAT_OFFSET 0x016c
+#define AM335X_MCSPI_CH3_CTRL_OFFSET 0x0170
+#define AM335X_MCSPI_TX3_OFFSET 0x0174
+#define AM335X_MCSPI_RX3_OFFSET 0x0178
+#define AM335X_MCSPI_XFER_LEVEL_OFFSET 0x017c
+#define AM335X_MCSPI_DAFTX_OFFSET 0x0180
+#define AM335X_MCSPI_DAFRX_OFFSET 0x01a0
+
+#define AM335X_MCSPI_CH_CONF_OFFSET(n) (0x012c + (unsigned int)(n) * 0x14)
+#define AM335X_MCSPI_CH_STAT_OFFSET(n) (0x0130 + (unsigned int)(n) * 0x14)
+#define AM335X_MCSPI_CH_CTRL_OFFSET(n) (0x0134 + (unsigned int)(n) * 0x14)
+#define AM335X_MCSPI_TX_OFFSET(n) (0x0138 + (unsigned int)(n) * 0x14)
+#define AM335X_MCSPI_RX_OFFSET(n) (0x013c + (unsigned int)(n) * 0x14)
+
+/* Register virtual addresses *******************************************************/
+
+#define AM335X_MCSPI0_SYSC (AM335X_MCSPI0_VADDR + AM335X_MCSPI_SYSC_OFFSET)
+#define AM335X_MCSPI0_SYSS (AM335X_MCSPI0_VADDR + AM335X_MCSPI_SYSS_OFFSET)
+#define AM335X_MCSPI0_IRQ_STAT (AM335X_MCSPI0_VADDR + AM335X_MCSPI_IRQ_STAT_OFFSET)
+#define AM335X_MCSPI0_IRQ_EN (AM335X_MCSPI0_VADDR + AM335X_MCSPI_IRQ_EN_OFFSET)
+#define AM335X_MCSPI0_SYST (AM335X_MCSPI0_VADDR + AM335X_MCSPI_SYST_OFFSET)
+#define AM335X_MCSPI0_MODUL_CTRL (AM335X_MCSPI0_VADDR + AM335X_MCSPI_MODUL_CTRL_OFFSET)
+#define AM335X_MCSPI0_CH0_CONF (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH0_CONF_OFFSET)
+#define AM335X_MCSPI0_CH0_STAT (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH0_STAT_OFFSET)
+#define AM335X_MCSPI0_CH0_CTRL (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH0_CTRL_OFFSET)
+#define AM335X_MCSPI0_TX0 (AM335X_MCSPI0_VADDR + AM335X_MCSPI_TX0_OFFSET)
+#define AM335X_MCSPI0_RX0 (AM335X_MCSPI0_VADDR + AM335X_MCSPI_RX0_OFFSET)
+#define AM335X_MCSPI0_CH1_CONF (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH1_CONF_OFFSET)
+#define AM335X_MCSPI0_CH1_STAT (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH1_STAT_OFFSET)
+#define AM335X_MCSPI0_CH1_CTRL (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH1_CTRL_OFFSET)
+#define AM335X_MCSPI0_TX1 (AM335X_MCSPI0_VADDR + AM335X_MCSPI_TX1_OFFSET)
+#define AM335X_MCSPI0_RX1 (AM335X_MCSPI0_VADDR + AM335X_MCSPI_RX1_OFFSET)
+#define AM335X_MCSPI0_CH2_CONF (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH2_CONF_OFFSET)
+#define AM335X_MCSPI0_CH2_STAT (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH2_STAT_OFFSET)
+#define AM335X_MCSPI0_CH2_CTRL (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH2_CTRL_OFFSET)
+#define AM335X_MCSPI0_TX2 (AM335X_MCSPI0_VADDR + AM335X_MCSPI_TX2_OFFSET)
+#define AM335X_MCSPI0_RX2 (AM335X_MCSPI0_VADDR + AM335X_MCSPI_RX2_OFFSET)
+#define AM335X_MCSPI0_CH3_CONF (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH3_CONF_OFFSET)
+#define AM335X_MCSPI0_CH3_STAT (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH3_STAT_OFFSET)
+#define AM335X_MCSPI0_CH3_CTRL (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH3_CTRL_OFFSET)
+#define AM335X_MCSPI0_TX3 (AM335X_MCSPI0_VADDR + AM335X_MCSPI_TX3_OFFSET)
+#define AM335X_MCSPI0_RX3 (AM335X_MCSPI0_VADDR + AM335X_MCSPI_RX3_OFFSET)
+#define AM335X_MCSPI0_XFER_LEVEL (AM335X_MCSPI0_VADDR + AM335X_MCSPI_XFER_LEVEL_OFFSET)
+#define AM335X_MCSPI0_DAFTX (AM335X_MCSPI0_VADDR + AM335X_MCSPI_DAFTX_OFFSET)
+#define AM335X_MCSPI0_DAFRX (AM335X_MCSPI0_VADDR + AM335X_MCSPI_DAFRX_OFFSET)
+
+#define AM335X_MCSPI0_CH_CONF(n) (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH_CONF_OFFSET(n))
+#define AM335X_MCSPI0_CH_STAT(n) (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH_STAT_OFFSET(n))
+#define AM335X_MCSPI0_CH_CTRL(n) (AM335X_MCSPI0_VADDR + AM335X_MCSPI_CH_CTRL_OFFSET(n))
+#define AM335X_MCSPI0_TX(n) (AM335X_MCSPI0_VADDR + AM335X_MCSPI_TX_OFFSET(n))
+#define AM335X_MCSPI0_RX(n) (AM335X_MCSPI0_VADDR + AM335X_MCSPI_RX_OFFSET(n))
+
+#define AM335X_MCSPI1_SYSC (AM335X_MCSPI1_VADDR + AM335X_MCSPI_SYSC_OFFSET)
+#define AM335X_MCSPI1_SYSS (AM335X_MCSPI1_VADDR + AM335X_MCSPI_SYSS_OFFSET)
+#define AM335X_MCSPI1_IRQ_STAT (AM335X_MCSPI1_VADDR + AM335X_MCSPI_IRQ_STAT_OFFSET)
+#define AM335X_MCSPI1_IRQ_EN (AM335X_MCSPI1_VADDR + AM335X_MCSPI_IRQ_EN_OFFSET)
+#define AM335X_MCSPI1_SYST (AM335X_MCSPI1_VADDR + AM335X_MCSPI_SYST_OFFSET)
+#define AM335X_MCSPI1_MODUL_CTRL (AM335X_MCSPI1_VADDR + AM335X_MCSPI_MODUL_CTRL_OFFSET)
+#define AM335X_MCSPI1_CH0_CONF (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH0_CONF_OFFSET)
+#define AM335X_MCSPI1_CH0_STAT (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH0_STAT_OFFSET)
+#define AM335X_MCSPI1_CH0_CTRL (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH0_CTRL_OFFSET)
+#define AM335X_MCSPI1_TX0 (AM335X_MCSPI1_VADDR + AM335X_MCSPI_TX0_OFFSET)
+#define AM335X_MCSPI1_RX0 (AM335X_MCSPI1_VADDR + AM335X_MCSPI_RX0_OFFSET)
+#define AM335X_MCSPI1_CH1_CONF (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH1_CONF_OFFSET)
+#define AM335X_MCSPI1_CH1_STAT (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH1_STAT_OFFSET)
+#define AM335X_MCSPI1_CH1_CTRL (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH1_CTRL_OFFSET)
+#define AM335X_MCSPI1_TX1 (AM335X_MCSPI1_VADDR + AM335X_MCSPI_TX1_OFFSET)
+#define AM335X_MCSPI1_RX1 (AM335X_MCSPI1_VADDR + AM335X_MCSPI_RX1_OFFSET)
+#define AM335X_MCSPI1_CH2_CONF (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH2_CONF_OFFSET)
+#define AM335X_MCSPI1_CH2_STAT (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH2_STAT_OFFSET)
+#define AM335X_MCSPI1_CH2_CTRL (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH2_CTRL_OFFSET)
+#define AM335X_MCSPI1_TX2 (AM335X_MCSPI1_VADDR + AM335X_MCSPI_TX2_OFFSET)
+#define AM335X_MCSPI1_RX2 (AM335X_MCSPI1_VADDR + AM335X_MCSPI_RX2_OFFSET)
+#define AM335X_MCSPI1_CH3_CONF (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH3_CONF_OFFSET)
+#define AM335X_MCSPI1_CH3_STAT (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH3_STAT_OFFSET)
+#define AM335X_MCSPI1_CH3_CTRL (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH3_CTRL_OFFSET)
+#define AM335X_MCSPI1_TX3 (AM335X_MCSPI1_VADDR + AM335X_MCSPI_TX3_OFFSET)
+#define AM335X_MCSPI1_RX3 (AM335X_MCSPI1_VADDR + AM335X_MCSPI_RX3_OFFSET)
+#define AM335X_MCSPI1_XFER_LEVEL (AM335X_MCSPI1_VADDR + AM335X_MCSPI_XFER_LEVEL_OFFSET)
+#define AM335X_MCSPI1_DAFTX (AM335X_MCSPI1_VADDR + AM335X_MCSPI_DAFTX_OFFSET)
+#define AM335X_MCSPI1_DAFRX (AM335X_MCSPI1_VADDR + AM335X_MCSPI_DAFRX_OFFSET)
+
+#define AM335X_MCSPI1_CH_CONF(n) (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH_CONF_OFFSET(n))
+#define AM335X_MCSPI1_CH_STAT(n) (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH_STAT_OFFSET(n))
+#define AM335X_MCSPI1_CH_CTRL(n) (AM335X_MCSPI1_VADDR + AM335X_MCSPI_CH_CTRL_OFFSET(n))
+#define AM335X_MCSPI1_TX(n) (AM335X_MCSPI1_VADDR + AM335X_MCSPI_TX_OFFSET(n))
+#define AM335X_MCSPI1_RX(n) (AM335X_MCSPI1_VADDR + AM335X_MCSPI_RX_OFFSET(n))
+
+/* Register bit field definitions ***************************************************/
+
+#define MCSPI_SYSC_AUTOIDLE (1 << 0) /* Bit 0: Internal OCP Clock gating strategy */
+#define MCSPI_SYSC_SRST (1 << 1) /* Bit 1: Software reset */
+#define MCSPI_SYSC_IDLE_SHIFT (3) /* Bits 3-4: Power management */
+#define MCSPI_SYSC_IDLE_MASK (3 << MCSPI_SYSC_IDLE_MASK)
+# define MCSPI_SYSC_IDLE_FORCE (0 << MCSPI_SYSC_IDLE_SHIFT) /* Force-idle mode */
+# define MCSPI_SYSC_IDLE_NO (1 << MCSPI_SYSC_IDLE_SHIFT) /* No-idle mode */
+# define MCSPI_SYSC_IDLE_SMART (2 << MCSPI_SYSC_IDLE_SHIFT) /* Smart-idle mode */
+#define MCSPI_SYSC_CLK_SHIFT (8) /* Bits 8-9: Clocks activity during wake-up mode period */
+#define MCSPI_SYSC_CLK_MASK (3 << MCSPI_SYSC_CLK_SHIFT)
+# define MCSPI_SYSC_CLK_NONE (0 << MCSPI_SYSC_CLK_SHIFT) /* Both clocks may be switched off */
+# define MCSPI_SYSC_CLK_OCP (1 << MCSPI_SYSC_CLK_SHIFT) /* Only OCP clock is maintained */
+# define MCSPI_SYSC_CLK_FUNC (2 << MCSPI_SYSC_CLK_SHIFT) /* Only functions clock is maintained */
+# define MCSPI_SYSC_CLK_BOTH (3 << MCSPI_SYSC_CLK_SHIFT) /* Both clocks are maintained */
+
+#define MCSPI_SYSS_RST_DONE (1 << 0) /* Bit 0: Reset done */
+
+#define MCSPI_IRQ_TX0_EMPTY (0) /* Bit 0: Channel 0 transmitter register empty or almost empty */
+#define MCSPI_IRQ_TX0_UFLOW (1) /* Bit 1: Channel 0 transmitter register underflow */
+#define MCSPI_IRQ_RX0_FULL (2) /* Bit 2: Channel 0 receiver register full or almost full */
+#define MCSPI_IRQ_RX0_OFLOW (3) /* Bit 3: Channel 0 receiver register overflow (slave mode only). */
+#define MCSPI_IRQ_TX1_EMPTY (4) /* Bit 4: Channel 1 transmitter register empty or almost empty */
+#define MCSPI_IRQ_TX1_UFLOW (5) /* Bit 5: Channel 1 transmitter register underflow */
+#define MCSPI_IRQ_RX1_FULL (6) /* Bit 6: Channel 1 receiver register full or almost full */
+#define MCSPI_IRQ_TX2_EMPTY (8) /* Bit 8: Channel 2 transmitter register empty or almost empty */
+#define MCSPI_IRQ_TX2_UFLOW (9) /* Bit 9: Channel 2 transmitter register underflow */
+#define MCSPI_IRQ_RX2_FULL (10) /* Bit 10: Channel 2 receiver register full or almost full */
+#define MCSPI_IRQ_TX3_EMPTY (12) /* Bit 12: Channel 3 transmitter register empty or almost empty */
+#define MCSPI_IRQ_TX3_UFLOW (13) /* Bit 13: Channel 3 transmitter register underflow */
+#define MCSPI_IRQ_RX3_FULL (14) /* Bit 14: Channel 3 receiver register full or almost full */
+#define MCSPI_IRQ_EOW (17) /* Bit 17: End of word (EOW) count event */
+
+#define MCSPI_SYST_SPIEN0 (1 << 0) /* Bit 0: SPIEN[0] line (signal data value) */
+#define MCSPI_SYST_SPIEN1 (1 << 1) /* Bit 1: SPIEN[1] line (signal data value) */
+#define MCSPI_SYST_SPIEN2 (1 << 2) /* Bit 2: SPIEN[2] line (signal data value) */
+#define MCSPI_SYST_SPIEN3 (1 << 3) /* Bit 3: SPIEN[3] line (signal data value) */
+#define MCSPI_SYST_SPIDAT0 (1 << 4) /* Bit 4: SPIDAT[0] line (signal data value) */
+#define MCSPI_SYST_SPIDAT1 (1 << 5) /* Bit 5: SPIDAT[1] line (signal data value) */
+#define MCSPI_SYST_SPICLK (1 << 6) /* Bit 6: SPICLK line (signal data value) */
+#define MCSPI_SYST_SPIDAT_DIR0 (1 << 8) /* Bit 8: Sets the direction of the SPIDAT[0] */
+#define MCSPI_SYST_SPIDAT_DIR1 (1 << 9) /* Bit 9: Sets the direction of the SPIDAT[1] */
+#define MCSPI_SYST_SPIEN_DIR (1 << 10) /* Bit 10: Sets the direction of the SPIEN */
+#define MCSPI_SYST_SSB (1 << 11) /* Bit 11: Set status bit */
+
+#define MCSPI_MODUL_CTRL_SINGLE (1 << 0) /* Bit 0: Single Channel / Multi Channel selection */
+#define MCSPI_MODUL_CTRL_PIN34 (1 << 1) /* Bit 1: Pin mode selection */
+#define MCSPI_MODUL_CTRL_MS (1 << 2) /* Bit 2: Master / Slave selection */
+#define MCSPI_MODUL_CTRL_SYS_TEST (1 << 3) /* Bit 3: Enables the system test mode */
+#define MCSPI_MODUL_CTRL_IDLY_SHIFT (4) /* Bits 4-6: Initial SPI delay for first transfer */
+#define MCSPI_MODUL_CTRL_IDLY_MASK (15 << MCSPI_MODUL_CTRL_INIT_DLY_SHIFT)
+# define MCSPI_MODUL_CTRL_IDLY_NONE (0 << MCSPI_MODUL_CTRL_INIT_DLY_SHIFT) /* No delay for first SPI transfer */
+# define MCSPI_MODUL_CTRL_IDLY_4CLK (1 << MCSPI_MODUL_CTRL_INIT_DLY_SHIFT) /* The controller wait 4 SPI bus clock */
+# define MCSPI_MODUL_CTRL_IDLY_8CLK (2 << MCSPI_MODUL_CTRL_INIT_DLY_SHIFT) /* The controller wait 8 SPI bus clock */
+# define MCSPI_MODUL_CTRL_IDLY_16CLK (3 << MCSPI_MODUL_CTRL_INIT_DLY_SHIFT) /* The controller wait 16 SPI bus clock */
+# define MCSPI_MODUL_CTRL_IDLY_32CLK (4 << MCSPI_MODUL_CTRL_INIT_DLY_SHIFT) /*The controller wait 32 SPI bus clock */
+#define MCSPI_MODUL_CTRL_MOA (1 << 7) /* Bit 7: Multiple word OCP access */
+#define MCSPI_MODUL_CTRL_FDAA (1 << 8) /* Bit 8: FIFO DMA Address 256 bit aligned */
+
+#define MCSPI_CH_CONF_PHA (1 << 0) /* Bit 0: SPICLK phase */
+#define MCSPI_CH_CONF_POL (1 << 1) /* Bit 1: SPICLK polarity */
+#define MCSPI_CH_CONF_CLKD_SHIFT (2) /* Bits 2-5: Frequency divider for SPICLK */
+#define MCSPI_CH_CONF_CLKD_MASK (15 << MCSPI_CH_CONF_CLKD_SHIFT)
+# define MCSPI_CH_CONF_CLKD_DIV1 (0 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 1 */
+# define MCSPI_CH_CONF_CLKD_DIV2 (1 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 2 */
+# define MCSPI_CH_CONF_CLKD_DIV4 (2 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 4 */
+# define MCSPI_CH_CONF_CLKD_DIV8 (3 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 8 */
+# define MCSPI_CH_CONF_CLKD_DIV16 (4 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 16 */
+# define MCSPI_CH_CONF_CLKD_DIV32 (5 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 32 */
+# define MCSPI_CH_CONF_CLKD_DIV64 (6 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 64 */
+# define MCSPI_CH_CONF_CLKD_DIV128 (7 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 128 */
+# define MCSPI_CH_CONF_CLKD_DIV256 (8 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 256 */
+# define MCSPI_CH_CONF_CLKD_DIV512 (9 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 512 */
+# define MCSPI_CH_CONF_CLKD_DIV1K (10 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 1024 */
+# define MCSPI_CH_CONF_CLKD_DIV2K (11 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 2048 */
+# define MCSPI_CH_CONF_CLKD_DIV4K (12 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 4096 */
+# define MCSPI_CH_CONF_CLKD_DIV8K (13 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 8192 */
+# define MCSPI_CH_CONF_CLKD_DIV16K (14 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 16384 */
+# define MCSPI_CH_CONF_CLKD_DIV32K (15 << MCSPI_CH_CONF_CLKD_SHIFT) /* Divide by 32768 */
+#define MCSPI_CH_CONF_EPOL (1 << 6) /* Bit 6: SPIEN polarity */
+#define MCSPI_CH_CONF_WL_SHIFT (7) /* Bits 7-11: SPI word length */
+#define MCSPI_CH_CONF_WL_MASK (31 << MCSPI_CH_CONF_WL_SHIFT)
+# define MCSPI_CH_CONF_WL_4BITS (3 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 4-bits long */
+# define MCSPI_CH_CONF_WL_5BITS (4 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 5-bits long */
+# define MCSPI_CH_CONF_WL_6BITS (5 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 6-bits long */
+# define MCSPI_CH_CONF_WL_7BITS (6 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 7-bits long */
+# define MCSPI_CH_CONF_WL_8BITS (7 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 8-bits long */
+# define MCSPI_CH_CONF_WL_9BITS (8 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 9-bits long */
+# define MCSPI_CH_CONF_WL_10BITS (9 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 10-bits long */
+# define MCSPI_CH_CONF_WL_11BITS (10 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 11-bits long */
+# define MCSPI_CH_CONF_WL_12BITS (11 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 12-bits long */
+# define MCSPI_CH_CONF_WL_13BITS (12 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 13-bits long */
+# define MCSPI_CH_CONF_WL_14BITS (13 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 14-bits long */
+# define MCSPI_CH_CONF_WL_15BITS (14 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 15-bits long */
+# define MCSPI_CH_CONF_WL_16BITS (15 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 16-bits long */
+# define MCSPI_CH_CONF_WL_17BITS (16 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 17-bits long */
+# define MCSPI_CH_CONF_WL_18BITS (17 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 18-bits long */
+# define MCSPI_CH_CONF_WL_19BITS (18 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 19-bits long */
+# define MCSPI_CH_CONF_WL_20BITS (19 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 20-bits long */
+# define MCSPI_CH_CONF_WL_21BITS (20 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 21-bits long */
+# define MCSPI_CH_CONF_WL_22BITS (21 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 22-bits long */
+# define MCSPI_CH_CONF_WL_23BITS (22 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 23-bits long */
+# define MCSPI_CH_CONF_WL_24BITS (23 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 24-bits long */
+# define MCSPI_CH_CONF_WL_25BITS (24 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 25-bits long */
+# define MCSPI_CH_CONF_WL_26BITS (25 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 26-bits long */
+# define MCSPI_CH_CONF_WL_27BITS (26 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 27-bits long */
+# define MCSPI_CH_CONF_WL_28BITS (27 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 28-bits long */
+# define MCSPI_CH_CONF_WL_29BITS (28 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 29-bits long */
+# define MCSPI_CH_CONF_WL_30BITS (29 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 30-bits long */
+# define MCSPI_CH_CONF_WL_31BITS (30 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 31-bits long */
+# define MCSPI_CH_CONF_WL_32BITS (31 << MCSPI_CH_CONF_WL_SHIFT) /* The SPI word is 32-bits long */
+#define MCSPI_CH_CONF_TRM_SHIFT (12) /* Bits 12-13: Transmit/receive modes */
+#define MCSPI_CH_CONF_TRM_MASK (3 << MCSPI_CH_CONF_TRM_SHIFT)
+# define MCSPI_CH_CONF_TRM_RXTX (0 << MCSPI_CH_CONF_TRM_SHIFT) /* Transmit and receive mode */
+# define MCSPI_CH_CONF_TRM_RX (1 << MCSPI_CH_CONF_TRM_SHIFT) /* Receive-only mode */
+# define MCSPI_CH_CONF_TRM_TX (2 << MCSPI_CH_CONF_TRM_SHIFT) /* Transmit-only mode */
+#define MCSPI_CH_CONF_DMAW (1 << 14) /* Bit 14: DMA write request */
+#define MCSPI_CH_CONF_DMAR (1 << 15) /* Bit 15: DMA read request */
+#define MCSPI_CH_CONF_DPE0 (1 << 16) /* Bit 16: Transmission enable for data line 0 */
+#define MCSPI_CH_CONF_DPE1 (1 << 17) /* Bit 17: Transmission enable for data line 1 */
+#define MCSPI_CH_CONF_IS (1 << 18) /* Bit 18: Input select */
+#define MCSPI_CH_CONF_TURBO (1 << 19) /* Bit 19: Turbo mode */
+#define MCSPI_CH_CONF_FORCE (1 << 20) /* Bit 20: Manual SPIEN assertion to keep SPIEN active between SPI words */
+#define MCSPI_CH_CONF_SPIENSLV_SHIFT (21) /* Bits 21-22: SPI slave select signal detection */
+#define MCSPI_CH_CONF_SPIENSLV_MASK (3 << MCSPI_CH_CONF_SPIENSLV_SHIFT)
+# define MCSPI_CH_CONF_SPIENSLV0 (0 << MCSPI_CH_CONF_SPIENSLV_SHIFT) /* Detection enabled only on SPIEN[0] */
+# define MCSPI_CH_CONF_SPIENSLV1 (1 << MCSPI_CH_CONF_SPIENSLV_SHIFT) /* Detection enabled only on SPIEN[1] */
+# define MCSPI_CH_CONF_SPIENSLV2 (2 << MCSPI_CH_CONF_SPIENSLV_SHIFT) /* Detection enabled only on SPIEN[2] */
+# define MCSPI_CH_CONF_SPIENSLV3 (3 << MCSPI_CH_CONF_SPIENSLV_SHIFT) /* Detection enabled only on SPIEN[3] */
+#define MCSPI_CH_CONF_SBE (1 << 23) /* Bit 23: Start bit enable for SPI transfer */
+#define MCSPI_CH_CONF_SBPOL (1 << 24) /* Bit 24: Start bit polarity */
+#define MCSPI_CH_CONF_TCS_SHIFT (25) /* Bits 25-26: Chip select time control */
+#define MCSPI_CH_CONF_TCS_MASK (3 << MCSPI_CH_CONF_TCS_SHIFT)
+# define MCSPI_CH_CONF_TCS_0P5 (0 << MCSPI_CH_CONF_TCS_SHIFT) /* 0.5 clock cycles */
+# define MCSPI_CH_CONF_TCS_1P5 (1 << MCSPI_CH_CONF_TCS_SHIFT) /* 1.5 clock cycles */
+# define MCSPI_CH_CONF_TCS_2P5 (2 << MCSPI_CH_CONF_TCS_SHIFT) /* 2.5 clock cycles */
+# define MCSPI_CH_CONF_TCS_3P5 (3 << MCSPI_CH_CONF_TCS_SHIFT) /* 3.5 clock cycles */
+#define MCSPI_CH_CONF_FFEW (1 << 27) /* Bit 27: FIFO enabled for transmit */
+#define MCSPI_CH_CONF_FFER (1 << 28) /* Bit 28: FIFO enabled for receive */
+#define MCSPI_CH_CONF_CLKG (1 << 29) /* Bit 29: Clock divider granularity */
+
+#define MCSPI_CH_STAT_RXS (1 << 0) /* Bit 0: Channel receiver register status */
+#define MCSPI_CH_STAT_TXS (1 << 1) /* Bit 1: Channel transmitter register status */
+#define MCSPI_CH_STAT_EOT (1 << 2) /* Bit 2: Channel end-of-transfer status */
+#define MCSPI_CH_STAT_TXFFE (1 << 3) /* Bit 3: Channel FIFO transmit buffer empty status */
+#define MCSPI_CH_STAT_TXFFF (1 << 4) /* Bit 4: Channel FIFO transmit buffer full status */
+#define MCSPI_CH_STAT_RXFFE (1 << 5) /* Bit 5: Channel FIFO receive buffer empty status */
+#define MCSPI_CH_STAT_RXFFF (1 << 6) /* Bit 6: Channel FIFO receive buffer full status */
+
+#define MCSPI_CH_CTRL_EN (1 << 0) /* Bit 0: Channel enable */
+#define MCSPI_CH_CTRL_EXTCLK_SHFT (8) /* Bits 8-15: Clock ratio extension */
+#define MCSPI_CH_CTRL_EXTCLK_MASK (255 << MCSPI_CH_CTRL_EXTCLK_SHFT)
+
+#define MCSPI_XFER_LEVEL_AEL_SHIFT (0) /* Bits 0-7: Buffer almost empty */
+#define MCSPI_XFER_LEVEL_AEL_MASK (255 << MCSPI_XFER_LEVEL_AEL_SHIFT)
+#define MCSPI_XFER_LEVEL_AFL_SHIFT (8) /* Bits 8-15: Buffer almost full */
+#define MCSPI_XFER_LEVEL_AFL_MASK (255 << MCSPI_XFER_LEVEL_AFL_SHIFT)
+#define MCSPI_XFER_LEVEL_WCNT_SHIFT (16) /* Bits 16-31: SPI word counter */
+#define MCSPI_XFER_LEVEL_WCNT_MASK (65535 << MCSPI_XFER_LEVEL_WCNT_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_MCSPI_H */
diff --git a/arch/arm/src/am335x/hardware/am335x_wdog.h b/arch/arm/src/am335x/hardware/am335x_wdog.h
index cd52b23395c..514a70edb73 100644
--- a/arch/arm/src/am335x/hardware/am335x_wdog.h
+++ b/arch/arm/src/am335x/hardware/am335x_wdog.h
@@ -49,57 +49,57 @@
/* Register offsets *****************************************************************/
-#define AM335X_WDT_WIDR_OFFSET 0x0000 /* Watchdog Identification Register */
-#define AM335X_WDT_WDSC_OFFSET 0x0010 /* Watchdog System Control Register */
-#define AM335X_WDT_WDST_OFFSET 0x0014 /* Watchdog Status Register */
-#define AM335X_WDT_WISR_OFFSET 0x0018 /* Watchdog Interrupt Status Register */
-#define AM335X_WDT_WIER_OFFSET 0x001C /* Watchdog Interrupt Enable Register */
-#define AM335X_WDT_WCLR_OFFSET 0x0024 /* Watchdog Control Register */
-#define AM335X_WDT_WCRR_OFFSET 0x0028 /* Watchdog Counter Register */
-#define AM335X_WDT_WLDR_OFFSET 0x002C /* Watchdog Load Register */
-#define AM335X_WDT_WTGR_OFFSET 0x0030 /* Watchdog Trigger Register */
-#define AM335X_WDT_WWPS_OFFSET 0x0034 /* Watchdog Write Posting Bits Register */
-#define AM335X_WDT_WDLY_OFFSET 0x0044 /* Watchdog Delay Configuration Register */
-#define AM335X_WDT_WSPR_OFFSET 0x0048 /* Watchdog Start/Stop Register */
-#define AM335X_WDT_WIRQSTATRAW_OFFSET 0x0054 /* Watchdog Raw Interrupt Status Register */
-#define AM335X_WDT_WIRQSTAT_OFFSET 0x0058 /* Watchdog Interrupt Status Register */
-#define AM335X_WDT_WIRQENSET_OFFSET 0x005C /* Watchdog Interrupt Enable Set Register */
-#define AM335X_WDT_WIRQENCLR_OFFSET 0x0060 /* Watchdog Interrupt Enable Clear Register */
+#define AM335X_WDT_IDR_OFFSET 0x0000 /* Watchdog Identification Register */
+#define AM335X_WDT_DSC_OFFSET 0x0010 /* Watchdog System Control Register */
+#define AM335X_WDT_DST_OFFSET 0x0014 /* Watchdog Status Register */
+#define AM335X_WDT_ISR_OFFSET 0x0018 /* Watchdog Interrupt Status Register */
+#define AM335X_WDT_IER_OFFSET 0x001c /* Watchdog Interrupt Enable Register */
+#define AM335X_WDT_CLR_OFFSET 0x0024 /* Watchdog Control Register */
+#define AM335X_WDT_CRR_OFFSET 0x0028 /* Watchdog Counter Register */
+#define AM335X_WDT_LDR_OFFSET 0x002c /* Watchdog Load Register */
+#define AM335X_WDT_TGR_OFFSET 0x0030 /* Watchdog Trigger Register */
+#define AM335X_WDT_WPS_OFFSET 0x0034 /* Watchdog Write Posting Bits Register */
+#define AM335X_WDT_DLY_OFFSET 0x0044 /* Watchdog Delay Configuration Register */
+#define AM335X_WDT_SPR_OFFSET 0x0048 /* Watchdog Start/Stop Register */
+#define AM335X_WDT_IRQ_STAT_RAW_OFFSET 0x0054 /* Watchdog Raw Interrupt Status Register */
+#define AM335X_WDT_IRQ_STAT_OFFSET 0x0058 /* Watchdog Interrupt Status Register */
+#define AM335X_WDT_IRQ_EN_SET_OFFSET 0x005c /* Watchdog Interrupt Enable Set Register */
+#define AM335X_WDT_IRQ_EN_CLR_OFFSET 0x0060 /* Watchdog Interrupt Enable Clear Register */
/* Register addresses ***************************************************************/
-#define AM335X_WDT_WIDR (AM335X_WDT1_VADDR + AM335X_WDT_WIDR_OFFSET)
-#define AM335X_WDT_WDSC (AM335X_WDT1_VADDR + AM335X_WDT_WDSC_OFFSET)
-#define AM335X_WDT_WDST (AM335X_WDT1_VADDR + AM335X_WDT_WDST_OFFSET)
-#define AM335X_WDT_WISR (AM335X_WDT1_VADDR + AM335X_WDT_WISR_OFFSET)
-#define AM335X_WDT_WIER (AM335X_WDT1_VADDR + AM335X_WDT_WIER_OFFSET)
-#define AM335X_WDT_WCLR (AM335X_WDT1_VADDR + AM335X_WDT_WCLR_OFFSET)
-#define AM335X_WDT_WCRR (AM335X_WDT1_VADDR + AM335X_WDT_WCRR_OFFSET)
-#define AM335X_WDT_WLDR (AM335X_WDT1_VADDR + AM335X_WDT_WLDR_OFFSET)
-#define AM335X_WDT_WTGR (AM335X_WDT1_VADDR + AM335X_WDT_WTGR_OFFSET)
-#define AM335X_WDT_WWPS (AM335X_WDT1_VADDR + AM335X_WDT_WWPS_OFFSET)
-#define AM335X_WDT_WDLY (AM335X_WDT1_VADDR + AM335X_WDT_WDLY_OFFSET)
-#define AM335X_WDT_WSPR (AM335X_WDT1_VADDR + AM335X_WDT_WSPR_OFFSET)
-#define AM335X_WDT_WIRQSTATRAW (AM335X_WDT1_VADDR + AM335X_WDT_WIRQSTATRAW_OFFSET)
-#define AM335X_WDT_WIRQSTAT (AM335X_WDT1_VADDR + AM335X_WDT_WIRQSTAT_OFFSET)
-#define AM335X_WDT_WIRQENSET (AM335X_WDT1_VADDR + AM335X_WDT_WIRQENSET_OFFSET)
-#define AM335X_WDT_WIRQENCLR (AM335X_WDT1_VADDR + AM335X_WDT_WIRQENCLR_OFFSET)
+#define AM335X_WDT_IDR (AM335X_WDT1_VADDR + AM335X_WDT_IDR_OFFSET)
+#define AM335X_WDT_DSC (AM335X_WDT1_VADDR + AM335X_WDT_DSC_OFFSET)
+#define AM335X_WDT_DST (AM335X_WDT1_VADDR + AM335X_WDT_DST_OFFSET)
+#define AM335X_WDT_ISR (AM335X_WDT1_VADDR + AM335X_WDT_ISR_OFFSET)
+#define AM335X_WDT_IER (AM335X_WDT1_VADDR + AM335X_WDT_IER_OFFSET)
+#define AM335X_WDT_CLR (AM335X_WDT1_VADDR + AM335X_WDT_CLR_OFFSET)
+#define AM335X_WDT_CRR (AM335X_WDT1_VADDR + AM335X_WDT_CRR_OFFSET)
+#define AM335X_WDT_LDR (AM335X_WDT1_VADDR + AM335X_WDT_LDR_OFFSET)
+#define AM335X_WDT_TGR (AM335X_WDT1_VADDR + AM335X_WDT_TGR_OFFSET)
+#define AM335X_WDT_WPS (AM335X_WDT1_VADDR + AM335X_WDT_WPS_OFFSET)
+#define AM335X_WDT_DLY (AM335X_WDT1_VADDR + AM335X_WDT_DLY_OFFSET)
+#define AM335X_WDT_SPR (AM335X_WDT1_VADDR + AM335X_WDT_SPR_OFFSET)
+#define AM335X_WDT_IRQ_STAT_RAW (AM335X_WDT1_VADDR + AM335X_WDT_IRQ_STAT_RAW_OFFSET)
+#define AM335X_WDT_IRQ_STAT (AM335X_WDT1_VADDR + AM335X_WDT_IRQ_STAT_OFFSET)
+#define AM335X_WDT_IRQ_EN_SET (AM335X_WDT1_VADDR + AM335X_WDT_IRQ_EN_SET_OFFSET)
+#define AM335X_WDT_IRQ_EN_CLR (AM335X_WDT1_VADDR + AM335X_WDT_IRQ_EN_CLR_OFFSET)
/* Register bit definitions *********************************************************/
/* Watchdog System Control Register */
-#define WDT_WDSC_SOFTRESET (1 << 1) /* Bit 1: Watchdog Software Reset */
-#define WDT_WDSC_IDLEMODE_SHIFT (3) /* Bit 3-4: Watchdog Idle Mode */
-# define WDT_WDSC_IDLEMODE_FORCE (0 << WDT_WDSC_IDLEMODE_SHIFT) /* Force-idle Mode */
-# define WDT_WDSC_IDLEMODE_NO (1 << WDT_WDSC_IDLEMODE_SHIFT) /* No-idle Mode */
-# define WDT_WDSC_IDLEMODE_SMART (2 << WDT_WDSC_IDLEMODE_SHIFT) /* Smart-idle Mode */
-# define WDT_WDSC_IDLEMODE_SMART_WKUP (3 << WDT_WDSC_IDLEMODE_SHIFT) /* Smart-idle Wakeup-capable Mode */
-#define WDT_WDSC_EMUFREE (1 << 5) /* Bit 5: Watchdog DEBUG Disable */
+#define WDT_DSC_SOFT_RST (1 << 1) /* Bit 1: Watchdog Software Reset */
+#define WDT_DSC_IDLE_SHIFT (3) /* Bit 3-4: Watchdog Idle Mode */
+# define WDT_DSC_IDLE_FORCE (0 << WDT_DSC_IDLE_SHIFT) /* Force-idle Mode */
+# define WDT_DSC_IDLE_NO (1 << WDT_DSC_IDLE_SHIFT) /* No-idle Mode */
+# define WDT_DSC_IDLE_SMART (2 << WDT_DSC_IDLE_SHIFT) /* Smart-idle Mode */
+# define WDT_DSC_IDLE_SMART_WKUP (3 << WDT_DSC_IDLE_SHIFT) /* Smart-idle Wakeup-capable Mode */
+#define WDT_DSC_EMU_FREE (1 << 5) /* Bit 5: Watchdog DEBUG Disable */
/* Watchdog Status Register */
-#define WDT_WDST_RESETDONE (1 << 0) /* Bit 0: Watchdog Reset Completed */
+#define WDT_DST_RST_DONE (1 << 0) /* Bit 0: Watchdog Reset Completed */
/* Watchdog Interrupt Registers */
@@ -108,26 +108,26 @@
/* Watchdog Control Register */
-#define WDT_WCLR_PTV_SHIFT (2) /* Bits 2-4: Prescaler Value */
-#define WDT_WCLR_PTV_MASK (7 << WDT_WCLR_PTV_SHIFT)
-# define WDT_WCLR_PTV(n) ((uint32_t)(n) << WDT_WCLR_PTV_SHIFT)
-#define WDT_WCLR_PRE_ENABLE (1 << 5) /* Bit 5: Prescaler Enabled */
+#define WDT_CLR_PTV_SHIFT (2) /* Bits 2-4: Prescaler Value */
+#define WDT_CLR_PTV_MASK (7 << WDT_CLR_PTV_SHIFT)
+# define WDT_CLR_PTV(n) ((uint32_t)(n) << WDT_CLR_PTV_SHIFT)
+#define WDT_CLR_PRE_ENABLE (1 << 5) /* Bit 5: Prescaler Enabled */
/* Watchdog Write Posting Bits Register */
-#define WDT_WWPS_W_PEND_WCLR (1 << 0) /* Bit 0: Write Pending for Register WCLR */
-#define WDT_WWPS_W_PEND_WCRR (1 << 1) /* Bit 1: Write pending for register WCRR */
-#define WDT_WWPS_W_PEND_WLDR (1 << 2) /* Bit 2: Write pending for register WLDR */
-#define WDT_WWPS_W_PEND_WTGR (1 << 3) /* Bit 3: Write pending for register WTGR */
-#define WDT_WWPS_W_PEND_WSPR (1 << 4) /* Bit 4: Write pending for register WSPR */
-#define WDT_WWPS_W_PEND_WDLY (1 << 5) /* Bit 5: Write pending for register WDLY */
+#define WDT_WPS_W_PEND_WCLR (1 << 0) /* Bit 0: Write Pending for Register WCLR */
+#define WDT_WPS_W_PEND_WCRR (1 << 1) /* Bit 1: Write pending for register WCRR */
+#define WDT_WPS_W_PEND_WLDR (1 << 2) /* Bit 2: Write pending for register WLDR */
+#define WDT_WPS_W_PEND_WTGR (1 << 3) /* Bit 3: Write pending for register WTGR */
+#define WDT_WPS_W_PEND_WSPR (1 << 4) /* Bit 4: Write pending for register WSPR */
+#define WDT_WPS_W_PEND_WDLY (1 << 5) /* Bit 5: Write pending for register WDLY */
/* Watchdog Start/Stop Register */
-#define WDT_WSPR_START_FEED_A (0x0000bbbb)
-#define WDT_WSPR_START_FEED_B (0x00004444)
-#define WDT_WSPR_STOP_FEED_A (0x0000aaaa)
-#define WDT_WSPR_STOP_FEED_B (0x00005555)
+#define WDT_SPR_START_FEED_A (0x0000bbbb)
+#define WDT_SPR_START_FEED_B (0x00004444)
+#define WDT_SPR_STOP_FEED_A (0x0000aaaa)
+#define WDT_SPR_STOP_FEED_B (0x00005555)
#endif /* __ARCH_ARM_SRC_AM335X_HARDWARE_AM335X_WDOG_H */
diff --git a/arch/arm/src/armv7-a/arm_pgalloc.c b/arch/arm/src/armv7-a/arm_pgalloc.c
index 0377eb12cf4..f9a82400275 100644
--- a/arch/arm/src/armv7-a/arm_pgalloc.c
+++ b/arch/arm/src/armv7-a/arm_pgalloc.c
@@ -53,7 +53,6 @@
#ifdef CONFIG_BUILD_KERNEL
-
/****************************************************************************
* Private Functions
****************************************************************************/
diff --git a/arch/arm/src/cxd56xx/Kconfig b/arch/arm/src/cxd56xx/Kconfig
index 30740742731..14ca69e6d9f 100644
--- a/arch/arm/src/cxd56xx/Kconfig
+++ b/arch/arm/src/cxd56xx/Kconfig
@@ -3,7 +3,7 @@
# see the file kconfig-language.txt in the NuttX tools repository.
#
-comment "CXD56xx Configuration Options"
+comment "CXD56xx Options"
config CXD56_ARCH_OPTS
bool
@@ -25,7 +25,6 @@ config CXD56_WLCSP
bool "WLCSP 100 pin package"
endchoice
-endmenu
comment "Basic Options"
@@ -44,7 +43,180 @@ config CXD56_ICC
bool
default y
-menu "CXD56xx Peripheral Support"
+config CXD56_FARAPI
+ bool
+ default y
+ select CXD56_CPUFIFO
+
+menu "Far API Configuration"
+ depends on CXD56_FARAPI
+
+config CXD56_FARAPI_VERSION_CHECK
+ bool "Far API Version Compatibility Check"
+ default y
+ ---help---
+ Enable the Far API version compatibility check. If the version
+ mismatch is deteced during system bootup, the target system shows
+ the message to update the loader and gnssfw firmwares.
+
+if CXD56_FARAPI_VERSION_CHECK
+
+config CXD56_FARAPI_VERSION_FAILED_PANIC
+ bool "Far API Version Check Failed to PANIC"
+ default n
+ ---help---
+ If the version mismatch is detected, do PANIC() to stop the system.
+endif
+
+config CXD56_FARAPI_DEBUG
+ bool "Debug Far API"
+
+endmenu # Far API Configuration
+
+comment "Timer Options"
+
+menu "Timer Options"
+
+menuconfig CXD56_RTC
+ bool "Real Time Clock (RTC)"
+ default y
+ ---help---
+ Support RTC
+
+if CXD56_RTC
+
+config CXD56_RTC_LATEINIT
+ bool "Late RTC initialization"
+ default y
+ ---help---
+ Enable the late RTC initialization after waiting until the external
+ CXD5247 RTC clock is stable. It will take 2 seconds typically at the
+ initial boot by power on reset.
+
+endif # CXD56_RTC
+
+menuconfig CXD56_TIMER
+ bool "Timer"
+ default y
+ select TIMER
+
+if CXD56_TIMER
+
+choice
+ prompt "Timer divider selection"
+ default CXD56_TIMER_DIVIDER_1
+ ---help---
+ Timer divider selects 1, 16 or 256. The smaller the divider, the higher
+ time resolution, but the shorter the maximum time until wrap-around.
+
+config CXD56_TIMER_DIVIDER_1
+ bool "Divider 1"
+
+config CXD56_TIMER_DIVIDER_16
+ bool "Divider 16"
+
+config CXD56_TIMER_DIVIDER_256
+ bool "Divider 256"
+
+endchoice
+endif # CXD56_TIMER
+
+menuconfig CXD56_WDT
+ bool "Watchdog Timer (WDT)"
+ default y
+ select WATCHDOG
+
+if CXD56_WDT
+
+config CXD56_WDT_INTERRUPT
+ bool "Interrupt on timeout"
+ default y
+ ---help---
+ This watchdog timer run 2 laps as long as the counter is not reloaded.
+ In the first lap, the watchdog interrupt occurs. Without interrupt
+ clear, The reset signal is asserted in the second timeout. This setting
+ enables the first interrupt.
+
+config CXD56_WDT_REGDEBUG
+ bool "Register level debug"
+ default n
+ ---help---
+ Enable low-level register debug output
+
+endif # CXD56_WDT
+
+endmenu
+
+comment "Power Management Options"
+
+menuconfig CXD56_PM
+ bool "Power Management"
+ default y
+ select POWER
+
+if CXD56_PM
+
+config CXD56_PM_PROCFS
+ bool "Power Management PROCFS support"
+ default n
+ ---help---
+ Enable the power domain status or the clock frequency monitor.
+
+config CXD56_GAUGE
+ bool "CXD5247 battery gauge"
+ default n
+ select BATTERY_GAUGE
+ ---help---
+ Enable battery gauge driver.
+ This is not a lower half of power driver, but compatible with NuttX gauge driver.
+
+if CXD56_GAUGE
+
+config CXD56_GAUGE_DEBUG
+ bool "Battery Gauge Debug"
+ default n
+ ---help---
+ Enable battery driver debug messages and debug IO command.
+
+endif
+
+config CXD56_CHARGER
+ bool "CXD5247 battery charger"
+ default n
+ select BATTERY_CHARGER
+ ---help---
+ Enable battery charger driver.
+ This is not a lower half of power driver, but compatible with NuttX charger driver.
+
+if CXD56_CHARGER
+
+config CXD56_CHARGER_TEMP_PRECISE
+ bool "Precise Temperature"
+ default y
+ ---help---
+ Get temperature precisely. If this option is enabled, driver calculate precisely
+ from register value to degrees Celsius.
+ This option requires libm.
+
+config CXD56_CHARGER_DEBUG
+ bool "Battery Charger Debug"
+ default n
+ ---help---
+ Enable battery charger driver debug messages.
+
+endif
+endif # CXD56_PM
+
+comment "Peripheral Support"
+
+menu "Peripheral Support"
+
+config CXD56_DMAC
+ bool "DMAC"
+ default y
+ ---help---
+ Enables DMAC
+ Currently supports SPI4 TX/RX and SPI5 TX/RX
config CXD56_GPIO_IRQ
bool "GPIO interrupt"
@@ -68,18 +240,886 @@ config CXD56_UART2
---help---
UART interface with hardware flow control in the application subsystem.
+config CXD56_SPI
+ bool "SPI"
+
+if CXD56_SPI
+
+config CXD56_SPI0
+ bool "SPI0"
+
+menuconfig CXD56_SPI3
+ bool "SPI3"
+
+if CXD56_SPI3
+
+config CXD56_SPI3_SCUSEQ
+ bool "SCU Sequencer"
+ default y
+ depends on CXD56_SCU
+ ---help---
+ Use the sensor control unit (SCU) sequencer.
+
+config CXD56_SPI3_CS0
+ bool "SPI3 Chip Select 0"
+ default y
+ ---help---
+ Enable chip select 0 of SPI3
+
+config CXD56_SPI3_CS1
+ bool "SPI3 Chip Select 1"
+ default n
+ ---help---
+ Enable chip select 1 of SPI3
+
+config CXD56_SPI3_CS2
+ bool "SPI3 Chip Select 2"
+ default n
+ ---help---
+ Enable chip select 2 of SPI3
+
+endif # CXD56_SPI3
+
+menuconfig CXD56_SPI4
+ bool "SPI4"
+
+if CXD56_SPI4
+
+config CXD56_DMAC_SPI4_TX
+ bool "DMAC support for SPI4 TX"
+ default n
+ select CXD56_DMAC
+ ---help---
+ Enables DMAC for SPI4 TX
+
+if CXD56_DMAC_SPI4_TX
+
+config CXD56_DMAC_SPI4_TX_CH
+ int "TX channel"
+ default 2
+ range 2 6
+
+config CXD56_DMAC_SPI4_TX_MAXSIZE
+ int "Max size to be sent in bytes"
+ default 192000
+ range 1 1572864
+ ---help---
+ This value should be same as RX.
+
+endif # CXD56_DMAC_SPI4_TX
+
+config CXD56_DMAC_SPI4_RX
+ bool "DMAC support for SPI4 RX"
+ default n
+ select CXD56_DMAC
+
+ ---help---
+ Enables DMAC for SPI4 RX
+
+if CXD56_DMAC_SPI4_RX
+
+config CXD56_DMAC_SPI4_RX_CH
+ int "RX channel"
+ default 3
+ range 2 6
+
+config CXD56_DMAC_SPI4_RX_MAXSIZE
+ int "Max size to be received in bytes"
+ default 192000
+ range 1 1572864
+ ---help---
+ This value should be same as TX.
+
+endif # CXD56_DMAC_SPI4_RX
+
+endif # CXD56_SPI4
+
+menuconfig CXD56_SPI5
+ bool "SPI5"
+
+if CXD56_SPI5
+
+choice
+ prompt "SPI5 pin configuration"
+ default CXD56_SPI5_PINMAP_EMMC
+
+config CXD56_SPI5_PINMAP_EMMC
+ bool "SPI5 pin assign to eMMC"
+ ---help---
+ SPI5 assigns to the shared pins with eMMC.
+
+config CXD56_SPI5_PINMAP_SDIO
+ bool "SPI5 pin assign to SDIO"
+ ---help---
+ SPI5 assigns to the shared pins with SDIO.
+endchoice
+
+config CXD56_DMAC_SPI5_TX
+ bool "DMAC support for SPI5 TX"
+ default n
+ select CXD56_DMAC
+ ---help---
+ Enables DMAC for SPI5 TX
+
+if CXD56_DMAC_SPI5_TX
+
+config CXD56_DMAC_SPI5_TX_CH
+ int "TX channel"
+ default 4
+ range 2 6
+
+config CXD56_DMAC_SPI5_TX_MAXSIZE
+ int "Max size to be sent in bytes"
+ default 1516
+ range 1 1572864
+ ---help---
+ This value should be same as RX.
+
+endif # CXD56_DMAC_SPI5_TX
+
+config CXD56_DMAC_SPI5_RX
+ bool "DMAC support for SPI5 RX"
+ default n
+ select CXD56_DMAC
+
+ ---help---
+ Enables DMAC for SPI5 RX
+
+if CXD56_DMAC_SPI5_RX
+
+config CXD56_DMAC_SPI5_RX_CH
+ int "RX channel"
+ default 5
+ range 2 6
+
+config CXD56_DMAC_SPI5_RX_MAXSIZE
+ int "Max size to be received in bytes"
+ default 1516
+ range 1 1572864
+ ---help---
+ This value should be same as TX.
+
+endif # CXD56_DMAC_SPI5_RX
+
+endif # CXD56_SPI5
+endif
+
+config CXD56_I2C
+ bool "I2C"
+
+if CXD56_I2C
+
+menuconfig CXD56_I2C0
+ bool "I2C0"
+
+if CXD56_I2C0
+
+config CXD56_I2C0_SCUSEQ
+ bool "SCU Sequencer"
+ default y
+ depends on CXD56_SCU
+ ---help---
+ Use the sensor control unit (SCU) sequencer.
+
+endif # CXD56_I2C0
+
+menuconfig CXD56_I2C1
+ bool "I2C1"
+
+if CXD56_I2C1
+
+config CXD56_I2C1_SCUSEQ
+ bool "SCU Sequencer"
+ default y
+ depends on CXD56_SCU
+ ---help---
+ Use the sensor control unit (SCU) sequencer.
+
+endif # CXD56_I2C1
+
+config CXD56_I2C2
+ bool "I2C2"
+
+config CXD56_I2C_DRIVER
+ bool "I2C character driver"
+ default n
+ select I2C_DRIVER
+ ---help---
+ Build in support for a character driver at /dev/i2c[N] that may be
+ used to perform I2C bus transfers from applications. The intent of
+ this driver is to support I2C testing. It is not suitable for use
+ in any real driver application.
+endif
+
config CXD56_USBDEV
bool "USB"
default n
---help---
Enables USB
+config CXD56_PWM
+ bool "PWM"
+
+if CXD56_PWM
+
+config CXD56_PWM0
+ bool "PWM0"
+ default n
+ ---help---
+ Enable PWM channel 0
+
+config CXD56_PWM1
+ bool "PWM1"
+ default n
+ ---help---
+ Enable PWM channel 1
+
+config CXD56_PWM2
+ bool "PWM2"
+ default n
+ ---help---
+ Enable PWM channel 2
+
+config CXD56_PWM3
+ bool "PWM3"
+ default n
+ ---help---
+ Enable PWM channel 3
+
+endif # CXD56_PWM
+
+config CXD56_ADC
+ bool "ADC"
+ default n
+ depends on CXD56_SCU
+ ---help---
+ Support ADC interface
+
+if CXD56_ADC
+
+menuconfig CXD56_HPADC0
+ bool "HPADC0"
+ default n
+
+if CXD56_HPADC0
+
+config CXD56_HPADC0_FREQ
+ int "Coefficient of sampling frequency"
+ default 11 if CXD56_SCU_32K
+ default 7 if CXD56_SCU_RCOSC
+ default 7 if CXD56_SCU_XOSC
+ range 9 11 if CXD56_SCU_32K
+ range 0 7 if CXD56_SCU_RCOSC
+ range 0 7 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = adc clock / 2 ^ n [Hz]
+ adc clock = SCU32K : if SCU clock is SCU32K.
+ adc clock = RCOSC / 4 : if SCU clock is RCOSC.
+ adc clock = XOSC / 3 / 4 : if SCU clock is XOSC 26MHz.
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 9 to 11
+ RCOSC : 0 to 7 (0 ~ 6 : over-sampling mode)
+ XOSC : 0 to 7 (0 ~ 6 : over-sampling mode)
+
+config CXD56_HPADC0_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_HPADC0_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_HPADC0_FSIZE
+ int "SCU FIFO size"
+ default 64
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endif # CXD56_HPADC0
+
+menuconfig CXD56_HPADC1
+ bool "HPADC1"
+ default n
+
+if CXD56_HPADC1
+
+config CXD56_HPADC1_FREQ
+ int "Coefficient of sampling frequency"
+ default 11 if CXD56_SCU_32K
+ default 7 if CXD56_SCU_RCOSC
+ default 7 if CXD56_SCU_XOSC
+ range 9 11 if CXD56_SCU_32K
+ range 0 7 if CXD56_SCU_RCOSC
+ range 0 7 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = adc clock / 2 ^ n [Hz]
+ adc clock = SCU32K : if SCU clock is SCU32K.
+ adc clock = RCOSC / 4 : if SCU clock is RCOSC.
+ adc clock = XOSC / 3 / 4 : if SCU clock is XOSC 26MHz.
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 9 to 11
+ RCOSC : 0 to 7 (0 ~ 6 : over-sampling mode)
+ XOSC : 0 to 7 (0 ~ 6 : over-sampling mode)
+
+config CXD56_HPADC1_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_HPADC1_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_HPADC1_FSIZE
+ int "SCU FIFO size"
+ default 64
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endif # CXD56_HPADC1
+
+config CXD56_LPADC
+ bool "LPADC"
+ default n
+
+if CXD56_LPADC
+
+choice
+ prompt "Select LPADC channel"
+ default CXD56_LPADC0
+
+config CXD56_LPADC0
+ bool "LPADC channel 0"
+ ---help---
+ Enable LPADC channel 0.
+ Other LPADC channel can not be used.
+
+config CXD56_LPADC1
+ bool "LPADC channel 1"
+ ---help---
+ Enable LPADC channel 1.
+ Other LPADC channel can not be used.
+
+config CXD56_LPADC2
+ bool "LPADC channel 2"
+ ---help---
+ Enable LPADC channel 2.
+ Other LPADC channel can not be used.
+
+config CXD56_LPADC3
+ bool "LPADC channel 3"
+ ---help---
+ Enable LPADC channel 3.
+ Other LPADC channel can not be used.
+
+config CXD56_LPADC0_1
+ bool "LPADC channel 0 and channel 1"
+ ---help---
+ Enable LPADC channel 0 and LPADC channel 1.
+ Switch the LPADC channel 0 sampling and LPADC channel 1 sampling in time division.
+
+config CXD56_LPADC_ALL
+ bool "LPADC all channels"
+ ---help---
+ Enable LPADC all channels.
+ Switch the LPADC all channels sampling in time division.
+endchoice
+
+menu "LADC0"
+ depends on CXD56_LPADC0
+
+config CXD56_LPADC0_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 11 15 if CXD56_SCU_32K
+ range 3 15 if CXD56_SCU_RCOSC
+ range 2 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ n [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 11 to 15
+ RCOSC : 3 to 15
+ XOSC : 2 to 15
+
+config CXD56_LPADC0_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC0_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC0_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC0
+
+menu "LADC1"
+ depends on CXD56_LPADC1
+
+config CXD56_LPADC1_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 11 15 if CXD56_SCU_32K
+ range 3 15 if CXD56_SCU_RCOSC
+ range 2 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ n [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 11 to 15
+ RCOSC : 3 to 15
+ XOSC : 2 to 15
+
+config CXD56_LPADC1_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC1_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC1_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC1
+
+menu "LADC2"
+ depends on CXD56_LPADC2
+
+config CXD56_LPADC2_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 11 15 if CXD56_SCU_32K
+ range 3 15 if CXD56_SCU_RCOSC
+ range 2 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ n [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 11 to 15
+ RCOSC : 3 to 15
+ XOSC : 2 to 15
+
+config CXD56_LPADC2_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC2_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC2_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC2
+
+menu "LADC3"
+ depends on CXD56_LPADC3
+
+config CXD56_LPADC3_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 11 15 if CXD56_SCU_32K
+ range 3 15 if CXD56_SCU_RCOSC
+ range 2 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ n [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 11 to 15
+ RCOSC : 3 to 15
+ XOSC : 2 to 15
+
+config CXD56_LPADC3_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC3_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC3_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC3
+
+menu "LADC0"
+ depends on CXD56_LPADC0_1
+
+config CXD56_LPADC0_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 12 15 if CXD56_SCU_32K
+ range 6 15 if CXD56_SCU_RCOSC
+ range 6 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ (n+1) [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 12 to 15
+ RCOSC : 6 to 15
+ XOSC : 6 to 15
+
+config CXD56_LPADC0_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC0_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC0_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC0_1
+
+menu "LADC1"
+ depends on CXD56_LPADC0_1
+
+config CXD56_LPADC1_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 12 15 if CXD56_SCU_32K
+ range 6 15 if CXD56_SCU_RCOSC
+ range 6 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ (n+1) [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 12 to 15
+ RCOSC : 6 to 15
+ XOSC : 6 to 15
+
+config CXD56_LPADC1_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC1_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC1_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC0_1
+
+menu "LADC0"
+ depends on CXD56_LPADC_ALL
+
+config CXD56_LPADC0_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 11 15 if CXD56_SCU_32K
+ range 7 15 if CXD56_SCU_RCOSC
+ range 7 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ (n+2) [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 11 to 15
+ RCOSC : 7 to 15
+ XOSC : 7 to 15
+
+config CXD56_LPADC0_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC0_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC0_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC_ALL
+
+menu "LADC1"
+ depends on CXD56_LPADC_ALL
+
+config CXD56_LPADC1_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 11 15 if CXD56_SCU_32K
+ range 7 15 if CXD56_SCU_RCOSC
+ range 7 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ (n+2) [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 11 to 15
+ RCOSC : 7 to 15
+ XOSC : 7 to 15
+
+config CXD56_LPADC1_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC1_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC1_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC_ALL
+
+menu "LADC2"
+ depends on CXD56_LPADC_ALL
+
+config CXD56_LPADC2_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 11 15 if CXD56_SCU_32K
+ range 7 15 if CXD56_SCU_RCOSC
+ range 7 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ (n+2) [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 11 to 15
+ RCOSC : 7 to 15
+ XOSC : 7 to 15
+
+config CXD56_LPADC2_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC2_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC2_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC_ALL
+
+menu "LADC3"
+ depends on CXD56_LPADC_ALL
+
+config CXD56_LPADC3_FREQ
+ int "Coefficient of sampling frequency"
+ default 12
+ range 11 15 if CXD56_SCU_32K
+ range 7 15 if CXD56_SCU_RCOSC
+ range 7 15 if CXD56_SCU_XOSC
+ ---help---
+ This configuration set to sampling frequency calculated by the following formula.
+ Sampling frequency = SCU32K / 2 ^ (n+2) [Hz]
+ Note. Setable range depends on the SCU clock mode.
+ SCU32K : 11 to 15
+ RCOSC : 7 to 15
+ XOSC : 7 to 15
+
+config CXD56_LPADC3_OFFSET
+ int "Offset"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC3_GAIN
+ int "Gain"
+ default 0
+ range 0 65535
+
+config CXD56_LPADC3_FSIZE
+ int "SCU FIFO size"
+ default 16
+ range 2 40960
+ ---help---
+ SCU FIFO size
+
+endmenu # CXD56_LPADC_ALL
+
+endif # CXD56_LPADC
+
+endif # CXD56_ADC
+
+menuconfig CXD56_SCU
+ bool "Sensor Control Unit (SCU)"
+ default y
+
+if CXD56_SCU
+
+config CXD56_SCU_PREDIV
+ int "Sequencer Sampling Predivider"
+ default 64
+ range 1 256
+ ---help---
+ This configuration ralated to maximum sampling rate based
+ on 32.768KHz.
+ e.g. 32768 / 64 = 512 (samples)
+
+choice
+ prompt "SCU clock mode"
+ default CXD56_SCU_RCOSC
+
+config CXD56_SCU_32K
+ bool "Same with SCU32K"
+
+config CXD56_SCU_RCOSC
+ bool "RCOSC"
+
+config CXD56_SCU_XOSC
+ bool "XOSC"
+endchoice
+
+if CXD56_SCU_XOSC
+config CXD56_SCU_XOSC_DIV
+ int "SCU XOSC predivider"
+ default 2
+ range 1 4
+endif
+
+choice
+ prompt "SCU32K clock source"
+ default CXD56_SCU32K_RTC
+
+config CXD56_SCU32K_RCRTC
+ bool "RCRTC"
+
+config CXD56_SCU32K_RTC
+ bool "RTC"
+endchoice
+
+config CXD56_SCU_DEBUG
+ bool "SCU Debug"
+ default n
+
+config CXD56_SCU_DEBUG_ERR
+ bool "Error Messages"
+ default n
+ depends on CXD56_SCU_DEBUG
+
+config CXD56_SCU_DEBUG_WARN
+ bool "Warning Messages"
+ default n
+ depends on CXD56_SCU_DEBUG_ERR
+
+config CXD56_SCU_DEBUG_INFO
+ bool "Info Messages"
+ default n
+ depends on CXD56_SCU_DEBUG_WARN
+
+config CXD56_UDMAC
+ bool "DMAC support"
+ default y
+ select ARCH_DMA
+ ---help---
+ Use DMAC for reading sensing data from SCU FIFO.
+endif # CXD56_SCU
+
+config CXD56_CISIF
+ bool "CMOS image sensor interface"
+ default n
+ ---help---
+ CMOS image sensor interface for cx5602 chip
+endmenu
+
+comment "Storage Options"
+
+menu "Storage Options"
+
+menuconfig CXD56_SFC
+ bool "SPI Flash"
+ default n if CXD56_SUBCORE
+ default y
+ select MTD
+
+if CXD56_SFC
+
+config CXD56_SFC_PAGE_SHIFT_SIZE
+ int "SPI Flash page shift size"
+ default 12
+ range 8 12
+ ---help---
+ Specify page shift size to determine block size of SPI flash access.
+ Relationship between page shift size and block size is as follows.
+ page shift size : block size
+ 8 : 256
+ 9 : 512
+ 10 : 1024
+ 11 : 2048
+ 12 : 4096
+ When file system is SMART file system, please set the value to SMART
+ Device sector size or less.
+ Following equation is satisfied.
+ MTD_SMART_SECTOR_SIZE >= (1 << CXD56_SFC_PAGE_SHIFT_SIZE)
+
+config CXD56_SFC_VERIFY_WRITE
+ bool "Enable write with verify"
+ default n
+ ---help---
+ Enalbe SPI flash write function with verify.
+
+endif # CXD56_SFC
+
menuconfig CXD56_SDIO
bool "SDIO SD Card"
default n
select ARCH_HAVE_SDIO
select SDIO_BLOCKSETUP
- select SCHED_WORKQUEUE
select SCHED_HPWORK
if CXD56_SDIO
@@ -115,4 +1155,32 @@ config CXD56_SDIO_ENABLE_MULTIFUNCTION
endif # SDIO Configuration
+menuconfig CXD56_SPISD
+ bool "SPI SD Card"
+ default n
+ select MMCSD_SPI
+
+if CXD56_SPISD
+
+config CXD56_SPISD_SLOT_NO
+ int "SPI SD Card Slot Number"
+ default 0
+ ---help---
+ Select spi sd card slot number.
+
+endif # SPISD Configuration
+
+config CXD56_EMMC
+ bool "eMMC"
+ default n if CXD56_SUBCORE
+ ---help---
+ Emmc driver for cxd56xx chip
+
+endmenu
+
+config CXD56_GE2D
+ bool "Graphics Engine"
+ default n
+ ---help---
+ A hardware image processor device.
endmenu
diff --git a/arch/arm/src/cxd56xx/Make.defs b/arch/arm/src/cxd56xx/Make.defs
index cbc488ef2bc..9a2c000a580 100644
--- a/arch/arm/src/cxd56xx/Make.defs
+++ b/arch/arm/src/cxd56xx/Make.defs
@@ -83,16 +83,34 @@ CMN_CSRCS += up_copyarmstate.c
endif
endif
+CHIP_ASRCS += cxd56_farapistub.S
+
CHIP_CSRCS = cxd56_allocateheap.c cxd56_idle.c
+CHIP_CSRCS += cxd56_uid.c
CHIP_CSRCS += cxd56_serial.c cxd56_uart.c cxd56_irq.c
CHIP_CSRCS += cxd56_start.c
CHIP_CSRCS += cxd56_timerisr.c
CHIP_CSRCS += cxd56_pinconfig.c
CHIP_CSRCS += cxd56_clock.c
+CHIP_CSRCS += cxd56_delay.c
CHIP_CSRCS += cxd56_gpio.c
CHIP_CSRCS += cxd56_pmic.c
CHIP_CSRCS += cxd56_cpufifo.c
CHIP_CSRCS += cxd56_icc.c
+CHIP_CSRCS += cxd56_powermgr.c
+CHIP_CSRCS += cxd56_farapi.c
+CHIP_CSRCS += cxd56_sysctl.c
+
+ifeq ($(CONFIG_CXD56_PM_PROCFS),y)
+CHIP_CSRCS += cxd56_powermgr_procfs.c
+endif
+
+ifeq ($(CONFIG_CXD56_RTC),y)
+CHIP_CSRCS += cxd56_rtc.c
+ifeq ($(CONFIG_RTC_DRIVER),y)
+CHIP_CSRCS += cxd56_rtc_lowerhalf.c
+endif
+endif
ifeq ($(CONFIG_CXD56_GPIO_IRQ),y)
CHIP_CSRCS += cxd56_gpioint.c
@@ -101,3 +119,65 @@ endif
ifeq ($(CONFIG_USBDEV),y)
CHIP_CSRCS += cxd56_usbdev.c
endif
+
+ifeq ($(CONFIG_CXD56_SDIO),y)
+CHIP_CSRCS += cxd56_sdhci.c
+endif
+
+ifeq ($(CONFIG_CXD56_SFC),y)
+CHIP_CSRCS += cxd56_sfc.c
+endif
+
+ifeq ($(CONFIG_CXD56_EMMC),y)
+CHIP_CSRCS += cxd56_emmc.c
+endif
+
+ifeq ($(CONFIG_CXD56_SPI),y)
+CHIP_CSRCS += cxd56_spi.c
+endif
+
+ifeq ($(CONFIG_CXD56_I2C),y)
+CHIP_CSRCS += cxd56_i2c.c
+endif
+
+ifeq ($(CONFIG_CXD56_DMAC),y)
+CHIP_CSRCS += cxd56_dmac.c
+endif
+
+ifeq ($(CONFIG_CXD56_PWM),y)
+CHIP_CSRCS += cxd56_pwm.c
+endif
+
+ifeq ($(CONFIG_CXD56_GAUGE),y)
+CHIP_CSRCS += cxd56_gauge.c
+endif
+
+ifeq ($(CONFIG_CXD56_CHARGER),y)
+CHIP_CSRCS += cxd56_charger.c
+endif
+
+ifeq ($(CONFIG_CXD56_GE2D),y)
+CHIP_CSRCS += cxd56_ge2d.c
+endif
+
+ifeq ($(CONFIG_CXD56_CISIF),y)
+CHIP_CSRCS += cxd56_cisif.c
+endif
+
+ifeq ($(CONFIG_CXD56_SCU),y)
+CHIP_CSRCS += cxd56_scu.c cxd56_scufifo.c
+ifeq ($(CONFIG_CXD56_ADC),y)
+CHIP_CSRCS += cxd56_adc.c
+endif
+ifeq ($(CONFIG_CXD56_UDMAC),y)
+CHIP_CSRCS += cxd56_udmac.c
+endif
+endif
+
+ifeq ($(CONFIG_CXD56_TIMER),y)
+CHIP_CSRCS += cxd56_timer.c
+endif
+
+ifeq ($(CONFIG_CXD56_WDT),y)
+CHIP_CSRCS += cxd56_wdt.c
+endif
diff --git a/arch/arm/src/cxd56xx/cxd56_adc.c b/arch/arm/src/cxd56xx/cxd56_adc.c
new file mode 100644
index 00000000000..85cff79df79
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_adc.c
@@ -0,0 +1,1065 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_adc.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "chip.h"
+#include "up_arch.h"
+#include "hardware/cxd56_adc.h"
+#include "hardware/cxd56_scuseq.h"
+#include "cxd56_clock.h"
+#include "cxd56_adc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_CXD56_HPADC0_FSIZE
+#define CONFIG_CXD56_HPADC0_FSIZE 64
+#endif
+#ifndef CONFIG_CXD56_HPADC1_FSIZE
+#define CONFIG_CXD56_HPADC1_FSIZE 64
+#endif
+#ifndef CONFIG_CXD56_LPADC0_FSIZE
+#define CONFIG_CXD56_LPADC0_FSIZE 16
+#endif
+#ifndef CONFIG_CXD56_LPADC1_FSIZE
+#define CONFIG_CXD56_LPADC1_FSIZE 16
+#endif
+#ifndef CONFIG_CXD56_LPADC2_FSIZE
+#define CONFIG_CXD56_LPADC2_FSIZE 16
+#endif
+#ifndef CONFIG_CXD56_LPADC3_FSIZE
+#define CONFIG_CXD56_LPADC3_FSIZE 16
+#endif
+
+#ifndef CONFIG_CXD56_HPADC0_OFFSET
+#define CONFIG_CXD56_HPADC0_OFFSET 0
+#endif
+#ifndef CONFIG_CXD56_HPADC1_OFFSET
+#define CONFIG_CXD56_HPADC1_OFFSET 0
+#endif
+#ifndef CONFIG_CXD56_LPADC0_OFFSET
+#define CONFIG_CXD56_LPADC0_OFFSET 0
+#endif
+#ifndef CONFIG_CXD56_LPADC1_OFFSET
+#define CONFIG_CXD56_LPADC1_OFFSET 0
+#endif
+#ifndef CONFIG_CXD56_LPADC2_OFFSET
+#define CONFIG_CXD56_LPADC2_OFFSET 0
+#endif
+#ifndef CONFIG_CXD56_LPADC3_OFFSET
+#define CONFIG_CXD56_LPADC3_OFFSET 0
+#endif
+
+#ifndef CONFIG_CXD56_HPADC0_GAIN
+#define CONFIG_CXD56_HPADC0_GAIN 0
+#endif
+#ifndef CONFIG_CXD56_HPADC1_GAIN
+#define CONFIG_CXD56_HPADC1_GAIN 0
+#endif
+#ifndef CONFIG_CXD56_LPADC0_GAIN
+#define CONFIG_CXD56_LPADC0_GAIN 0
+#endif
+#ifndef CONFIG_CXD56_LPADC1_GAIN
+#define CONFIG_CXD56_LPADC1_GAIN 0
+#endif
+#ifndef CONFIG_CXD56_LPADC2_GAIN
+#define CONFIG_CXD56_LPADC2_GAIN 0
+#endif
+#ifndef CONFIG_CXD56_LPADC3_GAIN
+#define CONFIG_CXD56_LPADC3_GAIN 0
+#endif
+
+#define ADC_BYTESPERSAMPLE 2
+#define ADC_ELEMENTSIZE 0
+
+typedef enum adc_ch
+{
+ CH0 = 0, /* LPADC0 */
+ CH1, /* LPADC1 */
+ CH2, /* LPADC2 */
+ CH3, /* LPADC3 */
+ CH4, /* HPADC0 */
+ CH5, /* HPADC1 */
+ CH_MAX,
+} adc_ch_t;
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure represents the state of one ADC channel */
+
+struct cxd56adc_dev_s
+{
+ adc_ch_t ch; /* adc cnannel number */
+ FAR struct seq_s *seq; /* sequencer */
+ uint8_t freq; /* coefficient of adc sampling frequency */
+ uint16_t fsize; /* SCU FIFO size */
+ uint16_t ofst; /* offset */
+ uint16_t gain; /* gain */
+ uint8_t fifomode; /* fifo mode */
+ struct scufifo_wm_s *wm; /* water mark */
+ struct math_filter_s *filter; /* math filter */
+ struct scuev_notify_s * notify; /* notify */
+};
+
+/****************************************************************************
+ * Static Function Prototypes
+ ****************************************************************************/
+
+/* Character driver methods */
+
+static int cxd56_adc_open(FAR struct file *filep);
+static int cxd56_adc_close(FAR struct file *filep);
+static ssize_t cxd56_adc_read(FAR struct file *filep, FAR char *buffer,
+ size_t len);
+static int cxd56_adc_ioctl(FAR struct file *filep, int cmd,
+ unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* ADC interface operations */
+
+static const struct file_operations g_adcops =
+{
+ cxd56_adc_open, /* open */
+ cxd56_adc_close, /* close */
+ cxd56_adc_read, /* read */
+ 0, /* write */
+ 0, /* seek */
+ cxd56_adc_ioctl, /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+ 0, /* poll */
+#endif
+};
+
+#if defined (CONFIG_CXD56_LPADC0) || defined (CONFIG_CXD56_LPADC0_1) || defined (CONFIG_CXD56_LPADC_ALL)
+static struct cxd56adc_dev_s g_lpadc0priv =
+{
+ .ch = CH0,
+ .seq = NULL,
+ .freq = CONFIG_CXD56_LPADC0_FREQ,
+ .fsize = CONFIG_CXD56_LPADC0_FSIZE,
+ .ofst = CONFIG_CXD56_LPADC0_OFFSET,
+ .gain = CONFIG_CXD56_LPADC0_GAIN,
+ .wm = NULL,
+ .filter = NULL,
+ .notify = NULL,
+};
+#endif
+
+#if defined (CONFIG_CXD56_LPADC1) || defined (CONFIG_CXD56_LPADC0_1) || defined (CONFIG_CXD56_LPADC_ALL)
+static struct cxd56adc_dev_s g_lpadc1priv =
+{
+ .ch = CH1,
+ .seq = NULL,
+ .freq = CONFIG_CXD56_LPADC1_FREQ,
+ .fsize = CONFIG_CXD56_LPADC1_FSIZE,
+ .ofst = CONFIG_CXD56_LPADC1_OFFSET,
+ .gain = CONFIG_CXD56_LPADC1_GAIN,
+ .wm = NULL,
+ .filter = NULL,
+ .notify = NULL,
+};
+#endif
+
+#if defined (CONFIG_CXD56_LPADC2) || defined (CONFIG_CXD56_LPADC_ALL)
+static struct cxd56adc_dev_s g_lpadc2priv =
+{
+ .ch = CH2,
+ .seq = NULL,
+ .freq = CONFIG_CXD56_LPADC2_FREQ,
+ .fsize = CONFIG_CXD56_LPADC2_FSIZE,
+ .ofst = CONFIG_CXD56_LPADC2_OFFSET,
+ .gain = CONFIG_CXD56_LPADC2_GAIN,
+ .wm = NULL,
+ .filter = NULL,
+ .notify = NULL,
+};
+#endif
+
+#if defined (CONFIG_CXD56_LPADC3) || defined (CONFIG_CXD56_LPADC_ALL)
+static struct cxd56adc_dev_s g_lpadc3priv =
+{
+ .ch = CH3,
+ .seq = NULL,
+ .freq = CONFIG_CXD56_LPADC3_FREQ,
+ .fsize = CONFIG_CXD56_LPADC3_FSIZE,
+ .ofst = CONFIG_CXD56_LPADC3_OFFSET,
+ .gain = CONFIG_CXD56_LPADC3_GAIN,
+ .wm = NULL,
+ .filter = NULL,
+ .notify = NULL,
+};
+#endif
+
+#ifdef CONFIG_CXD56_HPADC0
+static struct cxd56adc_dev_s g_hpadc0priv =
+{
+ .ch = CH4,
+ .seq = NULL,
+ .freq = CONFIG_CXD56_HPADC0_FREQ,
+ .fsize = CONFIG_CXD56_HPADC0_FSIZE,
+ .ofst = CONFIG_CXD56_HPADC0_OFFSET,
+ .gain = CONFIG_CXD56_HPADC0_GAIN,
+ .wm = NULL,
+ .filter = NULL,
+ .notify = NULL,
+};
+#endif
+
+#ifdef CONFIG_CXD56_HPADC1
+static struct cxd56adc_dev_s g_hpadc1priv =
+{
+ .ch = CH5,
+ .seq = NULL,
+ .freq = CONFIG_CXD56_HPADC1_FREQ,
+ .fsize = CONFIG_CXD56_HPADC1_FSIZE,
+ .ofst = CONFIG_CXD56_HPADC1_OFFSET,
+ .gain = CONFIG_CXD56_HPADC1_GAIN,
+ .wm = NULL,
+ .filter = NULL,
+ .notify = NULL,
+};
+#endif
+
+static bool adc_active[CH_MAX] = {
+ false, false, false, false, false, false
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: set_ofstgain
+ *
+ * Description:
+ * Set parameters for offset/gain.
+ *
+ ****************************************************************************/
+
+static int set_ofstgain(FAR struct cxd56adc_dev_s *priv)
+{
+ int ret = OK;
+ uint32_t addr;
+
+ if (priv->ch == CH5)
+ {
+ addr = SCUSEQ_ADC_MATH_PROC_OFST_GAIN(priv->ch + 1);
+ }
+ else
+ {
+ addr = SCUSEQ_ADC_MATH_PROC_OFST_GAIN(priv->ch);
+ }
+
+ if ((priv->ofst > 0) || (priv->gain > 0))
+ {
+ putreg32(priv->gain << 16 | priv->ofst, addr);
+ ret = seq_ioctl(priv->seq, 0, SCUIOC_SETOGADJUST, 0);
+ if (ret < 0)
+ {
+ aerr("SETOGADJUST failed. %d\n", ret);
+ return ret;
+ }
+ }
+ else
+ {
+ putreg32(0x08000000, addr);
+ ret = seq_ioctl(priv->seq, 0, SCUIOC_CLROGADJUST, 0);
+ if (ret < 0)
+ {
+ aerr("CLROGADJUST failed. %d\n", ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: adc_start
+ *
+ * Description:
+ * Start ADC channel.
+ *
+ ****************************************************************************/
+
+static int adc_start(adc_ch_t ch, uint8_t freq, FAR struct seq_s *seq,
+ int fsize, int fifomode,
+ struct scufifo_wm_s *wm,
+ struct math_filter_s *filter,
+ struct scuev_notify_s *notify)
+{
+ uint32_t *addr;
+ uint32_t val;
+ uint32_t mask;
+ uint32_t div;
+ int ret;
+
+ if (adc_active[ch])
+ {
+ return OK;
+ }
+
+ ret = seq_ioctl(seq, 0, SCUIOC_SETFIFO, fsize);
+ if (ret < 0)
+ {
+ aerr("SETFIFO failed. %d\n", ret);
+ return ret;
+ }
+ ret = seq_ioctl(seq, 0, SCUIOC_SETFIFOMODE, fifomode);
+ if (ret < 0)
+ {
+ aerr("SETFIFOMODE failed. %d\n", ret);
+ return ret;
+ }
+ if (wm)
+ {
+ ret = seq_ioctl(seq, 0, SCUIOC_SETWATERMARK, (unsigned long)wm);
+ if (ret < 0)
+ {
+ aerr("SETWATERMARK failed. %d\n", ret);
+ return ret;
+ }
+ }
+ if (filter)
+ {
+ ret = seq_ioctl(seq, 0, SCUIOC_SETFILTER, (unsigned long)filter);
+ if (ret < 0)
+ {
+ aerr("SETFILTER failed. %d\n", ret);
+ return ret;
+ }
+ }
+ if (notify)
+ {
+ ret = seq_ioctl(seq, 0, SCUIOC_SETNOTIFY, (unsigned long)notify);
+ if (ret < 0)
+ {
+ aerr("SETNOTIFY failed. %d\n", ret);
+ return ret;
+ }
+ }
+ if (ch <= CH3)
+ {
+ /* LPADC.A1 LPADC_CH : todo: GPS ch */
+
+ val = ch;
+#ifdef CONFIG_CXD56_LPADC0_1
+ val = 4;
+#endif
+#ifdef CONFIG_CXD56_LPADC_ALL
+ val = 5;
+#endif
+ putreg32(val, SCUADCIF_LPADC_A1);
+
+ /* LPADC_D1/D4/D5/D6 ratio */
+
+ div = (freq <= 15) ? freq : 15;
+ addr = (ch == CH0) ? (uint32_t *)SCUADCIF_LPADC_D1 :
+ (uint32_t *)(SCUADCIF_LPADC_D4 + 4 * (ch - CH1));
+ mask = 0x00000f00;
+ val = getreg32(addr) & ~mask;
+ val |= (div << 8);
+ putreg32(val, addr);
+
+ /* LPADC_AT1 */
+
+ mask = 0x000000ff;
+ val = getreg32(SCUADCIF_LPADC_AT1) & ~mask;
+ val |= 0x00000004;
+ putreg32(val, SCUADCIF_LPADC_AT1);
+
+ /* LPADC_AT0 */
+
+ mask = 0x00000001;
+ val = getreg32(SCUADCIF_LPADC_AT0) & ~mask;
+ putreg32(val, SCUADCIF_LPADC_AT0);
+
+ /* power and clock */
+
+ div = (freq <= 15) ? 0 : freq - 15;
+ cxd56_lpadc_clock_enable(div);
+
+ /* LPADC.A0 */
+
+ putreg32(1, SCUADCIF_LPADC_A0);
+
+ /* LPADC.D0 */
+
+ putreg32(1, SCUADCIF_LPADC_D0);
+ }
+ else
+ {
+ /* HPADC.AC0 */
+
+#ifndef CONFIG_CXD56_SCU_32K
+#ifdef CONFIG_CXD56_SCU_RCOSC
+ val = 0x00000001;
+#else
+ uint32_t xoscfreq = cxd56_get_xosc_clock();
+ if (xoscfreq <= 24000000)
+ {
+ val = 0x00000000;
+ }
+ else if (xoscfreq <= 30000000)
+ {
+ val = 0x00000010;
+ }
+ else if (xoscfreq <= 45000000)
+ {
+ val = 0x00000020;
+ }
+ else
+ {
+ val = 0x00000030;
+ }
+#endif
+ putreg32(val, SCUADCIF_HPADC_AC0);
+#endif
+
+ /* HPADC.AC1 */
+
+ putreg32(1, SCUADCIF_HPADC_AC1);
+
+ /* HPADCn.A0 */
+
+ addr = (ch == CH4) ? (uint32_t *)SCUADCIF_HPADC0_A0 :
+ (uint32_t *)SCUADCIF_HPADC1_A0;
+#ifdef CONFIG_CXD56_SCU_32K
+ val = 0x00000001;
+#else
+ val = 0x00000000;
+#endif
+ putreg32(val, addr);
+
+ /* HPADC.DC : todo: HPADC0 16bit x 2 */
+
+ /* HPADCn.AT0 */
+
+ addr = (ch == CH4) ? (uint32_t *)SCUADCIF_HPADC0_AT0 :
+ (uint32_t *)SCUADCIF_HPADC1_AT0;
+ mask = 0x000000f1;
+ val = getreg32(addr) & ~mask;
+ val |= 0x000000c0;
+ putreg32(val, addr);
+
+ /* power and clock */
+
+ div = (freq <= 7) ? 0 : freq - 7;
+ cxd56_hpadc_clock_enable(div);
+
+ /* HPADC.A1 */
+
+ addr = (ch == CH4) ? (uint32_t *)SCUADCIF_HPADC0_A1 :
+ (uint32_t *)SCUADCIF_HPADC1_A1;
+ putreg32(7, addr);
+
+ /* HPADC.A2 */
+
+ addr = (ch == CH4) ? (uint32_t *)SCUADCIF_HPADC0_A2 :
+ (uint32_t *)SCUADCIF_HPADC1_A2;
+ putreg32(1, addr);
+
+ /* HPADC.D0 */
+
+ addr = (ch == CH4) ? (uint32_t *)SCUADCIF_HPADC0_D0 :
+ (uint32_t *)SCUADCIF_HPADC1_D0;
+ putreg32(1, addr);
+
+ /* HPADC.D1 */
+
+ div = (freq <= 7) ? freq : 7;
+ addr = (ch == CH4) ? (uint32_t *)SCUADCIF_HPADC0_D1 :
+ (uint32_t *)SCUADCIF_HPADC1_D1;
+ mask = 0x00000700;
+ val = getreg32(addr) & ~mask;
+ val |= (div << 8);
+ putreg32(val, addr);
+ }
+
+ ret = seq_ioctl(seq, 0, SCUIOC_START, 0);
+
+ if (!ret)
+ {
+ if (ch <= CH3)
+ {
+ /* LPADC.D2 */
+
+ mask = 0x1 << ch;
+ val = getreg32(SCUADCIF_LPADC_D2) & ~mask;
+ val |= mask;
+ putreg32(val, SCUADCIF_LPADC_D2);
+ }
+ else
+ {
+ /* HPADC.D2 */
+
+ addr = (ch == CH4) ? (uint32_t *)SCUADCIF_HPADC0_D2 :
+ (uint32_t *)SCUADCIF_HPADC1_D2;
+ putreg32(1, addr);
+ }
+ adc_active[ch] = true;
+ }
+ else
+ {
+ /* todo:err case */
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: adc_stop
+ *
+ * Description:
+ * Stop ADC channel.
+ *
+ ****************************************************************************/
+
+static int adc_stop(adc_ch_t ch, FAR struct seq_s *seq)
+{
+ uint32_t *addr;
+ uint32_t val;
+ uint32_t mask;
+ int i;
+ bool is_clockdisable = true;
+
+ if (!adc_active[ch])
+ {
+ return OK;
+ }
+
+ (void) seq_ioctl(seq, 0, SCUIOC_STOP, 0);
+
+ if (ch <= CH3)
+ {
+ /* LPADC.D2 */
+
+ mask = 0x1 << ch;
+ val = getreg32(SCUADCIF_LPADC_D2) & ~mask;
+ putreg32(val, SCUADCIF_LPADC_D2);
+
+ for (i = 0; i < CH4; i++)
+ {
+ if ((i != ch) && adc_active[i])
+ {
+ is_clockdisable = false;
+ break;
+ }
+ }
+ if (is_clockdisable)
+ {
+ cxd56_lpadc_clock_disable();
+ }
+ }
+ else
+ {
+ /* HPADC.D2 */
+
+ addr = (ch == CH4) ? (uint32_t *)SCUADCIF_HPADC0_D2 :
+ (uint32_t *)SCUADCIF_HPADC1_D2;
+ putreg32(0, addr);
+
+ if (((ch == CH4) && !adc_active[CH5]) ||
+ ((ch == CH5) && !adc_active[CH4]))
+ {
+ cxd56_hpadc_clock_disable();
+ }
+ }
+
+ adc_active[ch] = false;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: adc_validcheck
+ *
+ * Description:
+ * Check ioctl command to pass to scu driver.
+ *
+ ****************************************************************************/
+
+static bool adc_validcheck(int cmd)
+{
+ if ((cmd == SCUIOC_SETFILTER) ||
+ (cmd == SCUIOC_SETNOTIFY) ||
+ (cmd == SCUIOC_SETWATERMARK) ||
+ (cmd == SCUIOC_SETFIFOMODE) ||
+ (cmd == SCUIOC_DELFIFODATA))
+ {
+ return true;
+ }
+ return false;
+}
+
+/****************************************************************************
+ * Name: cxd56_adc_open
+ *
+ * Description:
+ * Standard character driver open method.
+ *
+ ****************************************************************************/
+
+static int cxd56_adc_open(FAR struct file *filep)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct cxd56adc_dev_s *priv = inode->i_private;
+ int ret = OK;
+ int type;
+
+ DEBUGASSERT(priv != NULL);
+ DEBUGASSERT(priv->seq == NULL);
+ DEBUGASSERT(priv->ch < CH_MAX);
+
+ type = SCU_BUS_LPADC0 + priv->ch;
+
+ /* Open sequencer */
+
+ priv->seq = seq_open(SEQ_TYPE_NORMAL, type);
+ if (!priv->seq)
+ {
+ return -ENOENT;
+ }
+
+ /* Set sample data information to sequencer */
+
+ seq_setsample(priv->seq, ADC_BYTESPERSAMPLE, 0, ADC_ELEMENTSIZE, false);
+
+ /* Set offset/gain */
+
+ ret = set_ofstgain(priv);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ ainfo("open ch%d freq%d scufifo%d\n", priv->ch, priv->freq, priv->fsize);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_adc_close
+ *
+ * Description:
+ * Standard character driver close method.
+ *
+ ****************************************************************************/
+
+static int cxd56_adc_close(FAR struct file *filep)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct cxd56adc_dev_s *priv = inode->i_private;
+
+ DEBUGASSERT(priv != NULL);
+ DEBUGASSERT(priv->seq != NULL);
+ DEBUGASSERT(priv->ch < CH_MAX);
+
+ /* Close sequencer */
+
+ seq_close(priv->seq);
+ priv->seq = NULL;
+
+ if (priv->wm)
+ {
+ kmm_free(priv->wm);
+ priv->wm = NULL;
+ }
+ if (priv->filter)
+ {
+ kmm_free(priv->filter);
+ priv->filter = NULL;
+ }
+ if (priv->notify)
+ {
+ kmm_free(priv->notify);
+ priv->notify = NULL;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_adc_read
+ *
+ * Description:
+ * Standard character driver read method.
+ *
+ ****************************************************************************/
+
+static ssize_t cxd56_adc_read(FAR struct file *filep, FAR char *buffer,
+ size_t len)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct cxd56adc_dev_s *priv = inode->i_private;
+ int ret = OK;
+
+ DEBUGASSERT(priv != NULL);
+ DEBUGASSERT(priv->seq != NULL);
+ DEBUGASSERT(priv->ch < CH_MAX);
+
+ len = len / ADC_BYTESPERSAMPLE * ADC_BYTESPERSAMPLE;
+ ret = seq_read(priv->seq, 0, buffer, len);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: cxd56_adc_ioctl
+ *
+ * Description:
+ * Standard character driver ioctl method.
+ *
+ ****************************************************************************/
+
+static int cxd56_adc_ioctl(FAR struct file *filep, int cmd,
+ unsigned long arg)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct cxd56adc_dev_s *priv = inode->i_private;
+ int ret = OK;
+ DEBUGASSERT(priv != NULL);
+ DEBUGASSERT(priv->seq != NULL);
+ DEBUGASSERT(priv->ch < CH_MAX);
+
+ switch (cmd)
+ {
+ case ANIOC_TRIGGER:
+ case ANIOC_CXD56_START:
+ ret = adc_start(priv->ch, priv->freq, priv->seq,
+ priv->fsize, priv->fifomode,
+ priv->wm, priv->filter, priv->notify);
+ break;
+
+ case ANIOC_CXD56_STOP:
+ ret = adc_stop(priv->ch, priv->seq);
+ break;
+
+ case ANIOC_CXD56_FREQ:
+ priv->freq = arg;
+ break;
+
+ case ANIOC_CXD56_FIFOSIZE:
+ priv->fsize = arg;
+ break;
+
+ case SCUIOC_SETFIFOMODE:
+ priv->fifomode = arg;
+ break;
+
+ case SCUIOC_SETWATERMARK:
+ if (adc_active[priv->ch] == false) /* before start */
+ {
+ struct scufifo_wm_s *wm = (struct scufifo_wm_s *)arg;
+ priv->wm = (struct scufifo_wm_s *)
+ kmm_malloc(sizeof(struct scufifo_wm_s));
+ *(priv->wm) = *wm;
+ }
+ else
+ {
+ ret = seq_ioctl(priv->seq, 0, cmd, arg);
+ }
+ break;
+
+ case SCUIOC_SETFILTER:
+ if (adc_active[priv->ch] == false) /* before start */
+ {
+ struct math_filter_s *filter = (struct math_filter_s *)arg;
+ priv->filter = (struct math_filter_s *)
+ kmm_malloc(sizeof(struct math_filter_s));
+ *(priv->filter) = *filter;
+ }
+ else
+ {
+ ret = seq_ioctl(priv->seq, 0, cmd, arg);
+ }
+ break;
+
+ case SCUIOC_SETNOTIFY:
+ if (adc_active[priv->ch] == false) /* before start */
+ {
+ struct scuev_notify_s *notify = (struct scuev_notify_s *)arg;
+ priv->notify = (struct scuev_notify_s *)
+ kmm_malloc(sizeof(struct scuev_notify_s));
+ *(priv->notify) = *notify;
+ }
+ else
+ {
+ ret = seq_ioctl(priv->seq, 0, cmd, arg);
+ }
+ break;
+
+ default:
+ {
+ if (adc_validcheck(cmd))
+ {
+ /* Redirect SCU commands */
+
+ ret = seq_ioctl(priv->seq, 0, cmd, arg);
+ }
+ else
+ {
+ aerr("Unrecognized cmd: %d\n", cmd);
+ ret = -EINVAL;
+ }
+ }
+ break;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_adc_getinterval
+ *
+ * Description:
+ * get sampling interval of ADC.
+ *
+ * Input Parameters:
+ * bustype - SCU_BUS_LPADC0, SCU_BUS_LPADC1, SCU_BUS_LPADC2, SCU_BUS_LPADC3,
+ * SCU_BUS_HPADC0, SCU_BUS_HPADC1
+ * *interval - Sampling interval
+ * *adjust - Adjustment value used for timestamp calculation
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void cxd56_adc_getinterval(int adctype, uint32_t *interval, uint16_t *adjust)
+{
+ uint32_t intval = 0;
+ uint32_t div = 0;
+
+ DEBUGASSERT(interval != NULL && adjust != NULL);
+
+ if ((adctype >= SCU_BUS_LPADC0) && (adctype <= SCU_BUS_LPADC3))
+ {
+ uint32_t chmodediv = 0;
+
+ *adjust = 0;
+#ifdef CONFIG_CXD56_LPADC0_1
+ chmodediv = 1;
+#endif
+#ifdef CONFIG_CXD56_LPADC_ALL
+ chmodediv = 2;
+#endif
+
+ if (adctype == SCU_BUS_LPADC0)
+ {
+#if defined (CONFIG_CXD56_LPADC0) || defined (CONFIG_CXD56_LPADC0_1) || defined (CONFIG_CXD56_LPADC_ALL)
+ div = g_lpadc0priv.freq;
+#endif
+ }
+ else if (adctype == SCU_BUS_LPADC1)
+ {
+#if defined (CONFIG_CXD56_LPADC1) || defined (CONFIG_CXD56_LPADC0_1) || defined (CONFIG_CXD56_LPADC_ALL)
+ div = g_lpadc1priv.freq;
+#endif
+ }
+ else if (adctype == SCU_BUS_LPADC2)
+ {
+#if defined (CONFIG_CXD56_LPADC2) || defined (CONFIG_CXD56_LPADC_ALL)
+ div = g_lpadc2priv.freq;
+#endif
+ }
+ else if (adctype == SCU_BUS_LPADC3)
+ {
+#if defined (CONFIG_CXD56_LPADC3) || defined (CONFIG_CXD56_LPADC_ALL)
+ div = g_lpadc3priv.freq;
+#endif
+ }
+
+ *interval = 1 << (chmodediv + div);
+ }
+ else if ((adctype == SCU_BUS_HPADC0) || (adctype == SCU_BUS_HPADC1))
+ {
+ *adjust = 1;
+ if (adctype == SCU_BUS_HPADC0)
+ {
+#ifdef CONFIG_CXD56_HPADC0
+ div = g_hpadc0priv.freq;
+#endif
+ }
+ else if (adctype == SCU_BUS_HPADC1)
+ {
+#ifdef CONFIG_CXD56_HPADC1
+ div = g_hpadc1priv.freq;
+#endif
+ }
+
+#ifdef CONFIG_CXD56_SCU_32K
+ *interval = 1 << div;
+#else
+ uint32_t freq = 0;
+#ifdef CONFIG_CXD56_SCU_RCOSC
+ freq = cxd56_get_rcosc_clock();
+#else
+ freq = cxd56_get_xosc_clock();
+ if (freq <= 24000000)
+ {
+ freq /= 2;
+ }
+ else if (freq <= 30000000)
+ {
+ freq /= 3;
+ }
+ else if (freq <= 45000000)
+ {
+ freq /= 4;
+ }
+ else
+ {
+ freq /= 6;
+ }
+#endif
+ if (freq > 0)
+ {
+ intval = (32768 << (2 + div + 1)) / freq;
+ if (intval & 1)
+ {
+ *interval = (intval >> 1) + 1;
+ }
+ else
+ {
+ *interval = (intval >> 1);
+ }
+ }
+#endif
+ }
+}
+
+/****************************************************************************
+ * Name: cxd56_adcinitialize
+ *
+ * Description:
+ * Initialize ADC channel for use with the upper_level ADC driver.
+ *
+ * Input Parameters:
+ * channel - adc channel number.
+ *
+ * Returned Value:
+ * On success, a pointer to the CXD56 lower half ADC driver is returned.
+ * NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+int cxd56_adcinitialize(void)
+{
+ int ret;
+
+ /* Avoid warnings when no ADC options enabled */
+
+ (void) ret;
+
+#if defined (CONFIG_CXD56_LPADC0) || defined (CONFIG_CXD56_LPADC0_1) || defined (CONFIG_CXD56_LPADC_ALL)
+ ret = register_driver("/dev/lpadc0", &g_adcops, 0666, &g_lpadc0priv);
+ if (ret < 0)
+ {
+ aerr("Failed to register driver(lpadc0): %d\n", ret);
+ return ret;
+ }
+#endif
+#if defined (CONFIG_CXD56_LPADC1) || defined (CONFIG_CXD56_LPADC0_1) || defined (CONFIG_CXD56_LPADC_ALL)
+ ret = register_driver("/dev/lpadc1", &g_adcops, 0666, &g_lpadc1priv);
+ if (ret < 0)
+ {
+ aerr("Failed to register driver(lpadc1): %d\n", ret);
+ return ret;
+ }
+#endif
+#if defined (CONFIG_CXD56_LPADC2) || defined (CONFIG_CXD56_LPADC_ALL)
+ ret = register_driver("/dev/lpadc2", &g_adcops, 0666, &g_lpadc2priv);
+ if (ret < 0)
+ {
+ aerr("Failed to register driver(lpadc2): %d\n", ret);
+ return ret;
+ }
+#endif
+#if defined (CONFIG_CXD56_LPADC3) || defined (CONFIG_CXD56_LPADC_ALL)
+ ret = register_driver("/dev/lpadc3", &g_adcops, 0666, &g_lpadc3priv);
+ if (ret < 0)
+ {
+ aerr("Failed to register driver(lpadc3): %d\n", ret);
+ return ret;
+ }
+#endif
+#ifdef CONFIG_CXD56_HPADC0
+ ret = register_driver("/dev/hpadc0", &g_adcops, 0666, &g_hpadc0priv);
+ if (ret < 0)
+ {
+ aerr("Failed to register driver(hpadc0): %d\n", ret);
+ return ret;
+ }
+#endif
+#ifdef CONFIG_CXD56_HPADC1
+ ret = register_driver("/dev/hpadc1", &g_adcops, 0666, &g_hpadc1priv);
+ if (ret < 0)
+ {
+ aerr("Failed to register driver(hpadc1): %d\n", ret);
+ return ret;
+ }
+#endif
+
+ return OK;
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_adc.h b/arch/arm/src/cxd56xx/cxd56_adc.h
new file mode 100644
index 00000000000..8531d5c79c0
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_adc.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_adc.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_ADC_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_ADC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+
+#ifndef __ASSEMBLY__
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_adc_getinterval
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_CXD56_ADC
+void cxd56_adc_getinterval(int adctype, uint32_t *interval, uint16_t *adjust);
+#else
+#define cxd56_adc_getinterval(adctype, interval, adjust)
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_ADC_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_charger.c b/arch/arm/src/cxd56xx/cxd56_charger.c
new file mode 100644
index 00000000000..3a53cef8458
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_charger.c
@@ -0,0 +1,688 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_charger.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* CXD5247GF is Li-Ion Battery Charger with Power-Path Management.
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include "cxd56_pmic.h"
+
+#ifdef CONFIG_CXD56_CHARGER
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Debug ********************************************************************/
+
+#ifdef CONFIG_CXD56_CHARGER_DEBUG
+#define baterr(fmt, ...) logerr(fmt, ## __VA_ARGS__)
+#define batdbg(fmt, ...) logdebug(fmt, ## __VA_ARGS__)
+#else
+#define baterr(fmt, ...)
+#define batdbg(fmt, ...)
+#endif
+
+/* Configuration */
+
+#undef USE_FLOAT_CONVERSION
+
+#ifdef CONFIG_CXD56_CHARGER_TEMP_PRECISE
+#if !defined(CONFIG_LIBM) && !defined(CONFIG_LIBM_NEWLIB)
+# error Temperature conversion in float requires math library.
+#endif
+#define USE_FLOAT_CONVERSION 1
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct charger_dev_s
+{
+ sem_t batsem;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int charger_get_status(FAR enum battery_charger_status_e *status);
+static int charger_get_health(FAR enum battery_charger_health_e *health);
+static int charger_online(FAR bool *online);
+static int charger_get_temptable(FAR struct battery_temp_table_s *table);
+static int charger_set_temptable(FAR struct battery_temp_table_s *table);
+
+static int charger_open(FAR struct file *filep);
+static int charger_close(FAR struct file *filep);
+static ssize_t charger_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen);
+static ssize_t charger_write(FAR struct file *filep,
+ FAR const char *buffer, size_t buflen);
+static int charger_ioctl(FAR struct file *filep, int cmd,
+ unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_chargerops =
+{
+ charger_open, /* open */
+ charger_close, /* close */
+ charger_read, /* read */
+ charger_write, /* write */
+ 0, /* seek */
+ charger_ioctl /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+ , NULL /* poll */
+#endif
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ , NULL /* unlink */
+#endif
+};
+
+static struct charger_dev_s g_chargerdev;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: charger_therm2temp
+ *
+ * Description:
+ * Convert temperature register value to degrees Celsius.
+ *
+ ****************************************************************************/
+
+static int charger_therm2temp(int val)
+{
+#ifdef USE_FLOAT_CONVERSION
+ float f1;
+ float f2;
+ float f3;
+ float f4;
+ float f5;
+ float f6;
+
+ f1 = (float)val;
+ f2 = f1 / 4096.f;
+ f3 = f2 * 100.f / (1.f - f2);
+ f4 = f3 / 100.f;
+ f5 = logf(f4);
+ f6 = 1.f / (f5 / 4250.f + 1.f / 298.f) - 273.f;
+
+ return (int)f6;
+#else
+ static short T[29] = /* -40,-35,..-20,-15,..,95,100 */
+ { 4020, 3986, 3939, 3877, 3759, 3691, 3562, 3405, 3222, 3015, /* -40,.. */
+ 2787, 2545, 2296, 2048, 1808, 1582, 1374, 1186, 1020, 874, /* 10,.. */
+ 747, 639 , 546, 467, 400, 343, 295, 254, 220
+ }; /* 60,..,100 */
+ int i;
+ int t0 = -45;
+ int t1 = -40;
+ int tt = -45;
+
+ for (i = 0; i < 29; i++)
+ {
+ if (val > T[i])
+ {
+ break;
+ }
+ t0 += 5;
+ t1 += 5;
+ }
+
+ if (i > 0)
+ {
+ int diff = T[i - 1] - T[i];
+ tt = t1 - (val - T[i]) * 5 / diff; /* interpolation : not accurate */
+ }
+
+ return tt;
+#endif
+}
+
+/****************************************************************************
+ * Name: charger_get_status
+ ****************************************************************************/
+
+static int charger_get_status(FAR enum battery_charger_status_e *status)
+{
+ uint8_t state;
+ int ret;
+
+ if (status == NULL)
+ {
+ return -EINVAL;
+ }
+
+ *status = BATTERY_UNKNOWN;
+
+ ret = cxd56_pmic_getchargestate(&state);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+ switch (state)
+ {
+ /* Is there some fault in the battery? */
+
+ case PMIC_STAT_BAT_UNUSUAL:
+ *status = BATTERY_FAULT;
+ break;
+
+ /* Is the charging done? */
+
+ case PMIC_STAT_CHG_COMPLETE:
+ *status = BATTERY_FULL;
+ break;
+
+ /* Is the charging in progress? */
+
+ case PMIC_STAT_GB_QCKCHARGE:
+ case PMIC_STAT_GB_LOWCHARGE:
+ case PMIC_STAT_GB_HIGHCHARGE:
+ *status = BATTERY_CHARGING;
+ break;
+
+ /* Is the charging ready? */
+
+ case PMIC_STAT_CHG_STOP:
+ *status = BATTERY_DISCHARGING;
+ break;
+
+ default:
+ _info("Charge state %d\n", state);
+ *status = BATTERY_IDLE;
+ break;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: charger_get_health
+ ****************************************************************************/
+
+static int charger_get_health(FAR enum battery_charger_health_e *health)
+{
+ FAR struct pmic_gauge_s gauge;
+ uint8_t state;
+ int temp;
+ int ret;
+
+ if (health == NULL)
+ {
+ return -EINVAL;
+ }
+
+ *health = BATTERY_HEALTH_UNKNOWN;
+
+ ret = cxd56_pmic_get_gauge(&gauge);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+ ret = cxd56_pmic_getchargestate(&state);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+ /* Convert register value to degrees Celsius */
+
+ temp = charger_therm2temp(gauge.temp);
+
+ if (temp < 10)
+ {
+ *health = BATTERY_HEALTH_COLD;
+ }
+ else if (temp > 60)
+ {
+ *health = BATTERY_HEALTH_OVERHEAT;
+ }
+ else
+ {
+ *health = BATTERY_HEALTH_GOOD;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: charger_online
+ ****************************************************************************/
+
+static int charger_online(FAR bool *online)
+{
+ if (online == NULL)
+ {
+ return -EINVAL;
+ }
+ *online = true;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: charger_get_current
+ ****************************************************************************/
+
+static int charger_get_current(FAR int *current)
+{
+ FAR struct pmic_gauge_s gauge;
+ int ret;
+
+ ASSERT(current);
+
+ *current = 0;
+
+ ret = cxd56_pmic_get_gauge(&gauge);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+ /* (Register value - 800h) / Current detection resistor (0.1 ohm) * 0.02929 */
+
+#ifdef USE_FLOAT_CONVERSION
+ *current = (gauge.current - 0x800) / 0.1f * 0.02929f;
+#else
+ *current = (gauge.current - 0x800) * 2929 / 10000;
+#endif
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: charger_get_voltage
+ ****************************************************************************/
+
+static int charger_get_voltage(FAR int *voltage)
+{
+ FAR struct pmic_gauge_s gauge;
+ int ret;
+
+ ASSERT(voltage);
+
+ *voltage = 0;
+
+ ret = cxd56_pmic_get_gauge(&gauge);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+#ifdef USE_FLOAT_CONVERSION
+ *voltage = gauge.voltage * 1.12f;
+#else
+ *voltage = gauge.voltage * 112 / 100;
+#endif
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: charger_get_temptable
+ ****************************************************************************/
+
+static int charger_get_temptable(FAR struct battery_temp_table_s *table)
+{
+ struct pmic_temp_table_s buf;
+ int ret;
+
+ ret = cxd56_pmic_gettemptable(&buf);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+ table->T60 = buf.T60;
+ table->T45 = buf.T45;
+ table->T10 = buf.T10;
+ table->T00 = buf.T00;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: charger_set_temptable
+ ****************************************************************************/
+
+static int charger_set_temptable(FAR struct battery_temp_table_s *table)
+{
+ struct pmic_temp_table_s buf;
+
+ buf.T60 = table->T60;
+ buf.T45 = table->T45;
+ buf.T10 = table->T10;
+ buf.T00 = table->T00;
+
+ return cxd56_pmic_settemptable(&buf);
+}
+
+/****************************************************************************
+ * Name: charger_open
+ *
+ * Description:
+ * This function is called whenever the battery device is opened.
+ *
+ ****************************************************************************/
+
+static int charger_open(FAR struct file *filep)
+{
+ return OK;
+}
+
+/****************************************************************************
+ * Name: charger_close
+ *
+ * Description:
+ * This routine is called when the battery device is closed.
+ *
+ ****************************************************************************/
+
+static int charger_close(FAR struct file *filep)
+{
+ return OK;
+}
+
+/****************************************************************************
+ * Name: charger_read
+ ****************************************************************************/
+
+static ssize_t charger_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen)
+{
+ /* Return nothing read */
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: charger_write
+ ****************************************************************************/
+
+static ssize_t charger_write(FAR struct file *filep,
+ FAR const char *buffer, size_t buflen)
+{
+ /* Return nothing written */
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: charger_ioctl
+ ****************************************************************************/
+
+static int charger_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct charger_dev_s *priv = inode->i_private;
+ int ret = -ENOTTY;
+
+ sem_wait(&priv->batsem);
+
+ switch (cmd)
+ {
+ case BATIOC_STATE:
+ {
+ FAR enum battery_charger_status_e *status =
+ (FAR enum battery_charger_status_e *)(uintptr_t)arg;
+ ret = charger_get_status(status);
+ }
+ break;
+
+ case BATIOC_HEALTH:
+ {
+ FAR enum battery_charger_health_e *health =
+ (FAR enum battery_charger_health_e *)(uintptr_t)arg;
+ ret = charger_get_health(health);
+ }
+ break;
+
+ case BATIOC_ONLINE:
+ {
+ FAR bool *online = (FAR bool *)(uintptr_t)arg;
+ ret = charger_online(online);
+ }
+ break;
+
+ case BATIOC_VOLTAGE:
+ {
+ FAR int *voltage = (FAR int *)(uintptr_t)arg;
+ ret = cxd56_pmic_setchargevol(*voltage);
+ }
+ break;
+
+ case BATIOC_CURRENT:
+ {
+ /* Not supported */
+
+ ret = OK;
+ }
+ break;
+
+ case BATIOC_INPUT_CURRENT:
+ {
+ FAR int *current = (FAR int *)(uintptr_t)arg;
+ ret = cxd56_pmic_setchargecurrent(*current);
+ }
+ break;
+
+ case BATIOC_GET_CHGVOLTAGE:
+ {
+ FAR int *voltage = (FAR int *)(uintptr_t)arg;
+ ret = cxd56_pmic_getchargevol(voltage);
+ }
+ break;
+
+ case BATIOC_GET_CHGCURRENT:
+ {
+ FAR int *current = (FAR int *)(uintptr_t)arg;
+ ret = cxd56_pmic_getchargecurrent(current);
+ }
+ break;
+
+ case BATIOC_GET_RECHARGEVOL:
+ {
+ FAR int *voltage = (FAR int *)(uintptr_t)arg;
+ ret = cxd56_pmic_getrechargevol(voltage);
+ }
+ break;
+
+ case BATIOC_SET_RECHARGEVOL:
+ {
+ FAR int *voltage = (FAR int *)(uintptr_t)arg;
+ ret = cxd56_pmic_setrechargevol(*voltage);
+ }
+ break;
+
+ case BATIOC_GET_COMPCURRENT:
+ {
+ FAR int *current = (FAR int *)(uintptr_t)arg;
+ ret = cxd56_pmic_getchargecompcurrent(current);
+ }
+ break;
+
+ case BATIOC_GET_TEMPTABLE:
+ {
+ FAR struct battery_temp_table_s *table =
+ (FAR struct battery_temp_table_s *)(uintptr_t)arg;
+ ret = charger_get_temptable(table);
+ }
+ break;
+
+ case BATIOC_SET_TEMPTABLE:
+ {
+ FAR struct battery_temp_table_s *table =
+ (FAR struct battery_temp_table_s *)(uintptr_t)arg;
+ ret = charger_set_temptable(table);
+ }
+ break;
+
+ case BATIOC_SET_COMPCURRENT:
+ {
+ FAR int *current = (FAR int *)(uintptr_t)arg;
+ ret = cxd56_pmic_setchargecompcurrent(*current);
+ }
+ break;
+
+ case BATIOC_GET_CURRENT:
+ {
+ FAR int *curr = (FAR int *)(uintptr_t)arg;
+
+ if (curr)
+ {
+ ret = charger_get_current(curr);
+ }
+ else
+ {
+ set_errno(EINVAL);
+ ret = -1;
+ }
+ }
+ break;
+
+ case BATIOC_GET_VOLTAGE:
+ {
+ FAR int *vol = (FAR int *)(uintptr_t)arg;
+
+ if (vol)
+ {
+ ret = charger_get_voltage(vol);
+ }
+ else
+ {
+ set_errno(EINVAL);
+ ret = -1;
+ }
+ }
+ break;
+
+ default:
+ ret = -ENOTTY;
+ break;
+ }
+
+ sem_post(&priv->batsem);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: cxd56_charger_initialize
+ *
+ * Description:
+ * Initialize the CXD5247 battery charger driver.
+ *
+ * Input Parameters:
+ * devpath - Device file path
+ *
+ * Returned Value:
+ * Return 0 on success. Otherwise, return a negated errno.
+ *
+ ****************************************************************************/
+
+int cxd56_charger_initialize(FAR const char *devpath)
+{
+ FAR struct charger_dev_s *priv = &g_chargerdev;
+ int ret;
+
+ /* Initialize the CXD5247 device structure */
+
+ sem_init(&priv->batsem, 0, 1);
+
+ /* Register battery driver */
+
+ ret = register_driver(devpath, &g_chargerops, 0666, priv);
+ if (ret < 0)
+ {
+ _err("ERROR: register_driver failed: %d\n", ret);
+ return -EFAULT;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_charger_uninitialize
+ *
+ * Description:
+ * Uninitialize the CXD5247 battery charger driver.
+ *
+ * Input Parameters:
+ * devpath - Device file path
+ *
+ * Returned Value:
+ * Return 0 on success. Otherwise, return a negated errno.
+ *
+ ****************************************************************************/
+
+int cxd56_charger_uninitialize(FAR const char *devpath)
+{
+ (void) unregister_driver(devpath);
+
+ return OK;
+}
+
+#endif /* CONFIG_CXD56_CHARGER */
diff --git a/arch/arm/src/cxd56xx/cxd56_charger.h b/arch/arm/src/cxd56xx/cxd56_charger.h
new file mode 100644
index 00000000000..8c5f7a7b5af
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_charger.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_charger.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_CHARGER_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_CHARGER_H
+
+/* initialize function */
+
+int cxd56_charger_initialize(FAR const char *devpath);
+int cxd56_charger_uninitialize(FAR const char *devpath);
+
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_CHARGER_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_cisif.c b/arch/arm/src/cxd56xx/cxd56_cisif.c
new file mode 100644
index 00000000000..d7f04d11d6d
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_cisif.c
@@ -0,0 +1,910 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_cisif.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include "up_arch.h"
+
+#include "cxd56_clock.h"
+#include "hardware/cxd56_cisif.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* To see the interrupt timing of Vsync */
+
+/* #define CISIF_INTR_TRACE */
+
+/* #define CISIF_DBG_CONTI_CAP */
+
+#define YUV_VSIZE_MIN (64)
+#define YUV_HSIZE_MIN (96)
+#define YUV_VSIZE_MAX (360)
+#define YUV_HSIZE_MAX (480)
+
+#define JPG_INT_ALL (JPG_ERR_STATUS_INT | \
+ JPG_MEM_OVF_INT | \
+ JPG_FIFO_OVF_INT | \
+ JPG_AXI_TRERR_INT | \
+ JPG_MARKER_ERR_INT | \
+ JPG_AXI_TRDN_INT)
+
+#define YCC_INT_ALL (YCC_MEM_OVF_INT | \
+ YCC_FIFO_OVF_INT | \
+ YCC_AXI_TRERR_INT | \
+ YCC_MARKER_ERR_INT | \
+ SIZE_UNDER_INT | \
+ SIZE_OVER_INT | \
+ YCC_AXI_TRDN_INT)
+
+/* YUV data size with frame v * h */
+
+#define YUV_SIZE(v, h) (v * h * 2)
+
+/* Check Buffer address alignement */
+
+#define CISIF_BUFADDR_ALIGNMENT (32)
+#define ILLEGAL_BUFADDR_ALIGNMENT(addr) (((addr) == NULL) || \
+ (((uint32_t)(addr) % \
+ CISIF_BUFADDR_ALIGNMENT) != 0))
+
+#ifdef CONFIG_CXD56_CISIF_DEBUG
+#define ciferr _err
+#define cifwarn _warn
+#define cifinfo _info
+#else
+#define ciferr(x...)
+#define cifwarn(x...)
+#define cifinfo(x...)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+enum state_e
+{
+ STATE_STANDBY,
+ STATE_READY,
+ STATE_CAPTURE,
+};
+
+typedef enum state_e state_t;
+
+typedef void (*intc_func_table)(uint8_t code);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static state_t g_state = STATE_STANDBY;
+static uint32_t g_storage_addr = 0;
+
+notify_callback_t g_jpg_notify_callback_func;
+notify_callback_t g_ycc_notify_callback_func;
+comp_callback_t g_comp_callback_func;
+
+static bool g_jpgint_receive;
+static bool g_errint_receive;
+
+#ifdef CISIF_INTR_TRACE
+static uint32_t g_cisif_vint_count = 0;
+static uint32_t g_cisif_vint_count_max = 0;
+static uint32_t g_cisif_time_start;
+static uint32_t g_cisif_time_stop;
+#endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void cisif_vs_int(uint8_t code);
+static void cisif_ycc_axi_trdn_int(uint8_t code);
+static void cisif_ycc_nstorage_int(uint8_t code);
+static void cisif_jpg_axi_trdn_int(uint8_t code);
+static void cisif_jpg_nstorage_int(uint8_t code);
+static void cisif_ycc_err_int(uint8_t code);
+static void cisif_jpg_err_int(uint8_t code);
+
+static void cisif_reg_write(uint16_t reg, uint32_t val);
+static uint32_t cisif_reg_read(uint16_t reg);
+
+static int cisif_check_param(cisif_param_t *p);
+static int cisif_set_yuv_param(cisif_param_t *p);
+static int cisif_set_jpg_param(cisif_param_t *p);
+
+static int cisif_check_sarea(void *s);
+static int cisif_set_yuv_sarea(void *s);
+static int cisif_set_jpg_sarea(void *s);
+static int cisif_set_intlev_sarea(void *s, uint32_t yuv_size);
+
+int cisif_intc_handler(int irq, FAR void *context, FAR void *arg);
+
+const intc_func_table g_intcomp_func[] =
+ {
+ cisif_vs_int, /* VS_INT */
+ NULL, /* EOY_INT */
+ NULL, /* SOY_INT */
+ NULL, /* EOI_INT */
+ NULL, /* SOI_INT */
+ NULL, /* YCC_VACT_END_INT */
+ NULL, /* JPG_VACT_END_INT */
+ cisif_ycc_axi_trdn_int, /* YCC_AXI_TRDN_INT */
+ cisif_ycc_nstorage_int, /* YCC_NSTORAGE_INT */
+ NULL, /* YCC_DAREA_END_INT */
+ cisif_jpg_axi_trdn_int, /* JPG_AXI_TRDN_INT */
+ cisif_jpg_nstorage_int, /* JPG_NSTORAGE_INT */
+ NULL, /* JPG_DAREA_END_INT */
+ NULL, /* reserve */
+ NULL, /* reserve */
+ NULL, /* VLATCH_INT */
+ cisif_ycc_err_int, /* SIZE_OVER_INT */
+ cisif_ycc_err_int, /* SIZE_UNDER_INT */
+ cisif_ycc_err_int, /* YCC_MARKER_ERR_INT */
+ cisif_ycc_err_int, /* YCC_AXI_TRERR_INT */
+ cisif_ycc_err_int, /* YCC_FIFO_OVF_INT */
+ cisif_ycc_err_int, /* YCC_MEM_OVF_INT */
+ NULL, /* reserve */
+ NULL, /* reserve */
+ cisif_jpg_err_int, /* JPG_MARKER_ERR_INT */
+ cisif_jpg_err_int, /* JPG_AXI_TRERR_INT */
+ cisif_jpg_err_int, /* JPG_FIFO_OVF_INT */
+ cisif_jpg_err_int, /* JPG_MEM_OVF_INT */
+ cisif_jpg_err_int, /* JPG_ERR_STATUS_INT */
+ };
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifdef CISIF_INTR_TRACE
+static uint64_t cisif_get_msec_time(void)
+{
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_REALTIME, &tp))
+ {
+ return 0;
+ }
+ return (((uint64_t)tp.tv_sec) * 1000 + tp.tv_nsec / 1000000);
+}
+
+static void cisif_trace_time_start(void)
+{
+ g_cisif_time_start = (uint32_t)cisif_get_msec_time();
+}
+
+static void cisif_trace_time_stop(char *str)
+{
+ g_cisif_time_stop = (uint32_t)cisif_get_msec_time();
+ printf("%s:%d[ms]\n", str, (uint32_t)(g_cisif_time_stop -
+ g_cisif_time_start));
+}
+
+void cisif_intrtrace_start(int max)
+{
+ g_cisif_vint_count_max = max;
+ g_cisif_vint_count = 0;
+ cisif_trace_time_start();
+}
+#endif
+
+/****************************************************************************
+ * cisif_vs_int
+ ****************************************************************************/
+
+static void cisif_vs_int(uint8_t code)
+{
+#ifdef CISIF_INTR_TRACE
+ if (g_cisif_vint_count < g_cisif_vint_count_max)
+ {
+ cisif_trace_time_stop("cisif_vs_int");
+ cisif_trace_time_start();
+ g_cisif_vint_count++;
+ }
+ else
+ {
+ g_cisif_vint_count_max = 0;
+ }
+#endif
+
+ switch (g_state)
+ {
+ case STATE_STANDBY:
+ cifinfo("invalid state\n");
+ break;
+
+ case STATE_READY:
+ g_errint_receive = false;
+ break;
+
+ case STATE_CAPTURE:
+ g_errint_receive = false;
+ break;
+
+ default:
+ cifinfo("invalid state\n");
+ break;
+ }
+}
+
+/****************************************************************************
+ * cisif_callback_for_intlev
+ ****************************************************************************/
+
+static void cisif_callback_for_intlev(uint8_t code)
+{
+ uint32_t size;
+ uint32_t yuv_size;
+
+ if (!g_jpgint_receive)
+ {
+ /* In either YUV or JPEG is not received,
+ * wait receiving.
+ */
+
+ g_jpgint_receive = true;
+ return;
+ }
+
+ /* Read received data size */
+
+ yuv_size = cisif_reg_read(CISIF_YCC_DSTRG_CONT);
+ size = yuv_size + cisif_reg_read(CISIF_JPG_DSTRG_CONT);
+
+ /* Notify and get next addr */
+
+ g_comp_callback_func(0, size, g_storage_addr);
+
+ g_jpgint_receive = false;
+
+ cisif_reg_write(CISIF_EXE_CMD, 1);
+ cisif_reg_write(CISIF_YCC_DREAD_CONT, 0);
+ cisif_reg_write(CISIF_JPG_DREAD_CONT, 0);
+
+ return;
+}
+
+/****************************************************************************
+ * cisif_ycc_axi_trdn_int
+ ****************************************************************************/
+static void cisif_ycc_axi_trdn_int(uint8_t code)
+{
+ uint32_t size;
+ uint32_t cisif_mode;
+
+#ifdef CISIF_INTR_TRACE
+ cisif_trace_time_stop("cisif_ycc_axi_trdn_int");
+#endif
+
+ if (g_errint_receive)
+ {
+ /* In error occured case in the same frame, ignore */
+
+ cisif_reg_write(CISIF_YCC_DREAD_CONT, 0);
+ return;
+ }
+
+ cisif_mode = cisif_reg_read(CISIF_MODE);
+ if (cisif_mode == MODE_INTLEV_TRS_EN)
+ {
+ /* In JPEG + YUV format case */
+
+ cisif_callback_for_intlev(code);
+ }
+ else
+ {
+ size = cisif_reg_read(CISIF_YCC_DSTRG_CONT);
+ g_comp_callback_func(0, size, g_storage_addr);
+ cisif_reg_write(CISIF_YCC_DREAD_CONT, 0);
+ }
+}
+
+/****************************************************************************
+ * cisif_ycc_nstorage_int
+ ****************************************************************************/
+
+static void cisif_ycc_nstorage_int(uint8_t code)
+{
+ uint32_t size;
+
+ size = cisif_reg_read(CISIF_YCC_DSTRG_CONT);
+ g_ycc_notify_callback_func (0, size, g_storage_addr);
+ cisif_reg_write(CISIF_YCC_DREAD_CONT, size);
+}
+
+/****************************************************************************
+ * cisif_jpg_axi_trdn_int
+ ****************************************************************************/
+
+static void cisif_jpg_axi_trdn_int(uint8_t code)
+{
+ uint32_t size;
+ uint32_t cisif_mode;
+
+#ifdef CISIF_INTR_TRACE
+ cisif_trace_time_stop("cisif_jpg_axi_trdn_int");
+#endif
+
+ if (g_errint_receive)
+ {
+ /* In error occured case in the same frame, ignore */
+
+ cisif_reg_write(CISIF_JPG_DREAD_CONT, 0);
+ return;
+ }
+
+ cisif_mode = cisif_reg_read(CISIF_MODE);
+
+ if (cisif_mode == MODE_INTLEV_TRS_EN)
+ {
+ /* In JPEG + YUV format case */
+
+ cisif_callback_for_intlev(code);
+ }
+ else
+ {
+ size = cisif_reg_read(CISIF_JPG_DSTRG_CONT);
+ g_comp_callback_func(0, size, g_storage_addr);
+ cisif_reg_write(CISIF_JPG_DREAD_CONT, 0);
+ }
+}
+
+/****************************************************************************
+ * cisif_jpg_nstorage_int
+ ****************************************************************************/
+
+static void cisif_jpg_nstorage_int(uint8_t code)
+{
+ uint32_t size;
+
+ size = cisif_reg_read(CISIF_JPG_DSTRG_CONT);
+
+ g_jpg_notify_callback_func(0, size, g_storage_addr);
+ cisif_reg_write(CISIF_JPG_DREAD_CONT, size);
+}
+
+/****************************************************************************
+ * cisif_ycc_err_int
+ ****************************************************************************/
+
+static void cisif_ycc_err_int(uint8_t code)
+{
+ uint32_t size;
+
+#ifdef CISIF_INTR_TRACE
+ cisif_trace_time_stop("cisif_ycc_err_int");
+#endif
+
+ size = cisif_reg_read(CISIF_YCC_DSTRG_CONT);
+ g_comp_callback_func(code, size, g_storage_addr);
+ cisif_reg_write(CISIF_YCC_DREAD_CONT, 0);
+ g_errint_receive = true;
+}
+
+/****************************************************************************
+ * cisif_jpg_err_int
+ ****************************************************************************/
+
+static void cisif_jpg_err_int(uint8_t code)
+{
+ uint32_t size;
+ uint32_t addr;
+
+#ifdef CISIF_INTR_TRACE
+ cisif_trace_time_stop("cisif_jpg_err_int");
+#endif
+
+ addr = g_storage_addr;
+
+ size = cisif_reg_read(CISIF_JPG_DSTRG_CONT);
+ g_comp_callback_func(code, size, addr);
+ cisif_reg_write(CISIF_JPG_DREAD_CONT, 0);
+ g_errint_receive = true;
+}
+
+/****************************************************************************
+ * cisif_intc_handler
+ ****************************************************************************/
+
+int cisif_intc_handler(int irq, FAR void *context, FAR void *arg)
+{
+ uint32_t value;
+ uint32_t enable;
+ uint8_t index;
+
+ value = cisif_reg_read(CISIF_INTR_STAT);
+ cisif_reg_write(CISIF_INTR_CLEAR, value & ALL_CLEAR_INT);
+ cifinfo("int stat %08x\n", value);
+
+ enable = cisif_reg_read(CISIF_INTR_ENABLE);
+ value = (value & enable);
+
+ for (index = 0;
+ index < sizeof(g_intcomp_func) / sizeof(g_intcomp_func[0]);
+ index++)
+ {
+ if ((value & (1 << index)) != 0)
+ {
+ g_intcomp_func[index](index);
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * cisif_reg_write
+ ****************************************************************************/
+
+static void cisif_reg_write(uint16_t reg, uint32_t val)
+{
+ putreg32(val, CXD56_CISIF_BASE + reg);
+}
+
+/****************************************************************************
+ * cisif_reg_read
+ ****************************************************************************/
+
+static uint32_t cisif_reg_read(uint16_t reg)
+{
+ return getreg32(CXD56_CISIF_BASE + reg);
+}
+
+/****************************************************************************
+ * cisif_check_param
+ ****************************************************************************/
+
+static int cisif_check_param(cisif_param_t *p)
+{
+ if (p == NULL)
+ {
+ return -EINVAL;
+ }
+
+ if (p->comp_func == NULL)
+ {
+ return -EINVAL;
+ }
+
+ switch (p->format)
+ {
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_JPEG:
+ case V4L2_PIX_FMT_JPEG_WITH_SUBIMG:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (p->format != V4L2_PIX_FMT_JPEG)
+ {
+ if (p->yuv_param.hsize < YUV_HSIZE_MIN ||
+ p->yuv_param.hsize > YUV_HSIZE_MAX ||
+ p->yuv_param.vsize < YUV_VSIZE_MIN ||
+ p->yuv_param.vsize > YUV_VSIZE_MAX)
+ {
+ return -EINVAL;
+ }
+
+ if (p->yuv_param.notify_func != NULL)
+ {
+ if (p->yuv_param.notify_size == 0)
+ {
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (p->format != V4L2_PIX_FMT_UYVY)
+ {
+ if (p->jpg_param.notify_func != NULL)
+ {
+ if (p->jpg_param.notify_size == 0)
+ {
+ return -EINVAL;
+ }
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * cisif_check_sarea
+ ****************************************************************************/
+
+static int cisif_check_sarea(void *s)
+{
+ if (s == NULL)
+ {
+ return -EINVAL;
+ }
+
+ cisif_sarea_t *ss = (cisif_sarea_t *)s;
+ if (ILLEGAL_BUFADDR_ALIGNMENT(ss->strg_addr) ||
+ ss->strg_size == 0)
+ {
+ return -EINVAL;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * cisif_set_yuvparam
+ ****************************************************************************/
+
+static int cisif_set_yuv_param(cisif_param_t *p)
+{
+ uint32_t act_size = 0;
+
+ act_size = (p->yuv_param.vsize & 0x1ff) << 16;
+ act_size |= p->yuv_param.hsize & 0x1ff;
+
+ cisif_reg_write(CISIF_ACT_SIZE, act_size);
+ cisif_reg_write(CISIF_CIS_SIZE, act_size);
+
+ /* must align 32 bytes */
+
+ cisif_reg_write(CISIF_YCC_NSTRG_SIZE, (p->yuv_param.notify_size
+ & 0xffffffe0));
+
+ g_ycc_notify_callback_func = p->yuv_param.notify_func;
+
+ return OK;
+}
+
+/****************************************************************************
+ * cisif_set_yuvsarea
+ ****************************************************************************/
+
+static int cisif_set_yuv_sarea(void *s)
+{
+ cisif_sarea_t *ss = (cisif_sarea_t *)s;
+
+ /* must align 32 bytes */
+
+ cisif_reg_write(CISIF_YCC_DAREA_SIZE, (ss->strg_size & 0xffffffe0));
+ cisif_reg_write(CISIF_YCC_START_ADDR, (uint32_t)ss->strg_addr);
+
+ return OK;
+}
+
+/****************************************************************************
+ * cisif_set_jpg_param
+ ****************************************************************************/
+
+static int cisif_set_jpg_param(cisif_param_t *p)
+{
+ /* must align 32 bytes */
+
+ cisif_reg_write(CISIF_JPG_NSTRG_SIZE, (p->jpg_param.notify_size
+ & 0xffffffe0));
+
+ g_jpg_notify_callback_func = p->jpg_param.notify_func;
+
+ return OK;
+}
+
+/****************************************************************************
+ * cisif_set_jpg_sarea
+ ****************************************************************************/
+
+static int cisif_set_jpg_sarea(void *s)
+{
+ cisif_sarea_t *ss = (cisif_sarea_t *)s;
+
+ /* must align 32 bytes */
+
+ cisif_reg_write(CISIF_JPG_DAREA_SIZE, (ss->strg_size & 0xffffffe0));
+ cisif_reg_write(CISIF_JPG_START_ADDR, (uint32_t)ss->strg_addr);
+
+ return OK;
+}
+
+/****************************************************************************
+ * cisif_set_jpg_sarea
+ ****************************************************************************/
+
+static int cisif_set_intlev_sarea(void *s, uint32_t yuv_size)
+{
+ cisif_sarea_t *sarea = (cisif_sarea_t *)s;
+ cisif_sarea_t sarea_int;
+
+ if (sarea->strg_size < yuv_size)
+ {
+ return -EINVAL;
+ }
+
+ /* Set for YUV */
+
+ sarea_int.strg_addr = sarea->strg_addr;
+ sarea_int.strg_size = yuv_size;
+ cisif_set_yuv_sarea(&sarea_int);
+
+ /* Set for JPEG */
+
+ sarea_int.strg_addr = sarea->strg_addr + yuv_size;
+ sarea_int.strg_size = sarea->strg_size - yuv_size;
+
+ cisif_set_jpg_sarea(&sarea_int);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * cxd56_cisifinit
+ ****************************************************************************/
+
+int cxd56_cisifinit(void)
+{
+ if (g_state != STATE_STANDBY)
+ {
+ return -EPERM;
+ }
+
+ /* enable CISIF clock */
+
+ cxd56_img_cisif_clock_enable();
+
+ /* disable CISIF interrupt */
+
+ cisif_reg_write(CISIF_INTR_DISABLE, ALL_CLEAR_INT);
+ cisif_reg_write(CISIF_INTR_CLEAR, ALL_CLEAR_INT);
+
+ /* attach interrupt handler */
+
+ irq_attach(CXD56_IRQ_CISIF, cisif_intc_handler, NULL);
+
+ /* enable CISIF irq */
+
+ up_enable_irq(CXD56_IRQ_CISIF);
+
+#ifdef CISIF_INTR_TRACE
+ cisif_reg_write(CISIF_INTR_ENABLE, VS_INT);
+#endif
+
+ g_state = STATE_READY;
+
+ return OK;
+}
+
+/****************************************************************************
+ * cxd56_cisiffinalize
+ ****************************************************************************/
+
+int cxd56_cisiffinalize(void)
+{
+ if (g_state != STATE_READY)
+ {
+ return -EPERM;
+ }
+
+ /* disable CISIF irq */
+
+ up_disable_irq(CXD56_IRQ_CISIF);
+
+ /* detach interrupt handler */
+
+ irq_detach(CXD56_IRQ_CISIF);
+
+ /* disable CISIF interrupt */
+
+ cisif_reg_write(CISIF_INTR_DISABLE, ALL_CLEAR_INT);
+ cisif_reg_write(CISIF_INTR_CLEAR, ALL_CLEAR_INT);
+
+ /* disable CISIF clock */
+
+ cxd56_img_cisif_clock_disable();
+
+ g_state = STATE_STANDBY;
+
+ return OK;
+}
+
+/****************************************************************************
+ * cxd56_cisifstartcapturing
+ ****************************************************************************/
+
+int cxd56_cisifstartcapture(
+ cisif_param_t *param,
+ cisif_sarea_t *sarea)
+{
+ uint32_t cisif_mode;
+ uint32_t interrupts = VS_INT;
+ int ret;
+
+ if (g_state != STATE_READY)
+ {
+ return -EPERM;
+ }
+
+ ret = cisif_check_param(param);
+ if (ret != OK)
+ {
+ return ret;
+ }
+
+ cisif_reg_write(CISIF_INTR_DISABLE, ALL_CLEAR_INT);
+
+ ret = cisif_check_sarea(sarea);
+ if (ret != OK)
+ {
+ return ret;
+ }
+
+ switch (param->format)
+ {
+ case V4L2_PIX_FMT_UYVY:
+ cisif_set_yuv_param(param);
+ cisif_set_yuv_sarea(sarea);
+
+ cisif_mode = MODE_YUV_TRS_EN;
+ interrupts |= YCC_INT_ALL;
+ break;
+
+ case V4L2_PIX_FMT_JPEG:
+ cisif_set_jpg_param(param);
+ cisif_set_jpg_sarea(sarea);
+
+ cisif_mode = MODE_JPG_TRS_EN;
+ interrupts |= JPG_INT_ALL;
+ break;
+
+ case V4L2_PIX_FMT_JPEG_WITH_SUBIMG:
+ cisif_set_yuv_param(param);
+ cisif_set_jpg_param(param);
+
+ cisif_set_intlev_sarea(sarea,
+ YUV_SIZE(param->yuv_param.vsize,
+ param->yuv_param.hsize));
+
+ cisif_mode = MODE_INTLEV_TRS_EN;
+ interrupts |= YCC_INT_ALL | JPG_INT_ALL;
+ g_jpgint_receive = false;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ g_comp_callback_func = param->comp_func;
+ g_storage_addr = (uint32_t)sarea->strg_addr;
+
+ g_state = STATE_CAPTURE;
+
+ if (g_ycc_notify_callback_func != NULL)
+ {
+ interrupts |= YCC_NSTORAGE_INT;
+ }
+
+ if (g_jpg_notify_callback_func != NULL)
+ {
+ interrupts |= JPG_NSTORAGE_INT;
+ }
+
+ cisif_reg_write(CISIF_MODE, cisif_mode);
+ cisif_reg_write(CISIF_INTR_CLEAR, interrupts);
+ cisif_reg_write(CISIF_INTR_ENABLE, interrupts);
+
+ cisif_reg_write(CISIF_DIN_ENABLE, 1);
+ cisif_reg_write(CISIF_EXE_CMD, 1);
+
+ return OK;
+}
+
+int cxd56_cisifstopcapture(void)
+{
+ g_state = STATE_READY;
+ cisif_reg_write(CISIF_DIN_ENABLE, 0);
+ cisif_reg_write(CISIF_INTR_DISABLE, ALL_CLEAR_INT);
+ cisif_reg_write(CISIF_EXE_CMD, 1);
+
+ return OK;
+}
+
+int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea)
+{
+ int ret;
+ uint32_t cisif_mode;
+ uint32_t yuv_regsize;
+ uint32_t yuv_hsize;
+ uint32_t yuv_vsize;
+
+ ret = cisif_check_sarea(sarea);
+ if (ret != OK)
+ {
+ return ret;
+ }
+
+ cisif_mode = cisif_reg_read(CISIF_MODE);
+
+ switch (cisif_mode)
+ {
+ case MODE_YUV_TRS_EN:
+ ret = cisif_set_yuv_sarea(sarea);
+ break;
+
+ case MODE_JPG_TRS_EN:
+ ret = cisif_set_jpg_sarea(sarea);
+ break;
+
+ default: /* MODE_INTLEV_TRS_EN */
+
+ /* Get YUV frame size information */
+
+ yuv_regsize = cisif_reg_read(CISIF_ACT_SIZE);
+ yuv_vsize = (yuv_regsize >> 16) & 0x1ff;
+ yuv_hsize = yuv_regsize & 0x01ff;
+
+ ret = cisif_set_intlev_sarea(sarea,
+ YUV_SIZE(yuv_vsize, yuv_hsize));
+ break;
+ }
+
+ if (ret != OK)
+ {
+ return ret;
+ }
+
+ cisif_reg_write(CISIF_EXE_CMD, 1);
+ g_storage_addr = (uint32_t)sarea->strg_addr;
+
+ return ret;
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_clock.c b/arch/arm/src/cxd56xx/cxd56_clock.c
index ecdc5c3b9b9..796f6fcd92c 100644
--- a/arch/arm/src/cxd56xx/cxd56_clock.c
+++ b/arch/arm/src/cxd56xx/cxd56_clock.c
@@ -97,10 +97,9 @@
#ifndef CONFIG_CXD56_UART2_BASE_CLOCK_DIVIDER
#define CONFIG_CXD56_UART2_BASE_CLOCK_DIVIDER 4
-#endif /* CONFIG_CXD56_UART2_BASE_CLOCK_DIVIDER */
+#endif
-/*
- * Flags for IMG device active
+/* Flags for IMG device active
*
* This flags for fixed clock devices.
*/
@@ -139,10 +138,14 @@ struct power_domain
static void cxd56_img_clock_enable(void);
static void cxd56_img_clock_disable(void);
-static void cxd56_scu_clock_ctrl(uint32_t block, uint32_t intr, int on);
-static void cxd56_scu_peri_clock_enable(FAR const struct scu_peripheral *p) __unused;
-static void cxd56_scu_peri_clock_disable(FAR const struct scu_peripheral *p) __unused;
-static void cxd56_scu_peri_clock_gating(FAR const struct scu_peripheral *p, int enable) __unused;
+static void cxd56_scu_clock_ctrl(\
+ uint32_t block, uint32_t intr, int on);
+static void cxd56_scu_peri_clock_enable(\
+ FAR const struct scu_peripheral *p) __unused;
+static void cxd56_scu_peri_clock_disable(\
+ FAR const struct scu_peripheral *p) __unused;
+static void cxd56_scu_peri_clock_gating(\
+ FAR const struct scu_peripheral *p, int enable) __unused;
/****************************************************************************
* Public Data
@@ -286,7 +289,7 @@ static inline void release_pwd_reset(uint32_t domain)
{
/* Release power domain reset */
- putreg32(domain | domain <<16, CXD56_TOPREG_PWD_RESET0);
+ putreg32(domain | domain << 16, CXD56_TOPREG_PWD_RESET0);
}
}
@@ -298,7 +301,7 @@ static void enable_pwd(int pdid)
stat = getreg32(CXD56_TOPREG_PWD_STAT);
if ((stat & domain) != domain)
{
- putreg32((domain|(domain<<16)), CXD56_TOPREG_PWD_CTL);
+ putreg32((domain | (domain << 16)), CXD56_TOPREG_PWD_CTL);
do_power_control();
release_pwd_reset(domain);
}
@@ -316,7 +319,7 @@ static void disable_pwd(int pdid)
g_digital.refs[pdid]--;
if (g_digital.refs[pdid] == 0)
{
- putreg32(domain<<16, CXD56_TOPREG_PWD_CTL);
+ putreg32(domain << 16, CXD56_TOPREG_PWD_CTL);
do_power_control();
}
}
@@ -330,7 +333,7 @@ static void enable_apwd(int apdid)
stat = getreg32(CXD56_TOPREG_ANA_PW_STAT);
if ((stat & domain) != domain)
{
- putreg32(domain|(domain<<16), CXD56_TOPREG_ANA_PW_CTL);
+ putreg32(domain | (domain << 16), CXD56_TOPREG_ANA_PW_CTL);
do_power_control();
}
g_analog.refs[apdid]++;
@@ -347,7 +350,7 @@ static void disable_apwd(int apdid)
g_analog.refs[apdid]--;
if (g_analog.refs[apdid] == 0)
{
- putreg32(domain<<16, CXD56_TOPREG_ANA_PW_CTL);
+ putreg32(domain << 16, CXD56_TOPREG_ANA_PW_CTL);
do_power_control();
}
}
@@ -419,7 +422,8 @@ void cxd56_xosc_disable(void)
void cxd56_spif_clock_enable(void)
{
- uint32_t val, rst;
+ uint32_t val;
+ uint32_t rst;
val = getreg32(CXD56_TOPREG_SYSIOP_SUB_CKEN);
if (val & CK_SFC)
@@ -446,7 +450,8 @@ void cxd56_spif_clock_enable(void)
void cxd56_spif_clock_disable(void)
{
- uint32_t val, rst;
+ uint32_t val;
+ uint32_t rst;
val = getreg32(CXD56_TOPREG_SYSIOP_SUB_CKEN);
if (!(val & CK_SFC))
@@ -470,7 +475,8 @@ void cxd56_spif_clock_disable(void)
uint32_t cxd56_get_cpu_baseclk(void)
{
uint32_t val;
- int n, m;
+ int n;
+ int m;
val = getreg32(CXD56_CRG_GEAR_AHB);
n = (val >> 16) & 0x7f;
@@ -507,7 +513,8 @@ void cxd56_cpu_clock_enable(int cpu)
void cxd56_cpulist_clock_enable(uint32_t cpus)
{
- uint32_t c, bits = (cpus & 0x3f) << 16;
+ uint32_t c;
+ uint32_t bits = (cpus & 0x3f) << 16;
c = getreg32(CXD56_CRG_CK_GATE_AHB);
putreg32(c | bits, CXD56_CRG_CK_GATE_AHB);
@@ -534,7 +541,8 @@ void cxd56_cpu_clock_disable(int cpu)
void cxd56_cpulist_clock_disable(uint32_t cpus)
{
- uint32_t c, bits = (cpus & 0x3f) << 16;
+ uint32_t c;
+ uint32_t bits = (cpus & 0x3f) << 16;
c = getreg32(CXD56_CRG_CK_GATE_AHB);
putreg32(c & ~bits, CXD56_CRG_CK_GATE_AHB);
@@ -561,7 +569,9 @@ void cxd56_cpu_reset(int cpu)
void cxd56_cpulist_reset(uint32_t cpus)
{
- uint32_t c, r, bits = (cpus & 0x3f) << 16;
+ uint32_t c;
+ uint32_t r;
+ uint32_t bits = (cpus & 0x3f) << 16;
/* Reset assert */
@@ -589,7 +599,8 @@ void cxd56_cpulist_reset(uint32_t cpus)
void cxd56_usb_clock_enable(void)
{
- uint32_t c, r;
+ uint32_t c;
+ uint32_t r;
enable_pwd(PDID_APP_SUB);
@@ -615,7 +626,8 @@ void cxd56_usb_clock_enable(void)
void cxd56_usb_clock_disable(void)
{
- uint32_t c, r;
+ uint32_t c;
+ uint32_t r;
c = getreg32(CXD56_CRG_CK_GATE_AHB);
if (c & CK_GATE_USB)
@@ -639,7 +651,9 @@ void cxd56_usb_clock_disable(void)
void cxd56_emmc_clock_enable(uint32_t div, uint32_t driver, uint32_t sample)
{
- uint32_t c, r, g;
+ uint32_t c;
+ uint32_t r;
+ uint32_t g;
enable_pwd(PDID_APP_SUB);
@@ -686,7 +700,9 @@ void cxd56_emmc_clock_enable(uint32_t div, uint32_t driver, uint32_t sample)
void cxd56_emmc_clock_disable(void)
{
- uint32_t c, r, g;
+ uint32_t c;
+ uint32_t r;
+ uint32_t g;
c = getreg32(CXD56_CRG_CKEN_EMMC);
if (c != 7)
@@ -699,7 +715,7 @@ void cxd56_emmc_clock_disable(void)
putreg32(0, CXD56_CRG_CKEN_EMMC);
r = getreg32(CXD56_CRG_RESET);
- putreg32(r & ~(XRS_MMC|XRS_MMC_CRG), CXD56_CRG_RESET);
+ putreg32(r & ~(XRS_MMC | XRS_MMC_CRG), CXD56_CRG_RESET);
disable_pwd(PDID_APP_SUB);
}
@@ -713,7 +729,8 @@ void cxd56_emmc_clock_disable(void)
void cxd56_sdio_clock_enable(void)
{
- uint32_t c, r;
+ uint32_t c;
+ uint32_t r;
enable_pwd(PDID_APP_SUB);
@@ -738,7 +755,8 @@ void cxd56_sdio_clock_enable(void)
void cxd56_sdio_clock_disable(void)
{
- uint32_t c, r;
+ uint32_t c;
+ uint32_t r;
c = getreg32(CXD56_CRG_CK_GATE_AHB);
if (c & CK_GATE_SDIO)
@@ -814,7 +832,8 @@ bool cxd56_audio_clock_is_enabled(void)
static void cxd56_spim_clock_enable(void)
{
- uint32_t val, rst;
+ uint32_t val;
+ uint32_t rst;
val = getreg32(CXD56_TOPREG_SYSIOP_SUB_CKEN);
if (val & CK_SPIM)
@@ -822,14 +841,16 @@ static void cxd56_spim_clock_enable(void)
return;
}
- putreg32(val | CK_SPIM | CK_COM_BRG | CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
+ putreg32(val | CK_SPIM | CK_COM_BRG |
+ CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
busy_wait(10);
putreg32(val | CK_COM_BRG | CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
rst = getreg32(CXD56_TOPREG_SWRESET_BUS);
putreg32(rst | XRST_SPIM, CXD56_TOPREG_SWRESET_BUS);
- putreg32(val | CK_SPIM | CK_COM_BRG | CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
+ putreg32(val | CK_SPIM | CK_COM_BRG |
+ CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
}
/****************************************************************************
@@ -842,7 +863,9 @@ static void cxd56_spim_clock_enable(void)
static void cxd56_spim_clock_disable(void)
{
- uint32_t val, rst, mask;
+ uint32_t val;
+ uint32_t rst;
+ uint32_t mask;
val = getreg32(CXD56_TOPREG_SYSIOP_SUB_CKEN);
if (!(val & CK_SPIM))
@@ -1095,7 +1118,8 @@ void cxd56_spi_clock_gear_adjust(int port, uint32_t maxfreq)
static void cxd56_i2cm_clock_enable(void)
{
- uint32_t val, rst;
+ uint32_t val;
+ uint32_t rst;
val = getreg32(CXD56_TOPREG_SYSIOP_SUB_CKEN);
if (val & CK_I2CM)
@@ -1103,14 +1127,16 @@ static void cxd56_i2cm_clock_enable(void)
return;
}
- putreg32(val | CK_I2CM | CK_COM_BRG | CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
+ putreg32(val | CK_I2CM | CK_COM_BRG |
+ CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
busy_wait(10);
putreg32(val | CK_COM_BRG | CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
rst = getreg32(CXD56_TOPREG_SWRESET_BUS);
putreg32(rst | XRST_I2CM, CXD56_TOPREG_SWRESET_BUS);
- putreg32(val | CK_I2CM | CK_COM_BRG | CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
+ putreg32(val | CK_I2CM | CK_COM_BRG |
+ CK_AHB_BRG_COMIF, CXD56_TOPREG_SYSIOP_SUB_CKEN);
}
/****************************************************************************
@@ -1122,7 +1148,9 @@ static void cxd56_i2cm_clock_enable(void)
static void cxd56_i2cm_clock_disable(void)
{
- uint32_t val, rst, mask;
+ uint32_t val;
+ uint32_t rst;
+ uint32_t mask;
val = getreg32(CXD56_TOPREG_SYSIOP_SUB_CKEN);
if (!(val & CK_I2CM))
@@ -1249,7 +1277,8 @@ void cxd56_i2c_clock_gate_disable(int port)
uint32_t cxd56_get_img_uart_baseclock(void)
{
uint32_t val;
- int n, m;
+ int n;
+ int m;
val = getreg32(CXD56_CRG_GEAR_IMG_UART);
n = (val >> 16) & 1;
@@ -1412,7 +1441,9 @@ static uint32_t cxd56_get_clock(enum clock_source cs)
return CONFIG_CXD56_XOSC_CLOCK;
case SYSPLL:
{
- uint32_t ctrl, rc, fb;
+ uint32_t ctrl;
+ uint32_t rc;
+ uint32_t fb;
ctrl = getreg32(CXD56_TOPREG_SYS_PLL_CTRL2);
rc = ctrl >> 30;
@@ -1466,7 +1497,7 @@ uint32_t cxd56_get_sys_baseclock(void)
{
uint32_t div = ((val >> 10) & 0x3) + 1;
- if (div == 4 && (val & (1<<2)))
+ if (div == 4 && (val & (1 << 2)))
{
div = 5;
}
@@ -1525,7 +1556,7 @@ uint32_t cxd56_get_appsmp_baseclock(void)
{
uint32_t div = ((val >> 10) & 0x3) + 1;
- if (div == 4 && (val & (1<<7)))
+ if (div == 4 && (val & (1 << 7)))
{
div = 5;
}
@@ -1554,7 +1585,8 @@ uint32_t cxd56_get_com_baseclock(void)
uint32_t cxd56_get_sdio_baseclock(void)
{
uint32_t val;
- int n, m;
+ int n;
+ int m;
val = getreg32(CXD56_CRG_GEAR_PER_SDIO);
n = (val >> 16) & 1;
@@ -1573,7 +1605,8 @@ uint32_t cxd56_get_sdio_baseclock(void)
uint32_t cxd56_get_img_spi_baseclock(void)
{
uint32_t val;
- int n, m;
+ int n;
+ int m;
val = getreg32(CXD56_CRG_GEAR_IMG_SPI);
n = (val >> 16) & 1;
@@ -1592,7 +1625,8 @@ uint32_t cxd56_get_img_spi_baseclock(void)
uint32_t cxd56_get_img_wspi_baseclock(void)
{
uint32_t val;
- int n, m;
+ int n;
+ int m;
val = getreg32(CXD56_CRG_GEAR_IMG_WSPI);
n = (val >> 16) & 1;
@@ -1704,7 +1738,8 @@ static void cxd56_img_clock_disable(void)
static void cxd56_scu_clock_ctrl(uint32_t block, uint32_t intr, int on)
{
- uint32_t val, stat;
+ uint32_t val;
+ uint32_t stat;
int retry = 10000;
putreg32(0xffffffff, CXD56_TOPREG_CRG_INT_CLR0);
@@ -1743,7 +1778,8 @@ static void cxd56_scu_clock_ctrl(uint32_t block, uint32_t intr, int on)
static void cxd56_scu_clock_enable(void)
{
- uint32_t val, stat;
+ uint32_t val;
+ uint32_t stat;
int retry = 1000;
val = getreg32(CXD56_TOPREG_SYSIOP_CKEN);
@@ -1797,7 +1833,8 @@ static void cxd56_scu_clock_enable(void)
void cxd56_scu_clock_disable(void)
{
- uint32_t val, stat;
+ uint32_t val;
+ uint32_t stat;
int retry = 1000;
val = getreg32(CXD56_TOPREG_SYSIOP_CKEN);
@@ -1823,7 +1860,8 @@ void cxd56_scu_clock_disable(void)
/* Enable each blocks in SCU */
val = getreg32(CXD56_TOPREG_SCU_CKEN);
- putreg32(val & ~(SCU_SCU | SCU_SC | SCU_32K | SCU_SEQ), CXD56_TOPREG_SCU_CKEN);
+ putreg32(val & ~(SCU_SCU | SCU_SC | SCU_32K | SCU_SEQ),
+ CXD56_TOPREG_SCU_CKEN);
do
{
@@ -1904,7 +1942,8 @@ void cxd56_scuseq_clock_disable(void)
static void cxd56_scu_peri_clock_enable(FAR const struct scu_peripheral *p)
{
- uint32_t val, rst;
+ uint32_t val;
+ uint32_t rst;
uint32_t cken = 1u << p->cken;
uint32_t crgintmask = 1u << p->crgintmask;
uint32_t swreset = 1u << p->swreset;
@@ -1932,7 +1971,8 @@ static void cxd56_scu_peri_clock_enable(FAR const struct scu_peripheral *p)
static void cxd56_scu_peri_clock_disable(FAR const struct scu_peripheral *p)
{
- uint32_t val, rst;
+ uint32_t val;
+ uint32_t rst;
uint32_t cken = 1u << p->cken;
uint32_t crgintmask = 1u << p->crgintmask;
uint32_t swreset = 1u << p->swreset;
@@ -1953,7 +1993,8 @@ static void cxd56_scu_peri_clock_disable(FAR const struct scu_peripheral *p)
disable_pwd(PDID_SCU);
}
-static void cxd56_scu_peri_clock_gating(FAR const struct scu_peripheral *p, int enable)
+static void cxd56_scu_peri_clock_gating(\
+ FAR const struct scu_peripheral *p, int enable)
{
uint32_t cken = 1u << p->cken;
@@ -2086,7 +2127,8 @@ uint32_t cxd56_get_syspll_clock(void)
uint32_t cxd56_get_sys_ahb_baseclock(void)
{
- uint32_t bus, ahb;
+ uint32_t bus;
+ uint32_t ahb;
bus = getreg32(CXD56_TOPREG_CKDIV_CPU_DSP_BUS);
ahb = 1 << ((bus >> 16) & 0x7);
@@ -2095,7 +2137,8 @@ uint32_t cxd56_get_sys_ahb_baseclock(void)
uint32_t cxd56_get_sys_apb_baseclock(void)
{
- uint32_t bus, apb;
+ uint32_t bus;
+ uint32_t apb;
bus = getreg32(CXD56_TOPREG_CKDIV_CPU_DSP_BUS);
apb = 1 << ((bus >> 24) & 0x3);
@@ -2104,7 +2147,8 @@ uint32_t cxd56_get_sys_apb_baseclock(void)
uint32_t cxd56_get_sys_sfc_baseclock(void)
{
- uint32_t bus, sfchclk;
+ uint32_t bus;
+ uint32_t sfchclk;
bus = getreg32(CXD56_TOPREG_CKDIV_CPU_DSP_BUS);
sfchclk = ((bus >> 28) & 0xf);
@@ -2191,7 +2235,8 @@ uint32_t cxd56_get_gps_ahb_baseclock(void)
uint32_t cxd56_get_usb_baseclock(void)
{
uint32_t val;
- int n, m;
+ int n;
+ int m;
val = getreg32(CXD56_CRG_GEAR_PER_USB);
n = (val >> 16) & 1;
@@ -2209,7 +2254,8 @@ uint32_t cxd56_get_usb_baseclock(void)
uint32_t cxd56_get_img_vsync_baseclock(void)
{
- int n, m;
+ int n;
+ int m;
n = getreg32(CXD56_CRG_GEAR_N_IMG_VENB);
m = getreg32(CXD56_CRG_GEAR_M_IMG_VENB);
@@ -2226,9 +2272,13 @@ uint32_t cxd56_get_img_vsync_baseclock(void)
int up_pmramctrl(int cmd, uintptr_t addr, size_t size)
{
- int startidx, endidx;
+ int startidx;
+ int endidx;
int i;
- uint32_t mode, mask, ctrl, stat;
+ uint32_t mode;
+ uint32_t mask;
+ uint32_t ctrl;
+ uint32_t stat;
uint32_t val;
int changed = 0;
@@ -2317,7 +2367,8 @@ int up_pmramctrl(int cmd, uintptr_t addr, size_t size)
void up_pmstatdump(void)
{
- uint32_t stat0, stat1;
+ uint32_t stat0;
+ uint32_t stat1;
const char statch[] = " -?+"; /* OFF, retention, invalid, ON */
const char gatech[] = "| "; /* clock on, clock off */
diff --git a/arch/arm/src/cxd56xx/cxd56_config.h b/arch/arm/src/cxd56xx/cxd56_config.h
index 1a47f401cbb..c95017e80cb 100644
--- a/arch/arm/src/cxd56xx/cxd56_config.h
+++ b/arch/arm/src/cxd56xx/cxd56_config.h
@@ -33,8 +33,8 @@
*
****************************************************************************/
-#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56XX_CONFIG_H
-#define __ARCH_ARM_SRC_CXD56XX_CXD56XX_CONFIG_H
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_CONFIG_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_CONFIG_H
/****************************************************************************
* Included Files
@@ -135,4 +135,4 @@
* Public Functions
****************************************************************************/
-#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56XX_CONFIG_H */
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_CONFIG_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_cpufifo.c b/arch/arm/src/cxd56xx/cxd56_cpufifo.c
index b5ec0957e34..c2edda9c052 100644
--- a/arch/arm/src/cxd56xx/cxd56_cpufifo.c
+++ b/arch/arm/src/cxd56xx/cxd56_cpufifo.c
@@ -80,6 +80,7 @@ static void cpufifo_reserve(uint32_t data[2]);
/****************************************************************************
* Private Data
****************************************************************************/
+
/* Only for SYS, GNSS CPUs */
static sq_queue_t g_pushqueue;
diff --git a/arch/arm/src/cxd56xx/cxd56_delay.c b/arch/arm/src/cxd56xx/cxd56_delay.c
new file mode 100644
index 00000000000..f54f7eabca4
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_delay.c
@@ -0,0 +1,119 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_delay.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+#include
+
+#include
+
+#include "cxd56_clock.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define CXD56XX_LOOPSPERMSEC_156MHZ 7428ull
+#define CXD56XX_LOOPSPERMSEC_BY_CLOCK(clock) \
+ (uint32_t)(CXD56XX_LOOPSPERMSEC_156MHZ * (clock) / 156000000ull)
+
+/* Adjust manually to be up_udelay(1000) is neary equal with up_udelay(999) */
+
+#define CXD56XX_LOOPSPERUSEC_ADJUST 810ul;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_mdelay
+ *
+ * Description:
+ * Delay inline for the requested number of milliseconds.
+ * *** NOT multi-tasking friendly ***
+ *
+ ****************************************************************************/
+
+void up_mdelay(unsigned int milliseconds)
+{
+ volatile unsigned int i;
+ volatile unsigned int j;
+ uint32_t clock = cxd56_get_cpu_baseclk();
+ uint32_t loops = CXD56XX_LOOPSPERMSEC_BY_CLOCK(clock);
+
+ for (i = 0; i < milliseconds; i++)
+ {
+ for (j = 0; j < loops; j++)
+ {
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: up_udelay
+ *
+ * Description:
+ * Delay inline for the requested number of microseconds. NOTE: Because
+ * of all of the setup, several microseconds will be lost before the actual
+ * timing looop begins. Thus, the delay will always be a few microseconds
+ * longer than requested.
+ *
+ * *** NOT multi-tasking friendly ***
+ *
+ ****************************************************************************/
+
+void up_udelay(useconds_t microseconds)
+{
+ volatile unsigned int i;
+ volatile unsigned int j;
+ uint32_t clock = cxd56_get_cpu_baseclk();
+ uint32_t loops = CXD56XX_LOOPSPERMSEC_BY_CLOCK(clock);
+ uint32_t milliseconds = microseconds / 1000;
+
+ for (i = 0; i < milliseconds; i++)
+ {
+ for (j = 0; j < loops; j++)
+ {
+ }
+ }
+ loops = loops * (microseconds % 1000) / CXD56XX_LOOPSPERUSEC_ADJUST;
+ for (i = 0; i < loops; i++)
+ {
+ }
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_dmac.c b/arch/arm/src/cxd56xx/cxd56_dmac.c
new file mode 100644
index 00000000000..5f1126a7fea
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_dmac.c
@@ -0,0 +1,980 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_dmac.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "cxd56_dmac.h"
+
+#define PM_APP_ADMAC 51
+#define PM_APP_SKDMAC 52
+#define PM_APP_IDMAC 54
+
+#define DMAC1_REG_BASE 0x4e020000u /* SMP_DMAC */
+#define DMAC2_REG_BASE 0x4e021000u /* SMP_SAKE */
+#define DMAC3_REG_BASE 0x4e102000u /* IMG_DMAC */
+
+#define is_dmac(n, dev) ((dev) == (struct dmac_register_map *)\
+ DMAC ## n ## _REG_BASE)
+
+#define NCHANNELS 9
+
+#define __RO volatile const
+#define __WO volatile
+#define __RW volatile
+
+struct dmac_ch_register_map {
+ __RW uint32_t srcaddr;
+ __RW uint32_t destaddr;
+ __RW uint32_t lli;
+ __RW uint32_t control;
+ __RW uint32_t configuration;
+ uint32_t reserved[3];
+};
+
+struct dmac080_ch_register_map {
+ __RW uint32_t srcaddr;
+ __RW uint32_t destaddr;
+ __RW uint32_t lli;
+ __RW uint32_t control;
+ __RW uint32_t configuration;
+ __RW uint32_t deflli;
+ uint32_t reserved[2];
+};
+
+struct dmac_register_map {
+ __RO uint32_t intstatus;
+ __RO uint32_t inttcstatus;
+ __WO uint32_t inttcclear;
+ __RO uint32_t interrorstatus;
+ __WO uint32_t interrorclear;
+ __RO uint32_t rawinttcstatus;
+ __RO uint32_t rawinterrorstatus;
+ __RO uint32_t enbldchns;
+ __RW uint32_t softbreq;
+ __RW uint32_t softsreq;
+ __RW uint32_t softlbreq;
+ __RW uint32_t softlsreq;
+ __RW uint32_t configuration;
+ __RW uint32_t sync;
+
+ uint32_t reserved0[50];
+
+ struct dmac_ch_register_map channel[2];
+};
+
+struct dmac080_register_map {
+ __RO uint32_t intstatus;
+ __RO uint32_t inttcstatus;
+ __WO uint32_t inttcclear;
+ __RO uint32_t interrorstatus;
+ __WO uint32_t interrorclear;
+ __RO uint32_t rawinttcstatus;
+ __RO uint32_t rawinterrorstatus;
+ __RO uint32_t enbldchns;
+ __RW uint32_t softbreq;
+ __RW uint32_t softsreq;
+ __RW uint32_t softlbreq;
+ __RW uint32_t softlsreq;
+ __RW uint32_t configuration;
+ __RW uint32_t sync;
+ __RW uint32_t sreqmask;
+
+ uint32_t reserved0[49];
+
+ /* XXX: deflli not supported */
+
+ struct dmac_ch_register_map channel[5];
+};
+
+#define DMAC_CH_ENABLE (1u<<0)
+#define DMAC_CH_HALT (1u<<18)
+#define DMAC_CH_ACTIVE (1u<<17)
+
+#ifndef itemsof
+#define itemsof(a) (sizeof(a)/sizeof(a[0]))
+#endif
+
+/**
+ * Link list item structure for use scatter/gather operation
+ */
+
+typedef struct {
+ uint32_t src_addr; /**< Source address */
+ uint32_t dest_addr; /**< Destination address */
+ uint32_t nextlli; /**< Next link list */
+ uint32_t control; /**< Transfer control */
+} dmac_lli_t;
+
+#define CXD56_DMAC_M2M 0 /**< Memory to memory */
+#define CXD56_DMAC_M2P 1 /**< Memory to peripheral, DMAC controlled */
+#define CXD56_DMAC_P2M 2 /**< Peripheral to memory, DMAC controlled */
+#define CXD56_DMAC_P2P 3 /**< Peripheral to peripheral */
+#define CXD56_DMAC_P2CP 4 /**< P2P destination controlled */
+#define CXD56_DMAC_M2CP 5 /**< M2P peripheral controlled */
+#define CXD56_DMAC_CP2M 6 /**< P2M peripheral controlled */
+#define CXD56_DMAC_CP2P 7 /**< P2P source controlled */
+
+#define CXD56_DMAC_BSIZE1 0 /**< 1 burst */
+#define CXD56_DMAC_BSIZE4 1 /**< 4 burst */
+#define CXD56_DMAC_BSIZE8 2 /**< 8 burst */
+#define CXD56_DMAC_BSIZE16 3 /**< 16 burst */
+#define CXD56_DMAC_BSIZE32 4 /**< 32 burst */
+#define CXD56_DMAC_BSIZE64 5 /**< 64 burst */
+#define CXD56_DMAC_BSIZE128 6 /**< 128 burst */
+#define CXD56_DMAC_BSIZE256 7 /**< 256 burst */
+
+#define CXD56_DMAC_LITTLE_ENDIAN 0 /**< Little endian */
+#define CXD56_DMAC_BIG_ENDIAN 1 /**< Bit endian */
+
+#define CXD56_DMAC_MASTER1 0 /**< AHB master 1 */
+#define CXD56_DMAC_MASTER2 1 /**< AHB master 2 */
+
+/* max transfer size at a time */
+
+#define CXD56_DMAC_MAX_SIZE 0xfff
+
+/**
+ * Helper macro for construct transfer control parameter.
+ * Each parameters are the same with PD_DmacSetControl().
+ *
+ * @par Example:
+ * Here is an example for transfer setting with no interrupt,
+ * address increments, 4 byte, 4 burst and 16380 bytes (4 x 4095).
+ *
+ * @code
+ * list.control = PD_DmacCtrlHelper(0, 1, 1,
+ * PD_DMAC_WIDTH32, PD_DMAC_WIDTH32,
+ * PD_DMAC_BSIZE4, PD_DMAC_BSIZE4,
+ * 0xfffu);
+ * @endcode
+ */
+
+#define DMAC_CTRL_HELPER(intr, di, si, dwidth, swidth, dbsize, sbsize, tsize) \
+ (((intr) & 1u) << 31 | \
+ ((di) & 1u) << 27 | \
+ ((si) & 1u) << 26 | \
+ ((dwidth) & 7u) << 21 | \
+ ((swidth) & 7u) << 18 | \
+ ((dbsize) & 7u) << 15 | \
+ ((sbsize) & 7u) << 12 | \
+ ((tsize) & 0xfffu))
+
+/**
+ * Helper macro for construct transfer control parameter
+ * (for APP DMAC channel 2 - 6).
+ * Each parameters are the same with PD_DmacSetExControl().
+ *
+ * @par Example:
+ * Here is an example for transfer setting with no interrupt,
+ * address increments, 4 byte, 4 burst and 16380 bytes (4 x 4095).
+ *
+ * @code
+ * list.control = PD_DmacExCtrlHelper(0, 1, 1, 0, 0,
+ * PD_DMAC_WIDTH32, PD_DMAC_WIDTH32,
+ * PD_DMAC_BSIZE4, PD_DMAC_BSIZE4,
+ * 0xfffu);
+ * @endcode
+ *
+ * @note If you want to different burst sizes to source and destination,
+ * then data may remained in FIFO. In this case, DMAC cannot clear them.
+ * Do not use this configuration to transferring unknown size data (especially
+ * communication peripherals). I recommend the same setting to burst sizes.
+ */
+
+#define DMAC_EX_CTRL_HELPER(\
+ intr, di, si, dmaster, smaster, dwidth, swidth, dbsize, sbsize, tsize) \
+ (((intr) & 1u) << 31 | \
+ ((di) & 1u) << 30 | \
+ ((si) & 1u) << 29 | \
+ ((dmaster) & 1u) << 28 | \
+ ((smaster) & 1u) << 27 | \
+ ((dwidth) & 3u) << 25 | \
+ ((swidth) & 3u) << 23 | \
+ ((dbsize) & 3u) << 21 | \
+ ((sbsize) & 3u) << 19 | \
+ ((tsize) & 0x7ffffu))
+
+static int open_channels = 0;
+
+static int intr_handler_admac0(int irq, FAR void *context, FAR void *arg);
+static int intr_handler_admac1(int irq, FAR void *context, FAR void *arg);
+static int intr_handler_idmac(int irq, FAR void *context, FAR void *arg);
+static int intr_handler_skdmac0(int irq, FAR void *context, FAR void *arg);
+static int intr_handler_skdmac1(int irq, FAR void *context, FAR void *arg);
+static uint32_t irq_map[] = {
+ CXD56_IRQ_APP_DMAC0,
+ CXD56_IRQ_APP_DMAC1,
+ CXD56_IRQ_IDMAC,
+ CXD56_IRQ_IDMAC,
+ CXD56_IRQ_IDMAC,
+ CXD56_IRQ_IDMAC,
+ CXD56_IRQ_IDMAC,
+ CXD56_IRQ_SKDMAC_0,
+ CXD56_IRQ_SKDMAC_1,
+};
+
+static int (*intc_handler[])(int irq, FAR void *context, FAR void *arg) = {
+ intr_handler_admac0,
+ intr_handler_admac1,
+ intr_handler_idmac,
+ intr_handler_idmac,
+ intr_handler_idmac,
+ intr_handler_idmac,
+ intr_handler_idmac,
+ intr_handler_skdmac0,
+ intr_handler_skdmac1,
+};
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* This structure describes one DMA channel */
+
+struct dma_channel_s
+{
+ uint8_t chan; /* DMA channel number (0-CXD56_DMA_NCHANNELS) */
+ bool inuse; /* TRUE: The DMA channel is in use */
+ dma_config_t config; /* Current configuration */
+ dmac_lli_t * list; /* Link list */
+ dma_callback_t callback; /* Callback invoked when the DMA completes */
+ void *arg; /* Argument passed to callback function */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This is the array of all DMA channels */
+
+static struct dma_channel_s g_dmach[NCHANNELS];
+static sem_t g_dmaexc;
+
+static int dma_init(int ch);
+static int dma_uninit(int ch);
+static int dma_open(int ch);
+static int dma_close(int ch);
+static int dma_setconfig(int ch, int itc, int ierr, int flowctrl,
+ int destperi, int srcperi);
+static int dma_setintrcallback(int ch, dma_callback_t func, void *data);
+static int dma_clearintrcallback(int ch);
+static int dma_start(int ch, dmac_lli_t *list);
+static int dma_stop(int ch);
+
+static int ch2dmac(int ch)
+{
+ switch (ch) {
+ case 0: case 1:
+ return 1;
+ case 2: case 3: case 4: case 5: case 6: /* APP IDMAC */
+ return 3;
+ case 7: case 8: /* APP SKDMAC */
+ return 2;
+ default:
+ return 0;
+ }
+}
+
+static struct dmac_register_map *get_device(int ch)
+{
+ int id = ch2dmac(ch);
+
+ switch (id) {
+ case 1: return (struct dmac_register_map *)DMAC1_REG_BASE;
+ case 2: return (struct dmac_register_map *)DMAC2_REG_BASE;
+ case 3: return (struct dmac_register_map *)DMAC3_REG_BASE;
+ }
+ return NULL;
+}
+
+static struct dmac_ch_register_map *get_channel(int ch)
+{
+ struct dmac_register_map *dev = get_device(ch);
+ if (dev == NULL)
+ return NULL;
+
+ if (is_dmac(2, dev)) {
+ return &dev->channel[ch - 7];
+ }
+ else if (is_dmac(3, dev)) {
+ return &((struct dmac080_register_map *)dev)->channel[ch - 2];
+ }
+
+ return &dev->channel[ch & 1];
+}
+
+static int get_pmid(int ch)
+{
+ switch (ch) {
+ case 0: case 1:
+ return PM_APP_ADMAC;
+ case 2: case 3: case 4: case 5: case 6:
+ return PM_APP_IDMAC;
+ case 7: case 8:
+ return PM_APP_SKDMAC;
+ default:
+ break; /* may not comes here */
+ }
+ return 0;
+}
+
+struct dmac_ch_register_frame {
+ uint32_t srcaddr;
+ uint32_t destaddr;
+ uint32_t lli;
+ uint32_t control;
+ uint32_t configuration;
+};
+
+struct dmac_register_frame {
+ uint32_t configuration;
+ struct dmac_ch_register_frame channel[2];
+};
+
+static void _dmac_intc_handler(int ch)
+{
+ struct dmac_register_map *dev = get_device(ch);
+ struct dma_channel_s *dmach;
+ uint32_t mask;
+ int itc;
+ int err;
+
+ mask = (1u << (ch & 1));
+
+ if (is_dmac(2, dev)) {
+ mask = 1u << (ch - 7);
+ }
+ else if (is_dmac(3, dev)) {
+ mask = 1u << (ch - 2);
+ }
+
+ itc = dev->inttcstatus & mask;
+ err = dev->interrorstatus & mask;
+ dev->inttcclear = itc;
+ dev->interrorclear = err;
+
+ dmach = &g_dmach[ch];
+
+ if (dmach->callback) {
+ int flags = itc ? CXD56_DMA_INTR_ITC : 0;
+ flags |= err ? CXD56_DMA_INTR_ERR : 0;
+ dmach->callback((DMA_HANDLE)dmach, flags, dmach->arg);
+ }
+}
+
+static int intr_handler_admac0(int irq, FAR void *context, FAR void *arg)
+{
+ _dmac_intc_handler(0);
+ return OK;
+}
+
+static int intr_handler_admac1(int irq, FAR void *context, FAR void *arg)
+{
+ _dmac_intc_handler(1);
+ return OK;
+}
+
+static int intr_handler_idmac(int irq, FAR void *context, FAR void *arg)
+{
+ struct dmac_register_map *dev = get_device(2); /* XXX */
+ uint32_t stat = dev->intstatus & 0x1f;
+ int i;
+
+ for (i = 2; stat; i++, stat >>= 1) {
+ if (stat & 1)
+ _dmac_intc_handler(i);
+ }
+
+ return OK;
+}
+
+static int intr_handler_skdmac0(int irq, FAR void *context, FAR void *arg)
+{
+ _dmac_intc_handler(7);
+ return OK;
+}
+
+static int intr_handler_skdmac1(int irq, FAR void *context, FAR void *arg)
+{
+ _dmac_intc_handler(8);
+ return OK;
+}
+
+static void controller_power_on(int ch)
+{
+ int id = get_pmid(ch);
+
+ if (id == PM_APP_SKDMAC)
+ return;
+
+/* TODO power on */
+}
+
+static void controller_power_off(int ch)
+{
+ int id = get_pmid(ch);
+
+ if (id == PM_APP_SKDMAC) /* Do not disable SKDMAC, leave it to SAKE driver. */
+ return;
+
+/* TODO power off */
+}
+
+int dma_init(int ch)
+{
+ int id = ch2dmac(ch);
+
+ if (!id)
+ return -ENODEV;
+
+ controller_power_on(ch);
+
+ irq_attach(irq_map[ch], intc_handler[ch], NULL);
+
+ return 0;
+}
+
+int dma_uninit(int ch)
+{
+ int id = ch2dmac(ch);
+
+ if (!id)
+ return -ENODEV;
+
+ controller_power_off(ch);
+
+ return 0;
+}
+
+int dma_open(int ch)
+{
+ struct dmac_register_map *dmac = get_device(ch);
+ irqstate_t flags;
+
+ if (dmac == NULL)
+ return -ENODEV;
+
+ flags = enter_critical_section();
+
+ if (open_channels & (1u << ch)) {
+ leave_critical_section(flags);
+ return -EBUSY;
+ }
+ open_channels |= 1u << ch;
+
+ leave_critical_section(flags);
+
+ g_dmach[ch].callback = NULL;
+ g_dmach[ch].arg = NULL;
+
+ dmac->sync = 0;
+ dmac->configuration |= 1;
+
+ return 0;
+}
+
+static int dma_close(int ch)
+{
+ struct dmac_register_map *dmac = get_device(ch);
+ uint32_t enabled;
+ irqstate_t flags;
+ uint32_t chmask;
+ int shift;
+
+ if (dmac == NULL)
+ return -ENODEV;
+
+ shift = ch & 1;
+
+ if (is_dmac(2, dmac)) {
+ shift = ch - 7;
+ }
+ else if (is_dmac(3, dmac)) {
+ shift = ch - 2;
+ }
+
+ enabled = dmac->enbldchns;
+ if (enabled & (1 << shift))
+ return -EBUSY;
+
+ dma_clearintrcallback(ch);
+
+ flags = enter_critical_section();
+
+ chmask = (3u << (ch & ~1));
+
+ if (is_dmac(2, dmac)) {
+ chmask = 0x3u << 7;
+ }
+ else if (is_dmac(3, dmac)) {
+ chmask = 0x1fu << 2;
+ }
+
+ open_channels &= ~(1u << ch);
+
+ /* Stop device if both of channels are already closed */
+
+ if (!(open_channels & chmask))
+ dmac->configuration &= ~1;
+
+ leave_critical_section(flags);
+
+ return 0;
+}
+
+static int dma_setconfig(int ch, int itc, int ierr, int flowctrl,
+ int destperi, int srcperi)
+{
+ struct dmac_ch_register_map *channel = get_channel(ch);
+ if (channel == NULL)
+ return -ENODEV;
+
+ channel->configuration = (itc & 1) << 15 |
+ (ierr & 1) << 14 |
+ (flowctrl & 7) << 11 |
+
+ /* Burst enable */
+
+ 1 << 25 | 1 << 24 |
+
+ (destperi & 0xf) << 6 |
+ (srcperi & 0xf) << 1;
+
+ return 0;
+}
+
+static int dma_setintrcallback(int ch, dma_callback_t func, void *data)
+{
+ if (ch >= NCHANNELS)
+ return -ENODEV;
+
+ g_dmach[ch].callback = func;
+ g_dmach[ch].arg = data;
+
+ up_enable_irq(irq_map[ch]);
+
+ return 0;
+}
+
+static int dma_clearintrcallback(int ch)
+{
+ if (ch >= NCHANNELS)
+ return -ENODEV;
+
+ g_dmach[ch].callback = NULL;
+ g_dmach[ch].arg = NULL;
+
+ up_disable_irq(irq_map[ch]);
+
+ return 0;
+}
+
+static int dma_start(int ch, dmac_lli_t *list)
+{
+ struct dmac_ch_register_map *channel = get_channel(ch);
+ if (channel == NULL)
+ return -ENODEV;
+
+ if (list) {
+ channel->srcaddr = list->src_addr;
+ channel->destaddr = list->dest_addr;
+ channel->lli = list->nextlli;
+ channel->control = list->control;
+ }
+
+ channel->configuration |= DMAC_CH_ENABLE;
+
+ return 0;
+}
+
+static int dma_stop(int ch)
+{
+ struct dmac_ch_register_map *channel = get_channel(ch);
+ if (channel == NULL)
+ return -ENODEV;
+
+ if (!(channel->configuration & DMAC_CH_ENABLE))
+ return 0; /* already stopped */
+
+ /* Set HALT and poll Active bit for FIFO is cleaned */
+
+ channel->configuration |= DMAC_CH_HALT;
+
+ (void) channel->lli;
+ (void) channel->lli;
+
+ while (channel->configuration & DMAC_CH_ACTIVE);
+
+ channel->configuration &= ~(DMAC_CH_HALT | DMAC_CH_ENABLE);
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: cxd56_dmainitialize
+ *
+ * Description:
+ * Initialize the DMA subsystem
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void weak_function up_dma_initialize(void)
+{
+ int i;
+
+ dmainfo("Initialize DMAC\n");
+
+ /* Initialize the channel list */
+
+ for (i = 0; i < NCHANNELS; i++)
+ {
+ g_dmach[i].chan = i;
+ }
+
+ sem_init(&g_dmaexc, 0, 1);
+}
+
+/****************************************************************************
+ * Name: cxd56_dmachannel
+ *
+ * Description:
+ * Allocate a DMA channel. This function gives the caller mutually exclusive
+ * access to a DMA channel.
+ *
+ * If no DMA channel is available, then cxd56_dmachannel() will wait until
+ * the holder of a channel relinquishes the channel by calling
+ * cxd56_dmafree().
+ *
+ * Input parameters:
+ * ch - DMA channel to use
+ * maxsize - Max size to be transfered in bytes
+ *
+ * Returned Value:
+ * This function ALWAYS returns a non-NULL, void* DMA channel handle.
+ *
+ * Assumptions:
+ * - The caller can wait for a DMA channel to be freed if it is not
+ * available.
+ *
+ ****************************************************************************/
+
+DMA_HANDLE cxd56_dmachannel(int ch, ssize_t maxsize)
+{
+ struct dma_channel_s *dmach;
+ int n;
+
+ /* Get exclusive access to allocate channel */
+
+ sem_wait(&g_dmaexc);
+
+ if (ch < 0 || ch >= NCHANNELS)
+ {
+ dmaerr("Invalid channel number %d.\n", ch);
+ goto err;
+ }
+ dmach = &g_dmach[ch];
+
+ if (maxsize == 0)
+ {
+ dmaerr("Invalid max size: %d\n", maxsize);
+ goto err;
+ }
+
+ if (dmach->inuse)
+ {
+ dmaerr("Channel already in use.\n");
+ goto err;
+ }
+
+ dmainfo("DMA channel %d\n", dmach->chan);
+
+ n = maxsize / CXD56_DMAC_MAX_SIZE;
+ if ((maxsize % CXD56_DMAC_MAX_SIZE) != 0)
+ {
+ n++;
+ }
+
+ dmach->list = (dmac_lli_t *)kmm_malloc(n * sizeof(dmac_lli_t));
+ if (dmach->list == NULL)
+ {
+ dmainfo("Failed to malloc\n");
+ goto err;
+ }
+
+ /* Initialize hardware */
+
+ dma_init(dmach->chan);
+ dma_open(dmach->chan);
+
+ dmach->inuse = true;
+
+ sem_post(&g_dmaexc);
+
+ return (DMA_HANDLE)dmach;
+
+err:
+ sem_post(&g_dmaexc);
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: cxd56_dmafree
+ *
+ * Description:
+ * Release a DMA channel. If another thread is waiting for this DMA channel
+ * in a call to cxd56_dmachannel, then this function will re-assign the
+ * DMA channel to that thread and wake it up.
+ *
+ * NOTE: The 'handle' used in this argument must NEVER be used again until
+ * cxd56_dmachannel() is called again to re-gain access to the channel.
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * - The caller holds the DMA channel.
+ * - There is no DMA in progress
+ *
+ ****************************************************************************/
+
+void cxd56_dmafree(DMA_HANDLE handle)
+{
+ struct dma_channel_s *dmach = (struct dma_channel_s *)handle;
+
+ if (dmach == NULL)
+ {
+ dmaerr("Invalid handle.\n");
+ return;
+ }
+
+ sem_wait(&g_dmaexc);
+
+ if (!dmach->inuse)
+ {
+ dmaerr("Channel %d already freed.\n", dmach->chan);
+ goto err;
+ }
+
+ dmainfo("free DMA channel %d\n", dmach->chan);
+
+ kmm_free(dmach->list);
+
+ dma_close(dmach->chan);
+ dma_uninit(dmach->chan);
+
+ dmach->inuse = false;
+
+err:
+ sem_post(&g_dmaexc);
+}
+
+/****************************************************************************
+ * Name: cxd56_rxdmasetup
+ *
+ * Description:
+ * Configure an RX (peripheral-to-memory) DMA before starting the transfer.
+ *
+ * Input Parameters:
+ * paddr - Peripheral address (source)
+ * maddr - Memory address (destination)
+ * nbytes - Number of bytes to transfer. Must be an even multiple of the
+ * configured transfer size.
+ * config - Channel configuration selections
+ *
+ ****************************************************************************/
+
+void cxd56_rxdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
+ size_t nbytes, dma_config_t config)
+{
+ struct dma_channel_s *dmach = (struct dma_channel_s *)handle;
+ int i;
+ int list_num;
+ uintptr_t dst;
+ size_t rest;
+ int peri;
+
+ DEBUGASSERT(dmach != NULL && dmach->inuse && dmach->list != NULL);
+
+ dst = maddr;
+ rest = nbytes;
+
+ list_num = (nbytes + CXD56_DMAC_MAX_SIZE - 1) / CXD56_DMAC_MAX_SIZE;
+ for (i = 0; i < list_num - 1; i++)
+ {
+ dmach->list[i].src_addr = paddr;
+ dmach->list[i].dest_addr = dst;
+ dmach->list[i].nextlli = (uint32_t)&dmach->list[i + 1];
+ dmach->list[i].control = DMAC_EX_CTRL_HELPER(0, 1, 0, /* interrupt / Dest inc / Src inc */
+ CXD56_DMAC_MASTER1, CXD56_DMAC_MASTER2, /* AHB dst master / AHB src master (fixed) */
+ config.dest_width, config.src_width, /* Dest / Src transfer width */
+ CXD56_DMAC_BSIZE4, CXD56_DMAC_BSIZE4, /* Dest / Src burst size (fixed) */
+ CXD56_DMAC_MAX_SIZE);
+
+ dst += CXD56_DMAC_MAX_SIZE;
+ rest -= CXD56_DMAC_MAX_SIZE;
+ }
+
+ dmach->list[i].src_addr = paddr;
+ dmach->list[i].dest_addr = dst;
+ dmach->list[i].nextlli = 0;
+ dmach->list[i].control = DMAC_EX_CTRL_HELPER(1, 1, 0, /* interrupt / Dest inc / Src inc */
+ CXD56_DMAC_MASTER1, CXD56_DMAC_MASTER2, /* AHB dst master / AHB src master (fixed) */
+ config.dest_width, config.src_width, /* Dest / Src transfer width */
+ CXD56_DMAC_BSIZE4, CXD56_DMAC_BSIZE4, /* Dest / Src burst size (fixed) */
+ rest);
+
+ peri = config.channel_cfg & CXD56_DMA_PERIPHERAL_MASK;
+ dma_setconfig(dmach->chan, 1, 1, CXD56_DMAC_P2M, 0, peri);
+}
+
+/****************************************************************************
+ * Name: cxd56_txdmasetup
+ *
+ * Description:
+ * Configure an TX (memory-to-peripheral) DMA before starting the transfer.
+ *
+ * Input Parameters:
+ * paddr - Peripheral address (destination)
+ * maddr - Memory address (source)
+ * nbytes - Number of bytes to transfer. Must be an even multiple of the
+ * configured transfer size.
+ * config - Channel configuration selections
+ *
+ ****************************************************************************/
+
+void cxd56_txdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
+ size_t nbytes, dma_config_t config)
+{
+ struct dma_channel_s *dmach = (struct dma_channel_s *)handle;
+ int i;
+ int list_num;
+ uintptr_t src;
+ size_t rest;
+ int peri;
+
+ DEBUGASSERT(dmach != NULL && dmach->inuse && dmach->list != NULL);
+
+ src = maddr;
+ rest = nbytes;
+
+ list_num = (nbytes + CXD56_DMAC_MAX_SIZE - 1) / CXD56_DMAC_MAX_SIZE;
+ for (i = 0; i < list_num - 1; i++)
+ {
+ dmach->list[i].src_addr = src;
+ dmach->list[i].dest_addr = paddr;
+ dmach->list[i].nextlli = (uint32_t)&dmach->list[i + 1];
+ dmach->list[i].control = DMAC_EX_CTRL_HELPER(0, 0, 1, /* interrupt / Dest inc / Src inc */
+ CXD56_DMAC_MASTER2, CXD56_DMAC_MASTER1, /* AHB dst master / AHB src master (fixed) */
+ config.dest_width, config.src_width, /* Dest / Src transfer width (fixed) */
+ CXD56_DMAC_BSIZE1, CXD56_DMAC_BSIZE1, /* Dest / Src burst size (fixed) */
+ CXD56_DMAC_MAX_SIZE);
+
+ src += CXD56_DMAC_MAX_SIZE;
+ rest -= CXD56_DMAC_MAX_SIZE;
+ }
+
+ dmach->list[i].src_addr = src;
+ dmach->list[i].dest_addr = paddr;
+ dmach->list[i].nextlli = 0;
+ dmach->list[i].control = DMAC_EX_CTRL_HELPER(1, 0, 1, /* interrupt / Dest inc / Src inc */
+ CXD56_DMAC_MASTER2, CXD56_DMAC_MASTER1, /* AHB dst master / AHB src master (fixed) */
+ config.dest_width, config.src_width, /* Dest / Src transfer width (fixed) */
+ CXD56_DMAC_BSIZE4, CXD56_DMAC_BSIZE4, /* Dest / Src burst size (fixed) */
+ rest);
+
+ peri = config.channel_cfg & CXD56_DMA_PERIPHERAL_MASK;
+ dma_setconfig(dmach->chan, 1, 1, CXD56_DMAC_M2P, peri, 0);
+}
+
+/****************************************************************************
+ * Name: cxd56_dmastart
+ *
+ * Description:
+ * Start the DMA transfer
+ *
+ * Assumptions:
+ * - DMA handle allocated by cxd56_dmachannel()
+ * - No DMA in progress
+ *
+ ****************************************************************************/
+
+void cxd56_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
+{
+ struct dma_channel_s *dmach = (struct dma_channel_s *)handle;
+
+ DEBUGASSERT(dmach && dmach->inuse);
+
+ /* Save the DMA complete callback info */
+
+ dma_setintrcallback(dmach->chan, callback, arg);
+ dma_start(dmach->chan, dmach->list);
+}
+
+/****************************************************************************
+ * Name: cxd56_dmastop
+ *
+ * Description:
+ * Cancel the DMA. After cxd56_dmastop() is called, the DMA channel is
+ * reset and cxd56_dmasetup() must be called before cxd56_dmastart() can be
+ * called again
+ *
+ * Assumptions:
+ * - DMA handle allocated by cxd56_dmachannel()
+ *
+ ****************************************************************************/
+
+void cxd56_dmastop(DMA_HANDLE handle)
+{
+ struct dma_channel_s *dmach = (struct dma_channel_s *)handle;
+
+ DEBUGASSERT(dmach);
+
+ dma_stop(dmach->chan);
+ dma_clearintrcallback(dmach->chan);
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_dmac.h b/arch/arm/src/cxd56xx/cxd56_dmac.h
new file mode 100644
index 00000000000..fe84e393b37
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_dmac.h
@@ -0,0 +1,206 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_dmac.h
+ *
+ * Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_DMAC_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_DMAC_H
+
+#include
+
+#include "hardware/cxd56_dmac_common.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define CXD56_DMA_PERIPHERAL_MASK (0x0f)
+#define CXD56_DMA_PERIPHERAL_UART2_TX (0)
+#define CXD56_DMA_PERIPHERAL_UART2_RX (1)
+#define CXD56_DMA_PERIPHERAL_SPI4_TX (2)
+#define CXD56_DMA_PERIPHERAL_SPI4_RX (3)
+#define CXD56_DMA_PERIPHERAL_SPI5_TX (4)
+#define CXD56_DMA_PERIPHERAL_SPI5_RX (5)
+
+#define CXD56_DMA_INTR_ITC (1u<<0) /**< Terminal count interrupt status */
+#define CXD56_DMA_INTR_ERR (1u<<1) /**< Error interrupt status */
+
+#define CXD56_DMAC_WIDTH8 0 /**< 8 bit width */
+#define CXD56_DMAC_WIDTH16 1 /**< 16 bit width */
+#define CXD56_DMAC_WIDTH32 2 /**< 32 bit width */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_dmachannel
+ *
+ * Description:
+ * Allocate a DMA channel. This function gives the caller mutually exclusive
+ * access to a DMA channel.
+ *
+ * If no DMA channel is available, then cxd56_dmachannel() will wait until
+ * the holder of a channel relinquishes the channel by calling
+ * cxd56_dmafree().
+ *
+ * Input parameters:
+ * ch - DMA channel to use
+ * maxsize - Max size to be transfered in bytes
+ *
+ * Returned Value:
+ * This function ALWAYS returns a non-NULL, void* DMA channel handle.
+ *
+ * Assumptions:
+ * - The caller can wait for a DMA channel to be freed if it is not
+ * available.
+ *
+ ****************************************************************************/
+
+DMA_HANDLE cxd56_dmachannel(int ch, ssize_t maxsize);
+
+/****************************************************************************
+ * Name: cxd56_dmafree
+ *
+ * Description:
+ * Release a DMA channel. If another thread is waiting for this DMA channel
+ * in a call to cxd56_dmachannel, then this function will re-assign the DMA
+ * channel to that thread and wake it up.
+ *
+ * NOTE: The 'handle' used in this argument must NEVER be used again until
+ * cxd56_dmachannel() is called again to re-gain access to the channel.
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * - The caller holds the DMA channel.
+ * - There is no DMA in progress
+ *
+ ****************************************************************************/
+
+void cxd56_dmafree(DMA_HANDLE handle);
+
+/****************************************************************************
+ * Name: cxd56_rxdmasetup
+ *
+ * Description:
+ * Configure an RX (peripheral-to-memory) DMA before starting the transfer.
+ *
+ * Input Parameters:
+ * paddr - Peripheral address (source)
+ * maddr - Memory address (destination)
+ * nbytes - Number of bytes to transfer. Must be an even multiple of the
+ * configured transfer size.
+ * config - Channel configuration selections
+ *
+ ****************************************************************************/
+
+void cxd56_rxdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
+ size_t nbytes, dma_config_t config);
+
+/****************************************************************************
+ * Name: cxd56_txdmasetup
+ *
+ * Description:
+ * Configure an TX (memory-to-peripheral) DMA before starting the transfer.
+ *
+ * Input Parameters:
+ * paddr - Peripheral address (destination)
+ * maddr - Memory address (source)
+ * nbytes - Number of bytes to transfer. Must be an even multiple of the
+ * configured transfer size.
+ * config - Channel configuration selections
+ *
+ ****************************************************************************/
+
+void cxd56_txdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
+ size_t nbytes, dma_config_t config);
+
+/****************************************************************************
+ * Name: cxd56_dmastart
+ *
+ * Description:
+ * Start the DMA transfer
+ *
+ * Assumptions:
+ * - DMA handle allocated by cxd56_dmachannel()
+ * - No DMA in progress
+ *
+ ****************************************************************************/
+
+void cxd56_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg);
+
+/****************************************************************************
+ * Name: cxd56_dmastop
+ *
+ * Description:
+ * Cancel the DMA. After cxd56_dmastop() is called, the DMA channel is reset
+ * and cxd56_dmasetup() must be called before cxd56_dmastart() can be called
+ * again
+ *
+ * Assumptions:
+ * - DMA handle allocated by cxd56_dmachannel()
+ *
+ ****************************************************************************/
+
+void cxd56_dmastop(DMA_HANDLE handle);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_DMAC_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_dmac_common.h b/arch/arm/src/cxd56xx/cxd56_dmac_common.h
new file mode 100644
index 00000000000..a642c554e84
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_dmac_common.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_dmac_common.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_DMAC_COMMON_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_DMAC_COMMON_H
+
+#include
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* DMA_HANDLE provides an opaque are reference that can be used to represent a
+ * DMA channel.
+ */
+
+typedef FAR void *DMA_HANDLE;
+
+/* Description:
+ * This is the type of the callback that is used to inform the user of the
+ * completion of the DMA.
+ *
+ * Input Parameters:
+ * handle - Refers tot he DMA channel or stream
+ * status - A bit encoded value that provides the completion status.
+ * See the DMASTATUS_* definitions above.
+ * arg - A user-provided value that was provided when cxd56_dmastart()
+ * was called.
+ */
+
+typedef void (*dma_callback_t)(DMA_HANDLE handle, uint8_t status, void *arg);
+
+/* Type of 'config' argument passed to cxd56_rxdmasetup() and
+ * cxd56_txdmasetup.
+ * See CXD56_DMA_* encodings above. If these encodings exceed 16-bits, then
+ * this should be changed to a uint32_t.
+ */
+
+typedef struct {
+ uint16_t channel_cfg;
+ uint8_t dest_width;
+ uint8_t src_width;
+} dma_config_t;
+
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_DMAC_COMMON_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_emmc.c b/arch/arm/src/cxd56xx/cxd56_emmc.c
new file mode 100644
index 00000000000..22db97918c2
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_emmc.c
@@ -0,0 +1,964 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_emmc.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include "chip.h"
+#include "up_arch.h"
+#include "cxd56_clock.h"
+#include "cxd56_emmc.h"
+#include "hardware/cxd56_emmc.h"
+#include "cxd56_pinconfig.h"
+
+#define SECTOR_SIZE (512)
+
+#define EMMC_DATA_WRITE 0
+#define EMMC_DATA_READ 1
+#define EMMC_NON_DATA 2
+
+#define EMMC_NON_RESP 0
+#define EMMC_RESP_R1 1
+#define EMMC_RESP_R1B 2
+#define EMMC_RESP_R2 3
+#define EMMC_RESP_R3 4
+
+struct emmc_dma_desc_s {
+ uint32_t ctrl;
+ uint32_t size;
+ uint32_t addr;
+ uint32_t next;
+};
+
+struct cxd56_emmc_state_s
+{
+ sem_t excsem;
+ int crefs;
+ uint32_t total_sectors;
+};
+
+/* Block driver interfaces **************************************************/
+
+static int cxd56_emmc_open(FAR struct inode *inode);
+static int cxd56_emmc_close(FAR struct inode *inode);
+static ssize_t cxd56_emmc_read(FAR struct inode *inode,
+ unsigned char *buffer, size_t start_sector,
+ unsigned int nsectors);
+#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY)
+static ssize_t cxd56_emmc_write(FAR struct inode *inode,
+ const unsigned char *buffer,
+ size_t start_sector,
+ unsigned int nsectors);
+#endif
+static int cxd56_emmc_geometry(FAR struct inode *inode,
+ struct geometry *geometry);
+static int emmc_interrupt(int irq, FAR void *context, FAR void *arg);
+
+static const struct block_operations g_bops =
+{
+ cxd56_emmc_open, /* open */
+ cxd56_emmc_close, /* close */
+ cxd56_emmc_read, /* read */
+#if defined(CONFIG_FS_WRITABLE)
+ cxd56_emmc_write, /* write */
+#else
+ NULL, /* write */
+#endif
+ cxd56_emmc_geometry, /* geometry */
+ NULL /* ioctl */
+};
+
+static sem_t g_waitsem;
+struct cxd56_emmc_state_s g_emmcdev;
+
+#define EMMC_CLKDIV_UNDER_400KHZ (32u)
+#define EMMC_CLKDIV_NON_DIV (0u)
+
+#define EMMC_RCA (2) /* greater than 1 */
+
+#define EMMC_DATA_TIMEOUT (0xFFFFFFu) /* max reg value */
+#define EMMC_RESP_TIMEOUT (0xFFu) /* max reg value */
+
+#define EMMC_MSIZE (6) /* Burst size is 512B */
+#define EMMC_FIFO_DEPTH (0x100) /* FIFO size is 1KB */
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+static void emmc_takesem(FAR sem_t *sem)
+{
+ while (sem_wait(sem) != 0)
+ {
+ ASSERT(errno == EINTR);
+ }
+}
+
+static void emmc_givesem(FAR sem_t *sem)
+{
+ sem_post(sem);
+}
+
+static void emmc_cmdstarted(void)
+{
+ uint32_t val;
+
+ do
+ {
+ val = getreg32(EMMC_CMD);
+ }
+ while (val & EMMC_CMD_START_CMD);
+}
+
+static void emmc_reset(uint32_t reg, uint32_t bits)
+{
+ uint32_t val;
+
+ val = getreg32(reg);
+ putreg32((val | bits), reg);
+ do
+ {
+ val = getreg32(reg);
+ }
+ while (val & bits);
+}
+
+#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY)
+static void emmc_flushwritefifo(void)
+{
+ /* eMMC host controller has a problem that invalid data is still remained
+ * in the FIFO after data write done,
+ * therefore, invalid data will be written to eMMC in the next data write.
+ * So, we need to reset FIFO after data write.
+ * And invalid data remain in FIFO when setting DDR_REG, too
+ */
+
+ emmc_reset(EMMC_CTRL, EMMC_CTRL_FIFO_RESET | EMMC_CTRL_CTRL_RESET);
+
+ putreg32(0, EMMC_CMDARG);
+ putreg32(EMMC_CMD_START_CMD | EMMC_CMD_USE_HOLDREG |
+ EMMC_CMD_UPDATE_CLKREG | EMMC_CMD_WAIT_PRE_DATA,
+ EMMC_CMD);
+
+ emmc_cmdstarted();
+
+ emmc_reset(EMMC_CTRL, EMMC_CTRL_FIFO_RESET);
+}
+#endif
+
+static void emmc_initregister(void)
+{
+ uint32_t rxwmark;
+ uint32_t txwmark;
+ uint32_t blksize;
+ uint32_t blksizeperhdatawidth;
+ uint32_t rdthr;
+
+ emmc_reset(EMMC_CTRL, EMMC_CTRL_CTRL_RESET);
+ emmc_reset(EMMC_CTRL, EMMC_CTRL_FIFO_RESET);
+ emmc_reset(EMMC_CTRL, EMMC_CTRL_DMA_RESET);
+ emmc_reset(EMMC_BMOD, EMMC_BMOD_SW_RESET);
+
+ putreg32(EMMC_CTRL_USE_IDMAC | EMMC_CTRL_INT_ENABLE, EMMC_CTRL);
+
+ putreg32((EMMC_DATA_TIMEOUT << EMMC_TMOUT_DATA_SHIFT) |
+ (EMMC_RESP_TIMEOUT << EMMC_TMOUT_RESP_SHIFT),
+ EMMC_TMOUT);
+
+ rxwmark = EMMC_FIFO_DEPTH / 2 - 1;
+ txwmark = EMMC_FIFO_DEPTH / 2;
+ putreg32((EMMC_MSIZE << EMMC_FIFOTH_MSIZE_SHIFT) |
+ (rxwmark << EMMC_FIFOTH_RX_SHIFT) |
+ (txwmark << EMMC_FIFOTH_TX_SHIFT),
+ EMMC_FIFOTH);
+
+ putreg32(EMMC_BMOD_IDMAC_EN | EMMC_BMOD_FIXED_BURST, EMMC_BMOD);
+
+ blksize = SECTOR_SIZE;
+ blksizeperhdatawidth = blksize / 4;
+ if (blksize < EMMC_FIFO_DEPTH / 2)
+ {
+ rdthr = blksizeperhdatawidth;
+ }
+ else
+ {
+ rdthr = blksizeperhdatawidth / 2;
+ }
+
+ putreg32((rdthr << EMMC_CARD_RD_THR_SHIFT |
+ EMMC_BSYCLR_INT_EN | EMMC_CARD_RD_THE_EN),
+ EMMC_CARDTHRCTL);
+
+ putreg32(0, EMMC_INTMASK);
+}
+
+static void emmc_changeclock(int clkdiv)
+{
+ uint32_t cmd;
+
+ cmd = EMMC_CMD_START_CMD | EMMC_CMD_UPDATE_CLKREG |
+ EMMC_CMD_USE_HOLDREG | EMMC_CMD_WAIT_PRE_DATA;
+
+ /* disable clock */
+
+ putreg32(EMMC_CLKENA_DIS, EMMC_CLKENA);
+ putreg32(cmd, EMMC_CMD);
+ emmc_cmdstarted();
+
+ /* change clock */
+
+ putreg32(clkdiv, EMMC_CLKDIV);
+ putreg32(cmd, EMMC_CMD);
+ emmc_cmdstarted();
+
+ /* enable clock */
+
+ putreg32(EMMC_CLKENA_ENA, EMMC_CLKENA);
+ putreg32(cmd, EMMC_CMD);
+ emmc_cmdstarted();
+}
+
+static struct emmc_dma_desc_s *emmc_setupdma(void *buf, unsigned int nbytes)
+{
+ int i;
+ int ndescs;
+ struct emmc_dma_desc_s *descs;
+ struct emmc_dma_desc_s *d;
+ uint32_t addr;
+ uint32_t size;
+ unsigned int remain;
+
+ if (nbytes == 0)
+ {
+ return NULL;
+ }
+
+ ndescs = nbytes / 4096;
+ if ((nbytes & (4096 - 1)) != 0)
+ {
+ ndescs++;
+ }
+
+ descs = (struct emmc_dma_desc_s *)
+ kmm_malloc(ndescs * sizeof(struct emmc_dma_desc_s));
+ if (!descs)
+ {
+ return NULL;
+ }
+
+ remain = nbytes;
+ addr = (uint32_t)(uintptr_t)buf;
+
+ for (i = 0, d = descs; i < ndescs; i++, d++)
+ {
+ d->ctrl = EMMC_IDMAC_DES0_OWN | EMMC_IDMAC_DES0_CH |
+ EMMC_IDMAC_DES0_DIC;
+
+ size = MIN(remain, 4096);
+ d->size = size;
+ d->addr = addr;
+ d->next = (uint32_t)(uintptr_t)(d + 1);
+
+ remain -= size;
+ addr += size;
+ }
+
+ ASSERT(remain == 0);
+
+ /* Adjust first and last descriptor members */
+
+ descs[0].ctrl |= EMMC_IDMAC_DES0_FD;
+ descs[ndescs-1].ctrl |= EMMC_IDMAC_DES0_LD;
+ descs[ndescs-1].next = 0;
+
+#ifdef CONFIG_DEBUG_VERBOSE
+ for (i = 0, d = descs; i < ndescs; i++, d++)
+ {
+ finfo("desc %p = ctrl 0x%x, size 0x%x, addr 0x%x, next 0x%x\n",
+ d, d->ctrl, d->size, d->addr, d->next);
+ }
+#endif
+
+ putreg32((uint32_t)(uintptr_t)descs, EMMC_DBADDR);
+
+ return descs;
+}
+
+static int emmc_checkresponse(void)
+{
+ uint32_t resp = getreg32(EMMC_RESP0);
+ uint32_t intsts = getreg32(EMMC_RINTSTS);
+
+ if (intsts & EMMC_INTSTS_RTO)
+ {
+ ferr("Response timed out.\n");
+ return -EIO;
+ }
+
+ if (resp & R1STATUS_ALL_ERR)
+ {
+ ferr("Response error %08x\n", resp);
+ return -EIO;
+ }
+ return OK;
+}
+
+static void emmc_send(int datatype, uint32_t opcode, uint32_t arg,
+ int resptype)
+{
+ uint32_t prev;
+ uint32_t mask;
+ uint32_t cmd;
+ uint32_t status;
+
+ /* Get current interrupt mask, leave SDIO relative bits. */
+
+ prev = mask = getreg32(EMMC_INTMASK) & EMMC_INTSTS_SDIO;
+
+ cmd = EMMC_CMD_START_CMD | EMMC_CMD_USE_HOLDREG |
+ EMMC_CMD_CHK_RESP_CRC | EMMC_CMD_RESP_EXPECTED |
+ EMMC_CMD_WAIT_PRE_DATA | opcode;
+
+ switch (datatype)
+ {
+ case EMMC_DATA_WRITE:
+ cmd |= EMMC_CMD_WRITE | EMMC_CMD_DATA_EXPECTED;
+ mask |= EMMC_INTSTS_DTO;
+ break;
+ case EMMC_DATA_READ:
+ cmd |= EMMC_CMD_READ | EMMC_CMD_DATA_EXPECTED;
+ mask |= EMMC_INTSTS_DTO;
+ break;
+ case EMMC_NON_DATA:
+ mask |= EMMC_INTSTS_CD;
+ if (opcode == GO_IDLE_STATE)
+ {
+ cmd |= EMMC_CMD_SEND_INIT;
+ cmd &= ~EMMC_CMD_CHK_RESP_CRC;
+ cmd &= ~EMMC_CMD_RESP_EXPECTED;
+ }
+ else if (opcode == SEND_OP_COND)
+ {
+ cmd &= ~EMMC_CMD_CHK_RESP_CRC;
+ }
+ else if (opcode == ALL_SEND_CID)
+ {
+ cmd |= EMMC_CMD_RESP_LENGTH;
+ }
+ else if (opcode == SEND_CSD)
+ {
+ cmd |= EMMC_CMD_RESP_LENGTH;
+ }
+ else if (opcode == STOP_TRANS)
+ {
+ cmd |= EMMC_CMD_STOP_CMD;
+ }
+ break;
+ }
+
+ /* Enable error interrupts */
+
+ mask |= EMMC_INTSTS_RCRC | EMMC_INTSTS_DCRC |
+ EMMC_INTSTS_DRTO | EMMC_INTSTS_HTO | EMMC_INTSTS_FRUN |
+ EMMC_INTSTS_HLE | EMMC_INTSTS_EBE;
+
+ putreg32(0xffffu, EMMC_RINTSTS);
+ putreg32(0x1ff37u, EMMC_IDSTS);
+ putreg32(mask, EMMC_INTMASK);
+
+ /* Send command */
+
+ putreg32(arg, EMMC_CMDARG);
+ putreg32(cmd, EMMC_CMD);
+
+ /* Wait for command or data transfer done */
+
+ emmc_takesem(&g_waitsem);
+
+ /* Restore interrupt mask */
+
+ putreg32(prev, EMMC_INTMASK);
+
+ /* Waiting for device ready */
+
+ do
+ {
+ status = getreg32(EMMC_STATUS);
+ }
+ while (status & EMMC_STATUS_DATA_BUSY);
+}
+
+static int emmc_is_powerup(void)
+{
+ int retry;
+
+ /* 5ms * 1000 times */
+
+ retry = 1000;
+ do
+ {
+ uint32_t response;
+ uint32_t intsts;
+
+ emmc_send(EMMC_NON_DATA, SEND_OP_COND,
+ OCR_SECTOR_MODE | OCR_DUAL_VOLT, EMMC_RESP_R3);
+ intsts = getreg32(EMMC_RINTSTS);
+ if (intsts & EMMC_INTSTS_RTO)
+ {
+ return -EIO;
+ }
+
+ response = getreg32(EMMC_RESP0);
+ if (response == (OCR_SECTOR_MODE | OCR_DUAL_VOLT | OCR_POWER_UP))
+ {
+ return 0;
+ }
+ up_mdelay(5);
+ }
+ while (--retry);
+
+ return -ETIMEDOUT;
+}
+
+static int emmc_switchcmd(uint8_t index, uint8_t val)
+{
+ emmc_send(EMMC_NON_DATA, SWITCH,
+ (uint32_t)((3u << 24) | (index << 16) | (val << 8)),
+ EMMC_RESP_R1B);
+ if (emmc_checkresponse())
+ {
+ return -EIO;
+ }
+
+ emmc_send(EMMC_NON_DATA, SEND_STATUS, EMMC_RCA << 16, EMMC_RESP_R1);
+ if (emmc_checkresponse())
+ {
+ return -EIO;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: emmc_interrupt
+ *
+ * Description:
+ * The eMMC Interrupt Handler
+ *
+ ****************************************************************************/
+
+static int emmc_interrupt(int irq, FAR void *context, FAR void *arg)
+{
+ uint32_t intr;
+
+ /* Get interrupt status and clear eMMC bits */
+
+ intr = getreg32(EMMC_MINTSTS) & ~EMMC_INTSTS_SDIO;
+ putreg32(intr, EMMC_RINTSTS);
+
+ if (intr & EMMC_INTSTS_RE)
+ {
+ ferr("Response error.\n");
+ }
+
+ if (intr & EMMC_INTSTS_CD)
+ {
+ /* Command done */
+ }
+
+ if (intr & EMMC_INTSTS_DTO)
+ {
+ /* Data transfer over */
+ }
+
+ if (intr & EMMC_INTSTS_TXDR)
+ {
+ ferr("Transmit FIFO data request.\n");
+ }
+
+ if (intr & EMMC_INTSTS_RXDR)
+ {
+ ferr("Receive FIFO data request.\n");
+ }
+
+ if (intr & EMMC_INTSTS_RCRC)
+ {
+ ferr("Response CRC error.\n");
+ }
+
+ if (intr & EMMC_INTSTS_DCRC)
+ {
+ ferr("Data CRC error.\n");
+ }
+
+ if (intr & EMMC_INTSTS_RTO)
+ {
+ ferr("Response timeout/Boot Ack Received.\n");
+ }
+
+ if (intr & EMMC_INTSTS_DRTO)
+ {
+ ferr("Data read timeout/Boot Data Start.\n");
+ }
+
+ if (intr & EMMC_INTSTS_HTO)
+ {
+ ferr("Data stavation-by-host timeout/Volt_switch_int.\n");
+ }
+
+ if (intr & EMMC_INTSTS_FRUN)
+ {
+ ferr("FIFO underrun/overrun error.\n");
+ }
+
+ if (intr & EMMC_INTSTS_HLE)
+ {
+ ferr("Hardware locked write error.\n");
+ }
+
+ if (intr & EMMC_INTSTS_BCI)
+ {
+ /* Start-bit error/Busy clear interrupt. */
+ }
+
+ if (intr & EMMC_INTSTS_ACD)
+ {
+ /* Auto command done */
+ }
+
+ if (intr & EMMC_INTSTS_EBE)
+ {
+ ferr("End-bit error/write no CRC.\n");
+ }
+
+ emmc_givesem(&g_waitsem);
+
+ return OK;
+}
+
+static void emmc_pincontrol(bool on)
+{
+ if (on)
+ {
+ CXD56_PIN_CONFIGS(PINCONFS_EMMC);
+ }
+ else
+ {
+ CXD56_PIN_CONFIGS(PINCONFS_EMMC_GPIO);
+ }
+}
+
+static int emmc_hwinitialize(void)
+{
+ int ret = OK;
+
+ cxd56_emmc_clock_enable(1, 1, 0);
+
+ /* Configure pin */
+
+ emmc_pincontrol(true);
+
+ /* Setup IRQ before command send */
+
+ emmc_initregister();
+
+ emmc_changeclock(EMMC_CLKDIV_UNDER_400KHZ);
+
+ irq_attach(CXD56_IRQ_EMMC, emmc_interrupt, NULL);
+
+ up_enable_irq(CXD56_IRQ_EMMC);
+
+ emmc_send(EMMC_NON_DATA, GO_IDLE_STATE, 0, EMMC_NON_RESP);
+
+ if ((ret = emmc_is_powerup()) != 0)
+ {
+ goto errout;
+ }
+
+ emmc_send(EMMC_NON_DATA, ALL_SEND_CID, 0, EMMC_RESP_R2);
+ emmc_send(EMMC_NON_DATA, SET_RELATIVE_ADDR, EMMC_RCA << 16, EMMC_RESP_R1);
+ if (emmc_checkresponse())
+ {
+ goto errout;
+ }
+
+#ifdef EMMC_USE_SEND_CSD
+ emmc_send(EMMC_NON_DATA, SEND_CSD, (EMMC_RCA << 16), EMMC_RESP_R2);
+#endif
+
+ emmc_send(EMMC_NON_DATA, SELECT_DESELECT, (EMMC_RCA << 16), EMMC_RESP_R1);
+ if (emmc_checkresponse())
+ {
+ goto errout;
+ }
+
+ ret = emmc_switchcmd(EXTCSD_HS_TIMING, EXTCSD_HS_TIMING_HIGH_SPEED);
+ if (ret)
+ {
+ goto errout;
+ }
+
+ ret = emmc_switchcmd(EXTCSD_BUS_WIDTH, EXTCSD_BUS_WIDTH_4BIT_SDR);
+ if (ret)
+ {
+ goto errout;
+ }
+
+ putreg32(EMMC_CTYPE_4BIT_MODE, EMMC_CTYPE);
+
+ emmc_changeclock(EMMC_CLKDIV_NON_DIV);
+
+ ret = emmc_switchcmd(EXTCSD_PON, EXTCSD_PON_POWERED_ON);
+ if (ret)
+ {
+ goto errout;
+ }
+
+ return OK;
+
+errout:
+ up_disable_irq(CXD56_IRQ_EMMC);
+ emmc_pincontrol(true);
+ cxd56_emmc_clock_disable();
+
+ return ret;
+}
+
+static int cxd56_emmc_readsectors(FAR struct cxd56_emmc_state_s *priv,
+ void *buf,
+ size_t start_sector,
+ unsigned int nsectors)
+{
+ struct emmc_dma_desc_s *descs;
+ uint32_t idsts;
+ int ret = OK;
+
+ descs = emmc_setupdma(buf, nsectors * SECTOR_SIZE);
+ if (!descs)
+ {
+ ferr("Building descriptor failed.\n");
+ return -ENOMEM;
+ }
+
+ emmc_takesem(&priv->excsem);
+
+ putreg32(nsectors * SECTOR_SIZE, EMMC_BYTCNT);
+ emmc_send(EMMC_NON_DATA, SET_BLOCK_COUNT, nsectors, EMMC_RESP_R1);
+
+ /* Check command error */
+
+ if (emmc_checkresponse())
+ {
+ ferr("SET_BLOCK_COUNT failed.\n");
+ ret = -EIO;
+ goto finish;
+ }
+
+ emmc_send(EMMC_DATA_READ, READ_MULTIPLE_BLOCK, start_sector, EMMC_RESP_R1);
+
+ /* Check command error */
+
+ if (emmc_checkresponse())
+ {
+ ferr("READ_MULTIPLE_BLOCK failed.\n");
+ ret = -EIO;
+ goto finish;
+ }
+
+ /* Check DMA status */
+
+ idsts = getreg32(EMMC_IDSTS);
+ if (idsts &
+ (EMMC_IDSTS_FBE | EMMC_IDSTS_DU | EMMC_IDSTS_CES | EMMC_IDSTS_AIS))
+ {
+ ferr("DMA status failed. %08x\n", idsts);
+ ret = -EIO;
+ }
+
+ finish:
+ emmc_givesem(&priv->excsem);
+ kmm_free(descs);
+
+ return ret;
+}
+
+#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY)
+static int cxd56_emmc_writesectors(FAR struct cxd56_emmc_state_s *priv,
+ const void *buf, size_t start_sector,
+ unsigned int nsectors)
+{
+ struct emmc_dma_desc_s *descs;
+ uint32_t idsts;
+ int ret = OK;
+
+ descs = emmc_setupdma((void *)buf, nsectors * SECTOR_SIZE);
+ if (!descs)
+ {
+ return -ENOMEM;
+ }
+
+ emmc_takesem(&priv->excsem);
+
+ putreg32(nsectors * SECTOR_SIZE, EMMC_BYTCNT);
+ emmc_send(EMMC_NON_DATA, SET_BLOCK_COUNT, nsectors, EMMC_RESP_R1);
+
+ /* Check command error */
+
+ if (emmc_checkresponse())
+ {
+ ferr("SET_BLOCK_COUNT failed.\n");
+ ret = -EIO;
+ goto finish;
+ }
+
+ emmc_send(EMMC_DATA_WRITE, WRITE_MULTIPLE_BLOCK,
+ start_sector, EMMC_RESP_R1);
+
+ /* Check command error */
+
+ if (emmc_checkresponse())
+ {
+ ferr("WRITE_MULTIPLE_BLOCK failed.\n");
+ ret = -EIO;
+ goto finish;
+ }
+
+ /* Check DMA status */
+
+ idsts = getreg32(EMMC_IDSTS);
+ if (idsts &
+ (EMMC_IDSTS_FBE | EMMC_IDSTS_DU | EMMC_IDSTS_CES | EMMC_IDSTS_AIS))
+ {
+ ferr("DMA status error. %08x\n", idsts);
+ ret = -EIO;
+ }
+
+ emmc_send(EMMC_NON_DATA, SEND_STATUS, EMMC_RCA << 16, EMMC_RESP_R1);
+
+ /* Check command error */
+
+ if (emmc_checkresponse())
+ {
+ ferr("SEND_STATUS failed.\n");
+ ret = -EIO;
+ goto finish;
+ }
+
+ emmc_flushwritefifo();
+
+ finish:
+ emmc_givesem(&priv->excsem);
+ kmm_free(descs);
+
+ return ret;
+}
+#endif
+
+static int cxd56_emmc_open(FAR struct inode *inode)
+{
+ FAR struct cxd56_emmc_state_s *priv;
+
+ DEBUGASSERT(inode && inode->i_private);
+ priv = (FAR struct cxd56_emmc_state_s *)inode->i_private;
+
+ /* Just increment the reference count on the driver */
+
+ emmc_takesem(&priv->excsem);
+ priv->crefs++;
+ emmc_givesem(&priv->excsem);
+ return OK;
+}
+
+static int cxd56_emmc_close(FAR struct inode *inode)
+{
+ FAR struct cxd56_emmc_state_s *priv;
+
+ DEBUGASSERT(inode && inode->i_private);
+ priv = (FAR struct cxd56_emmc_state_s *)inode->i_private;
+
+ /* Decrement the reference count on the block driver */
+
+ DEBUGASSERT(priv->crefs > 0);
+ emmc_takesem(&priv->excsem);
+ priv->crefs--;
+ emmc_givesem(&priv->excsem);
+ return OK;
+}
+
+static ssize_t cxd56_emmc_read(FAR struct inode *inode, unsigned char *buffer,
+ size_t start_sector, unsigned int nsectors)
+{
+ FAR struct cxd56_emmc_state_s *priv;
+ int ret;
+
+ DEBUGASSERT(inode && inode->i_private);
+ priv = (FAR struct cxd56_emmc_state_s *)inode->i_private;
+
+ finfo("Read sector %d (%d sectors) to %p\n",
+ start_sector, nsectors, buffer);
+
+ ret = cxd56_emmc_readsectors(priv, buffer, start_sector, nsectors);
+ if (ret)
+ {
+ ferr("Read sector failed. %d\n", ret);
+ return 0;
+ }
+
+ return nsectors;
+}
+
+#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY)
+static ssize_t cxd56_emmc_write(FAR struct inode *inode,
+ const unsigned char *buffer,
+ size_t start_sector,
+ unsigned int nsectors)
+{
+ FAR struct cxd56_emmc_state_s *priv;
+ int ret;
+
+ DEBUGASSERT(inode && inode->i_private);
+ priv = (FAR struct cxd56_emmc_state_s *)inode->i_private;
+
+ finfo("Write %p to sector %d (%d sectors)\n", buffer,
+ start_sector, nsectors);
+
+ ret = cxd56_emmc_writesectors(priv, buffer, start_sector, nsectors);
+ if (ret)
+ {
+ ferr("Write sector failed. %d\n", ret);
+ return 0;
+ }
+
+ return nsectors;
+}
+#endif
+
+static int cxd56_emmc_geometry(FAR struct inode *inode,
+ struct geometry *geometry)
+{
+ FAR struct cxd56_emmc_state_s *priv;
+
+ DEBUGASSERT(inode && inode->i_private);
+ priv = (FAR struct cxd56_emmc_state_s *)inode->i_private;
+
+ geometry->geo_available = true;
+ geometry->geo_mediachanged = false;
+#if defined(CONFIG_FS_WRITABLE)
+ geometry->geo_writeenabled = true;
+#else
+ geometry->geo_writeenabled = false;
+#endif
+ geometry->geo_nsectors = priv->total_sectors;
+ geometry->geo_sectorsize = SECTOR_SIZE;
+
+ return OK;
+}
+
+int cxd56_emmcinitialize(void)
+{
+ FAR struct cxd56_emmc_state_s *priv;
+ FAR uint8_t *buf;
+ FAR struct emmc_dma_desc_s *descs;
+ int ret;
+
+ priv = &g_emmcdev;
+
+ memset(priv, 0, sizeof(struct cxd56_emmc_state_s));
+ sem_init(&priv->excsem, 0, 1);
+ sem_init(&g_waitsem, 0, 0);
+
+ ret = emmc_hwinitialize();
+ if (ret != OK)
+ {
+ return -EIO;
+ }
+
+ buf = (FAR uint8_t *)kmm_malloc(SECTOR_SIZE);
+ if (buf)
+ {
+ putreg32(SECTOR_SIZE, EMMC_BYTCNT);
+ descs = emmc_setupdma(buf, SECTOR_SIZE);
+ if (descs)
+ {
+ emmc_send(EMMC_DATA_READ, SEND_EXT_CSD, 0, EMMC_RESP_R1);
+ if (emmc_checkresponse())
+ {
+ kmm_free(buf);
+ return -EIO;
+ }
+ priv->total_sectors = *(FAR uint32_t *)&buf[EXTCSD_SEC_COUNT];
+ kmm_free(descs);
+ }
+ kmm_free(buf);
+ }
+
+ ret = register_blockdriver("/dev/emmc0", &g_bops, 0, priv);
+ if (ret)
+ {
+ ferr("register_blockdriver failed: %d\n", -ret);
+ return ret;
+ }
+
+ return OK;
+}
+
+int emmc_uninitialize(void)
+{
+ /* Send power off command */
+
+ emmc_switchcmd(EXTCSD_PON, EXTCSD_PON_POWERED_OFF_LONG);
+
+ up_disable_irq(CXD56_IRQ_EMMC);
+
+ /* Configure pin */
+
+ emmc_pincontrol(false);
+
+ cxd56_emmc_clock_disable();
+
+ return 0;
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_emmc.h b/arch/arm/src/cxd56xx/cxd56_emmc.h
new file mode 100644
index 00000000000..078ad961dc6
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_emmc.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_emmc.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_EMMC_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_EMMC_H
+
+#include
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+int cxd56_emmcinitialize(void);
+void cxd56_emmcuninitialize(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_EMMC_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_farapi.c b/arch/arm/src/cxd56xx/cxd56_farapi.c
new file mode 100644
index 00000000000..db0cd8a7fdb
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_farapi.c
@@ -0,0 +1,287 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_farapi.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "up_arch.h"
+#include "up_internal.h"
+#include "chip.h"
+#include "cxd56_icc.h"
+#include "cxd56_config.h"
+#include "cxd56_farapistub.h"
+#include "hardware/cxd5602_backupmem.h"
+
+int PM_WakeUpCpu(int cpuid);
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define GPS_CPU_ID (1)
+
+#ifndef CONFIG_CXD56_FARAPI_VERSION_CHECK
+#define CONFIG_CXD56_FARAPI_VERSION_CHECK 1
+#endif
+
+#define CPU_ID (CXD56_CPU_BASE + 0x40)
+
+/****************************************************************************
+ * Private Type
+ ****************************************************************************/
+
+typedef int farapicallback(void *data);
+
+struct modulelist_s
+{
+ void *mod;
+ int cpuno;
+ void *reserved;
+ int16_t mbxid;
+};
+
+struct apimsg_s
+{
+ int id;
+ void *arg;
+ int16_t mbxid;
+ int16_t flagid;
+ int flagbitno;
+};
+
+struct farcallback_s
+{
+ int (*cbfunc)(void *); /* pointer to callback function */
+ void *data; /* callback data */
+ int flagbitno; /* callback eventflag bitno */
+};
+
+struct farmsghead_s
+{
+ struct farmsghead_s *next;
+};
+
+struct farmsg_s
+{
+ struct farmsghead_s head; /* message head */
+ int cpuid; /* CPU ID of API caller */
+ int modid; /* module table offset */
+ union
+ {
+ struct apimsg_s api;
+ struct farcallback_s cb;
+ } u;
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+extern char Image$$MODLIST$$Base[];
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static sem_t g_farwait;
+static sem_t g_farlock;
+static struct pm_cpu_wakelock_s g_wlock = {
+ .count = 0,
+ .info = PM_CPUWAKELOCK_TAG('R', 'M', 0),
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int farapi_semtake(sem_t *id)
+{
+ while (sem_wait(id) != 0)
+ {
+ ASSERT(errno == EINTR);
+ }
+ return OK;
+}
+
+#ifdef CONFIG_CXD56_FARAPI_DEBUG
+static void dump_farapi_message(struct farmsg_s *msg)
+{
+ _info("cpuid : %d\n", msg->cpuid);
+ _info("modid : %d\n", msg->modid);
+ _info("id : %d\n", msg->u.api.id);
+ _info("arg : %08x\n", msg->u.api.arg);
+ _info("mbxid : %d\n", msg->u.api.mbxid);
+ _info("flagid: %d\n", msg->u.api.flagid);
+ _info("flagbitno: %d\n", msg->u.api.flagbitno);
+}
+# define fainfo(x, ...) _info(x, ##__VA_ARGS__)
+#else
+# define dump_farapi_message(x)
+# define fainfo(x, ...)
+#endif
+
+static int cxd56_sendmsg(int cpuid, int protoid, int msgtype, uint16_t pdata,
+ uint32_t data)
+{
+ iccmsg_t msg;
+
+ msg.cpuid = cpuid;
+ msg.msgid = msgtype << 4;
+ msg.protodata = pdata;
+ msg.data = data;
+ return cxd56_iccsend(protoid, &msg, 0);
+}
+
+static int cxd56_farapidonehandler(int cpuid, int protoid,
+ uint32_t pdata, uint32_t data,
+ FAR void *userdata)
+{
+ /* Receive event flag message as Far API done.
+ * We need only far API done event.
+ */
+
+ if (protoid == CXD56_PROTO_FLG && (pdata & 0xf) == 0x7)
+ {
+ /* Send event flag response */
+
+ cxd56_sendmsg(cpuid, CXD56_PROTO_FLG, 5, pdata & 0xff00, 0);
+ sem_post(&g_farwait);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+__attribute__((used))
+void farapi_main(int id, void *arg, struct modulelist_s *mlist)
+{
+ struct farmsg_s msg;
+ struct apimsg_s *api;
+ int ret;
+#ifdef CONFIG_CXD56_GNSS_HOT_SLEEP
+ uint32_t gnscken;
+
+ if (mlist->cpuno == GPS_CPU_ID)
+ {
+ gnscken = getreg32(CXD56_TOPREG_GNSDSP_CKEN);
+ if (((gnscken & GNSDSP_CKEN_P1) != GNSDSP_CKEN_P1) &&
+ ((gnscken & GNSDSP_CKEN_COP) != GNSDSP_CKEN_COP))
+ {
+ PM_WakeUpCpu(GPS_CPU_ID);
+ }
+ }
+#endif
+
+ farapi_semtake(&g_farlock);
+
+ api = &msg.u.api;
+
+ msg.cpuid = getreg32(CPU_ID);
+ msg.modid = mlist - (struct modulelist_s *)&Image$$MODLIST$$Base;
+
+ api->id = id;
+ api->arg = arg;
+ api->mbxid = mlist->mbxid;
+ api->flagid = (msg.cpuid + 1) << 8 | 7; /* 7 is a magic. not zero */
+ api->flagbitno = 0; /* ignore */
+
+ dump_farapi_message(&msg);
+
+ /* Send request by mailbox protocol */
+
+ ret = cxd56_sendmsg(mlist->cpuno, CXD56_PROTO_MBX, 4, 1 << 8 | 1,
+ (uint32_t)(uintptr_t)&msg);
+ if (ret)
+ {
+ _err("Failed far api push\n");
+ goto err;
+ }
+
+ /* Suppress hot sleep until Far API done */
+
+ up_pm_acquire_wakelock(&g_wlock);
+
+ /* Wait event flag message as Far API done */
+
+ farapi_semtake(&g_farwait);
+
+ /* Permit hot sleep with Far API done */
+
+ up_pm_release_wakelock(&g_wlock);
+
+ dump_farapi_message(&msg);
+
+err:
+ sem_post(&g_farlock);
+}
+
+void cxd56_farapiinitialize(void)
+{
+#ifdef CONFIG_CXD56_FARAPI_VERSION_CHECK
+ if (GET_SYSFW_VERSION_BUILD() < FARAPISTUB_VERSION)
+ {
+ _alert("Mismatched version: loader(%d) != Self(%d)\n",
+ GET_SYSFW_VERSION_BUILD(), FARAPISTUB_VERSION);
+ _alert("Please update loader and gnssfw firmwares!!\n");
+# ifdef CONFIG_CXD56_FARAPI_VERSION_FAILED_PANIC
+ PANIC();
+# endif
+ }
+#endif
+ sem_init(&g_farlock, 0, 1);
+ sem_init(&g_farwait, 0, 0);
+
+ cxd56_iccinit(CXD56_PROTO_MBX);
+ cxd56_iccinit(CXD56_PROTO_FLG);
+
+ /* Setup CPU FIFO interrupt for SYS and GNSS */
+
+ cxd56_iccregisterhandler(CXD56_PROTO_MBX, cxd56_farapidonehandler, NULL);
+ cxd56_iccregisterhandler(CXD56_PROTO_FLG, cxd56_farapidonehandler, NULL);
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_farapi.h b/arch/arm/src/cxd56xx/cxd56_farapi.h
new file mode 100644
index 00000000000..eb4df75e5b7
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_farapi.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_farapi.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_FARAPI_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_FARAPI_H
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif /* ARCH_ARM_SRC_CXD56XX_CXD56_FARAPI_H */
+
+void cxd56_farapiinitialize(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_FARAPI_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_farapistub.S b/arch/arm/src/cxd56xx/cxd56_farapistub.S
new file mode 100644
index 00000000000..28cddfc510a
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_farapistub.S
@@ -0,0 +1,1186 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_farapistub.S
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+ .syntax unified
+ .section .text.stub
+ .align 1
+1:
+ push {r0-r3}
+ adr r1, 3f
+ mov r0, r12
+ subs r0, r0, r1
+ mov r1, sp
+ ldr r2, 2f
+ push {r4, lr}
+ bl farapi_main
+ pop {r0, r1}
+ mov r12, r1
+ pop {r0-r3}
+ bx r12
+
+ .align 2
+2:
+ .word _modulelist_power_mgr
+
+ .align 2
+3:
+
+ /* PM_GpsPllClockSetSource */
+ nop
+ nop
+
+ /* PM_PmicGetChargingPortType */
+ nop
+ nop
+
+ /* PM_PmicSetChargingCurrentValue */
+ nop
+ nop
+
+ /* PM_PmicStartCharging */
+ nop
+ nop
+
+ /* PM_PmicStopCharging */
+ nop
+ nop
+
+ /* PM_PeriPowerOn */
+ nop
+ nop
+
+ /* PM_PeriPowerOff */
+ nop
+ nop
+
+ /* _PM_PeriClockEnable */
+ nop
+ nop
+
+ /* _PM_PeriClockDisable */
+ nop
+ nop
+
+ /* _PM_UpdateCpuFreqInfo */
+ nop
+ nop
+
+ /* PM_PmicPowerOn */
+ nop
+ nop
+
+ /* PM_PmicPowerOff */
+ nop
+ nop
+
+ /* PM_SetWakeupTrigger */
+ nop
+ nop
+
+ /* PM_HostifClockEnable */
+ nop
+ nop
+
+ /* PM_HostifClockDisable */
+ nop
+ nop
+
+ .global PM_StartCpu
+ .thumb_func
+PM_StartCpu:
+ mov r12, pc
+ b 1b
+
+ .global PM_StopCpu
+ .thumb_func
+PM_StopCpu:
+ mov r12, pc
+ b 1b
+
+ .global PM_SleepCpu
+ .thumb_func
+PM_SleepCpu:
+ mov r12, pc
+ b 1b
+
+ .global PM_WakeUpCpu
+ .thumb_func
+PM_WakeUpCpu:
+ mov r12, pc
+ b 1b
+
+ .global PM_ColdSleep
+ .thumb_func
+PM_ColdSleep:
+ mov r12, pc
+ b 1b
+
+ .global PM_DeepSleep
+ .thumb_func
+PM_DeepSleep:
+ mov r12, pc
+ b 1b
+
+ .global PM_Reboot
+ .thumb_func
+PM_Reboot:
+ mov r12, pc
+ b 1b
+
+ .global PM_LoadImage
+ .thumb_func
+PM_LoadImage:
+ mov r12, pc
+ b 1b
+
+ /* PM_LoadImageToAddress */
+ nop
+ nop
+
+ /* PM_RamControlByAddress */
+ nop
+ nop
+
+ /* PM_ChangeClock */
+ nop
+ nop
+
+ .global PM_PmicControl
+ .thumb_func
+PM_PmicControl:
+ mov r12, pc
+ b 1b
+
+ /* PM_BootCpu */
+ nop
+ nop
+
+ /* PM_BootCpuWithWaitMode */
+ nop
+ nop
+
+ /* PM_GetClock */
+ nop
+ nop
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_power_mgr
+_modulelist_power_mgr:
+ .weak _module_power_mgr
+ .word _module_power_mgr
+ .word 0
+ .word 0
+ .word 0
+
+ .syntax unified
+ .section .text.stub
+ .align 1
+1:
+ push {r0-r3}
+ adr r1, 3f
+ mov r0, r12
+ subs r0, r0, r1
+ mov r1, sp
+ ldr r2, 2f
+ push {r4, lr}
+ bl farapi_main
+ pop {r0, r1}
+ mov r12, r1
+ pop {r0-r3}
+ bx r12
+
+ .align 2
+2:
+ .word _modulelist_flash_mgr
+
+ .align 2
+3:
+
+ /* FM_GetRegistryValue */
+ nop
+ nop
+
+ /* FM_SetRegistryValue */
+ nop
+ nop
+
+ /* FM_SetRegistryValueList */
+ nop
+ nop
+
+ /* FM_DeleteRegistryKey */
+ nop
+ nop
+
+ /* FM_GenerateRegistryKey */
+ nop
+ nop
+
+ /* FM_Sync */
+ nop
+ nop
+
+ /* FM_FileOpen */
+ nop
+ nop
+
+ /* FM_FileClose */
+ nop
+ nop
+
+ /* FM_FileRead */
+ nop
+ nop
+
+ /* FM_FileWrite */
+ nop
+ nop
+
+ /* FM_FileSeek */
+ nop
+ nop
+
+ /* FM_FileFlush */
+ nop
+ nop
+
+ /* FM_FileDelete */
+ nop
+ nop
+
+ .global FM_RawWrite
+ .thumb_func
+FM_RawWrite:
+ mov r12, pc
+ b 1b
+
+ .global FM_RawRead
+ .thumb_func
+FM_RawRead:
+ mov r12, pc
+ b 1b
+
+ .global FM_RawEraseSector
+ .thumb_func
+FM_RawEraseSector:
+ mov r12, pc
+ b 1b
+
+ /* FM_FileRename */
+ nop
+ nop
+
+ /* FM_FileGetAttr */
+ nop
+ nop
+
+ /* FM_FileSetAttr */
+ nop
+ nop
+
+ /* FM_FileClearAttr */
+ nop
+ nop
+
+ .global FM_RawVerifyWrite
+ .thumb_func
+FM_RawVerifyWrite:
+ mov r12, pc
+ b 1b
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_flash_mgr
+_modulelist_flash_mgr:
+ .weak _module_flash_mgr
+ .word _module_flash_mgr
+ .word 0
+ .word 0
+ .word 0
+
+ .syntax unified
+ .section .text.stub
+ .align 1
+1:
+ push {r0-r3}
+ adr r1, 3f
+ mov r0, r12
+ subs r0, r0, r1
+ mov r1, sp
+ ldr r2, 2f
+ push {r4, lr}
+ bl farapi_main
+ pop {r0, r1}
+ mov r12, r1
+ pop {r0-r3}
+ bx r12
+
+ .align 2
+2:
+ .word _modulelist_rtc_mgr
+
+ .align 2
+3:
+
+ /* SYS_RtcMgrSetTime */
+ nop
+ nop
+
+ /* SYS_RtcMgrGetTime */
+ nop
+ nop
+
+ /* SYS_RtcMgrConvTime */
+ nop
+ nop
+
+ /* SYS_RtcMgrConvCalendarTime */
+ nop
+ nop
+
+ /* SYS_RtcMgrSetCalendarTime */
+ nop
+ nop
+
+ /* SYS_RtcMgrGetCalendarTime */
+ nop
+ nop
+
+ /* SYS_RtcMgrAdjustTime */
+ nop
+ nop
+
+ /* SYS_RtcMgrRequestAlarm */
+ nop
+ nop
+
+ /* SYS_RtcMgrCancelAlarm */
+ nop
+ nop
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_rtc_mgr
+_modulelist_rtc_mgr:
+ .weak _module_rtc_mgr
+ .word _module_rtc_mgr
+ .word 0
+ .word 0
+ .word 0
+
+ .syntax unified
+ .section .text.stub
+ .align 1
+1:
+ push {r0-r3}
+ adr r1, 3f
+ mov r0, r12
+ subs r0, r0, r1
+ mov r1, sp
+ ldr r2, 2f
+ push {r4, lr}
+ bl farapi_main
+ pop {r0, r1}
+ mov r12, r1
+ pop {r0-r3}
+ bx r12
+
+ .align 2
+2:
+ .word _modulelist_gnss_pwr
+
+ .align 2
+3:
+
+ /* GNSP_ChangeClockBoot */
+ nop
+ nop
+
+ /* GNSP_ChangeClockNormal */
+ nop
+ nop
+
+ /* GNSP_SetAttribute */
+ nop
+ nop
+
+ /* GNSP_GetPowerStatus */
+ nop
+ nop
+
+ /* GNSP_PonGnss */
+ nop
+ nop
+
+ /* GNSP_PoffGnss */
+ nop
+ nop
+
+ /* GNSP_Sleep */
+ nop
+ nop
+
+ /* GNSP_Wakeup */
+ nop
+ nop
+
+ /* GNSP_SetWakeupTime */
+ nop
+ nop
+
+ /* GNSP_GetAttribute */
+ nop
+ nop
+
+ /* GNSP_ClockOn */
+ nop
+ nop
+
+ /* GNSP_ClockOff */
+ nop
+ nop
+
+ /* GNSP_ChangeMode */
+ nop
+ nop
+
+ /* GNSP_EnableIo */
+ nop
+ nop
+
+ /* GNSP_ControlGpioOut */
+ nop
+ nop
+
+ /* GNSP_Debug */
+ nop
+ nop
+
+ /* GNSP_ChangeClockRtc */
+ nop
+ nop
+
+ /* GNSP_ChangeClockSFCClkup */
+ nop
+ nop
+
+ /* GNSP_ChangeClockSFCClkdwn */
+ nop
+ nop
+
+ /* GNSP_GetBootCause */
+ nop
+ nop
+
+ /* GNSP_GetWakeupTrigger */
+ nop
+ nop
+
+ /* GNSP_SelfReboot */
+ nop
+ nop
+
+ /* GNSP_Start_KeepPPSOut */
+ nop
+ nop
+
+ /* GNSP_Stop_KeepPPSOut */
+ nop
+ nop
+
+ /* GNSP_SetSleepState */
+ nop
+ nop
+
+ /* GNSP_FreeSysMemory */
+ nop
+ nop
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_gnss_pwr
+_modulelist_gnss_pwr:
+ .weak _module_gnss_pwr
+ .word _module_gnss_pwr
+ .word 0
+ .word 0
+ .word 0
+
+ .syntax unified
+ .section .text.stub
+ .align 1
+1:
+ push {r0-r3}
+ adr r1, 3f
+ mov r0, r12
+ subs r0, r0, r1
+ mov r1, sp
+ ldr r2, 2f
+ push {r4, lr}
+ bl farapi_main
+ pop {r0, r1}
+ mov r12, r1
+ pop {r0-r3}
+ bx r12
+
+ .align 2
+2:
+ .word _modulelist_aca
+
+ .align 2
+3:
+
+ .global AS_AcaControl
+ .thumb_func
+AS_AcaControl:
+ mov r12, pc
+ b 1b
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_aca
+_modulelist_aca:
+ .weak _module_aca
+ .word _module_aca
+ .word 0
+ .word 0
+ .word 0
+
+ .syntax unified
+ .section .text.stub
+ .align 1
+1:
+ push {r0-r3}
+ adr r1, 3f
+ mov r0, r12
+ subs r0, r0, r1
+ mov r1, sp
+ ldr r2, 2f
+ push {r4, lr}
+ bl farapi_main
+ pop {r0, r1}
+ mov r12, r1
+ pop {r0-r3}
+ bx r12
+
+ .align 2
+2:
+ .word _modulelist_pinconfig
+
+ .align 2
+3:
+
+ .global PD_PinConfigs
+ .thumb_func
+PD_PinConfigs:
+ mov r12, pc
+ b 1b
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_pinconfig
+_modulelist_pinconfig:
+ .weak _module_pinconfig
+ .word _module_pinconfig
+ .word 0
+ .word 0
+ .word 0
+
+ .syntax unified
+ .section .text.stub
+ .align 1
+1:
+ push {r0-r3}
+ adr r1, 3f
+ mov r0, r12
+ subs r0, r0, r1
+ mov r1, sp
+ ldr r2, 2f
+ push {r4, lr}
+ bl farapi_main
+ pop {r0, r1}
+ mov r12, r1
+ pop {r0-r3}
+ bx r12
+
+ .align 2
+2:
+ .word _modulelist_uart
+
+ .align 2
+3:
+
+ .global PD_UartInit
+ .thumb_func
+PD_UartInit:
+ mov r12, pc
+ b 1b
+
+ .global PD_UartUninit
+ .thumb_func
+PD_UartUninit:
+ mov r12, pc
+ b 1b
+
+ .global PD_UartConfiguration
+ .thumb_func
+PD_UartConfiguration:
+ mov r12, pc
+ b 1b
+
+ .global PD_UartEnable
+ .thumb_func
+PD_UartEnable:
+ mov r12, pc
+ b 1b
+
+ .global PD_UartDisable
+ .thumb_func
+PD_UartDisable:
+ mov r12, pc
+ b 1b
+
+ .global PD_UartReceive
+ .thumb_func
+PD_UartReceive:
+ mov r12, pc
+ b 1b
+
+ .global PD_UartSend
+ .thumb_func
+PD_UartSend:
+ mov r12, pc
+ b 1b
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_uart
+_modulelist_uart:
+ .weak _module_uart
+ .word _module_uart
+ .word 0
+ .word 0
+ .word 0
+
+ .syntax unified
+ .section .text.stub
+ .align 1
+1:
+ push {r0-r3}
+ adr r1, 3f
+ mov r0, r12
+ subs r0, r0, r1
+ mov r1, sp
+ ldr r2, 2f
+ push {r4, lr}
+ bl farapi_main
+ pop {r0, r1}
+ mov r12, r1
+ pop {r0-r3}
+ bx r12
+
+ .align 2
+2:
+ .word _modulelist_update_mgr
+
+ .align 2
+3:
+
+ .global UM_Init
+ .thumb_func
+UM_Init:
+ mov r12, pc
+ b 1b
+
+ .global UM_Open
+ .thumb_func
+UM_Open:
+ mov r12, pc
+ b 1b
+
+ .global UM_Commit
+ .thumb_func
+UM_Commit:
+ mov r12, pc
+ b 1b
+
+ .global UM_Close
+ .thumb_func
+UM_Close:
+ mov r12, pc
+ b 1b
+
+ .global UM_CheckPoint
+ .thumb_func
+UM_CheckPoint:
+ mov r12, pc
+ b 1b
+
+ .global UM_DoUpdateSequence
+ .thumb_func
+UM_DoUpdateSequence:
+ mov r12, pc
+ b 1b
+
+ .global UM_Abort
+ .thumb_func
+UM_Abort:
+ mov r12, pc
+ b 1b
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_update_mgr
+_modulelist_update_mgr:
+ .weak _module_update_mgr
+ .word _module_update_mgr
+ .word 0
+ .word 0
+ .word 0
+
+ .syntax unified
+ .section .text.stub
+ .align 1
+1:
+ push {r0-r3}
+ adr r1, 3f
+ mov r0, r12
+ subs r0, r0, r1
+ mov r1, sp
+ ldr r2, 2f
+ push {r4, lr}
+ bl farapi_main
+ pop {r0, r1}
+ mov r12, r1
+ pop {r0-r3}
+ bx r12
+
+ .align 2
+2:
+ .word _modulelist_gnss
+
+ .align 2
+3:
+
+ .global GD_Start
+ .thumb_func
+GD_Start:
+ mov r12, pc
+ b 1b
+
+ .global GD_Stop
+ .thumb_func
+GD_Stop:
+ mov r12, pc
+ b 1b
+
+ .global GD_SelectSatelliteSystem
+ .thumb_func
+GD_SelectSatelliteSystem:
+ mov r12, pc
+ b 1b
+
+ .global GD_GetSatelliteSystem
+ .thumb_func
+GD_GetSatelliteSystem:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetReceiverPositionEllipsoidal
+ .thumb_func
+GD_SetReceiverPositionEllipsoidal:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetReceiverPositionOrthogonal
+ .thumb_func
+GD_SetReceiverPositionOrthogonal:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetOperationMode
+ .thumb_func
+GD_SetOperationMode:
+ mov r12, pc
+ b 1b
+
+ .global GD_GetOperationMode
+ .thumb_func
+GD_GetOperationMode:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetTcxoOffset
+ .thumb_func
+GD_SetTcxoOffset:
+ mov r12, pc
+ b 1b
+
+ .global GD_GetTcxoOffset
+ .thumb_func
+GD_GetTcxoOffset:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetTime
+ .thumb_func
+GD_SetTime:
+ mov r12, pc
+ b 1b
+
+ .global GD_GetAlmanac
+ .thumb_func
+GD_GetAlmanac:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetAlmanac
+ .thumb_func
+GD_SetAlmanac:
+ mov r12, pc
+ b 1b
+
+ .global GD_GetEphemeris
+ .thumb_func
+GD_GetEphemeris:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetEphemeris
+ .thumb_func
+GD_SetEphemeris:
+ mov r12, pc
+ b 1b
+
+ .global GD_GetVarEphemeris
+ .thumb_func
+GD_GetVarEphemeris:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetVarEphemeris
+ .thumb_func
+GD_SetVarEphemeris:
+ mov r12, pc
+ b 1b
+
+ .global GD_StartGpsTest
+ .thumb_func
+GD_StartGpsTest:
+ mov r12, pc
+ b 1b
+
+ .global GD_StopGpsTest
+ .thumb_func
+GD_StopGpsTest:
+ mov r12, pc
+ b 1b
+
+ .global GD_GetGpsTestResult
+ .thumb_func
+GD_GetGpsTestResult:
+ mov r12, pc
+ b 1b
+
+ .global GD_SaveBackupdata
+ .thumb_func
+GD_SaveBackupdata:
+ mov r12, pc
+ b 1b
+
+ .global GD_EraseBackup
+ .thumb_func
+GD_EraseBackup:
+ mov r12, pc
+ b 1b
+
+ .global GD_CepSetAssistData
+ .thumb_func
+GD_CepSetAssistData:
+ mov r12, pc
+ b 1b
+
+ .global GD_CepEraseAssistData
+ .thumb_func
+GD_CepEraseAssistData:
+ mov r12, pc
+ b 1b
+
+ .global GD_CepCheckAssistData
+ .thumb_func
+GD_CepCheckAssistData:
+ mov r12, pc
+ b 1b
+
+ .global GD_CepGetAgeData
+ .thumb_func
+GD_CepGetAgeData:
+ mov r12, pc
+ b 1b
+
+ .global GD_CepInitAssistData
+ .thumb_func
+GD_CepInitAssistData:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetAcquist
+ .thumb_func
+GD_SetAcquist:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetFrameTime
+ .thumb_func
+GD_SetFrameTime:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetTauGps
+ .thumb_func
+GD_SetTauGps:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetTimeGps
+ .thumb_func
+GD_SetTimeGps:
+ mov r12, pc
+ b 1b
+
+ .global GD_ClearReceiverInfo
+ .thumb_func
+GD_ClearReceiverInfo:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetTowAssist
+ .thumb_func
+GD_SetTowAssist:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetUtcModel
+ .thumb_func
+GD_SetUtcModel:
+ mov r12, pc
+ b 1b
+
+ .global GD_SpectrumControl
+ .thumb_func
+GD_SpectrumControl:
+ mov r12, pc
+ b 1b
+
+ .global GD_ReadBuffer
+ .thumb_func
+GD_ReadBuffer:
+ mov r12, pc
+ b 1b
+
+ .global GD_WriteBuffer
+ .thumb_func
+GD_WriteBuffer:
+ mov r12, pc
+ b 1b
+
+ .global GD_SetNotifyMask
+ .thumb_func
+GD_SetNotifyMask:
+ mov r12, pc
+ b 1b
+
+ .global GD_GeoAddRegion
+ .thumb_func
+GD_GeoAddRegion:
+ mov r12, pc
+ b 1b
+
+ .global GD_GeoModifyRegion
+ .thumb_func
+GD_GeoModifyRegion:
+ mov r12, pc
+ b 1b
+
+ .global GD_GeoDeleteRegione
+ .thumb_func
+GD_GeoDeleteRegione:
+ mov r12, pc
+ b 1b
+
+ .global GD_GeoDeleteAllRegion
+ .thumb_func
+GD_GeoDeleteAllRegion:
+ mov r12, pc
+ b 1b
+
+ .global GD_GeoGetRegionData
+ .thumb_func
+GD_GeoGetRegionData:
+ mov r12, pc
+ b 1b
+
+ .global GD_GeoGetUsedRegionId
+ .thumb_func
+GD_GeoGetUsedRegionId:
+ mov r12, pc
+ b 1b
+
+ .global GD_GeoSetOpMode
+ .thumb_func
+GD_GeoSetOpMode:
+ mov r12, pc
+ b 1b
+
+ .global GD_GeoSetAllRgionNotifyRequest
+ .thumb_func
+GD_GeoSetAllRgionNotifyRequest:
+ mov r12, pc
+ b 1b
+
+ .global GD_RegisterGeofence
+ .thumb_func
+GD_RegisterGeofence:
+ mov r12, pc
+ b 1b
+
+ .global GD_ReleaseGeofence
+ .thumb_func
+GD_ReleaseGeofence:
+ mov r12, pc
+ b 1b
+
+ .global GD_RegisterPvtlog
+ .thumb_func
+GD_RegisterPvtlog:
+ mov r12, pc
+ b 1b
+
+ .global GD_ReleasePvtlog
+ .thumb_func
+GD_ReleasePvtlog:
+ mov r12, pc
+ b 1b
+
+ .global GD_PvtlogDeleteLog
+ .thumb_func
+GD_PvtlogDeleteLog:
+ mov r12, pc
+ b 1b
+
+ .global GD_PvtlogGetLogStatus
+ .thumb_func
+GD_PvtlogGetLogStatus:
+ mov r12, pc
+ b 1b
+
+ .global GD_RtkStart
+ .thumb_func
+GD_RtkStart:
+ mov r12, pc
+ b 1b
+
+ .global GD_RtkStop
+ .thumb_func
+GD_RtkStop:
+ mov r12, pc
+ b 1b
+
+ .global GD_RtkSetOutputInterval
+ .thumb_func
+GD_RtkSetOutputInterval:
+ mov r12, pc
+ b 1b
+
+ .global GD_RtkGetOutputInterval
+ .thumb_func
+GD_RtkGetOutputInterval:
+ mov r12, pc
+ b 1b
+
+ .global GD_RtkSetGnss
+ .thumb_func
+GD_RtkSetGnss:
+ mov r12, pc
+ b 1b
+
+ .global GD_RtkGetGnss
+ .thumb_func
+GD_RtkGetGnss:
+ mov r12, pc
+ b 1b
+
+ .global GD_RtkSetEphNotify
+ .thumb_func
+GD_RtkSetEphNotify:
+ mov r12, pc
+ b 1b
+
+ .global GD_RtkGetEphNotify
+ .thumb_func
+GD_RtkGetEphNotify:
+ mov r12, pc
+ b 1b
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_gnss
+_modulelist_gnss:
+ .weak _module_gnss
+ .word _module_gnss
+ .word 1
+ .word 0
+ .word 0
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_gnss_geofence
+_modulelist_gnss_geofence:
+ .weak _module_gnss_geofence
+ .word _module_gnss_geofence
+ .word 1
+ .word 0
+ .word 0
+
+ .section .modulelist, "ax"
+ .align 2
+ .global _modulelist_gnss_pvtlog
+_modulelist_gnss_pvtlog:
+ .weak _module_gnss_pvtlog
+ .word _module_gnss_pvtlog
+ .word 1
+ .word 0
+ .word 0
diff --git a/arch/arm/src/cxd56xx/cxd56_farapistub.h b/arch/arm/src/cxd56xx/cxd56_farapistub.h
new file mode 100644
index 00000000000..8a9fd33dd92
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_farapistub.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_farapistub.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_FARAPISTUB_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_FARAPISTUB_H
+
+#define FARAPISTUB_VERSION 17639
+
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_FARAPISTUB_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_gauge.c b/arch/arm/src/cxd56xx/cxd56_gauge.c
new file mode 100644
index 00000000000..6ddda2bc245
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_gauge.c
@@ -0,0 +1,440 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_gauge.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* CXD5247GF is Li-Ion Battery Charger with Power-Path Management.
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include "cxd56_pmic.h"
+
+#ifdef CONFIG_CXD56_GAUGE
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Debug ********************************************************************/
+
+#ifdef CONFIG_CXD56_GAUGE_DEBUG
+#define baterr(fmt, ...) logerr(fmt, ## __VA_ARGS__)
+#define batdbg(fmt, ...) logdebug(fmt, ## __VA_ARGS__)
+#else
+#define baterr(fmt, ...)
+#define batdbg(fmt, ...)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct bat_gauge_dev_s
+{
+ sem_t batsem;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int gauge_open(FAR struct file *filep);
+static int gauge_close(FAR struct file *filep);
+static ssize_t gauge_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen);
+static ssize_t gauge_write(FAR struct file *filep,
+ FAR const char *buffer, size_t buflen);
+static int gauge_ioctl(FAR struct file *filep, int cmd,
+ unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_gaugeops =
+{
+ gauge_open, /* open */
+ gauge_close, /* close */
+ gauge_read, /* read */
+ gauge_write, /* write */
+ 0, /* seek */
+ gauge_ioctl /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+ , NULL /* poll */
+#endif
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ , NULL /* unlink */
+#endif
+};
+
+static struct bat_gauge_dev_s g_gaugedev;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: gauge_get_status
+ ****************************************************************************/
+
+static int gauge_get_status(FAR enum battery_gauge_status_e *status)
+{
+ uint8_t state;
+ int ret;
+
+ if (status == NULL)
+ {
+ return -EINVAL;
+ }
+
+ *status = BATTERY_UNKNOWN;
+
+ ret = cxd56_pmic_getchargestate(&state);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+ switch (state)
+ {
+ /* Is the charging done? */
+
+ case PMIC_STAT_CHG_COMPLETE:
+ *status = BATTERY_FULL;
+ break;
+
+ /* Is the charging in progress? */
+
+ case PMIC_STAT_GB_QCKCHARGE:
+ case PMIC_STAT_GB_LOWCHARGE:
+ case PMIC_STAT_GB_HIGHCHARGE:
+ *status = BATTERY_CHARGING;
+ break;
+
+ /* Is the discharging */
+
+ case PMIC_STAT_CHG_STOP:
+ *status = BATTERY_DISCHARGING;
+ break;
+
+ default:
+ _info("Charge state %d\n", state);
+ *status = BATTERY_IDLE;
+ break;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: gauge_get_vol
+ ****************************************************************************/
+
+static int gauge_get_vol(FAR b16_t *voltage)
+{
+ struct pmic_gauge_s gauge;
+ int ret;
+
+ if (voltage == NULL)
+ {
+ return -EINVAL;
+ }
+
+ *voltage = 0;
+
+ ret = cxd56_pmic_get_gauge(&gauge);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+ *voltage = gauge.voltage * 112 / 100;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: gauge_get_capacity
+ ****************************************************************************/
+
+static int gauge_get_capacity(FAR b16_t *capacity)
+{
+ b16_t vol;
+ int lower;
+ int upper;
+ int ret;
+
+ if (capacity == NULL)
+ {
+ return -EINVAL;
+ }
+
+ /* Get current battery voltage and upper/lower limit settings from PMIC. */
+
+ ret = gauge_get_vol(&vol);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+ ret = cxd56_pmic_getchargevol(&upper);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+ ret = cxd56_pmic_getlowervol(&lower);
+ if (ret < 0)
+ {
+ return -EIO;
+ }
+
+ /* Calculate capacity (0-100%)
+ * Actually, battery voltage possible to be under lower limit voltage.
+ *
+ * NOTE: This logic is tentative, linear from lower to upper. But it
+ * depends on the battery. Thus, user should be apply a voltage
+ * characteristic for capacity calculation if you want to more accuracy.
+ */
+
+ if (vol > lower)
+ {
+ upper -= lower;
+ vol -= lower;
+ *capacity = (vol * 100) / upper;
+ }
+ else
+ {
+ *capacity = 0;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: gauge_online
+ ****************************************************************************/
+
+static int gauge_online(FAR bool *online)
+{
+ if (online == NULL)
+ {
+ return -EINVAL;
+ }
+
+ *online = true;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: gauge_open
+ *
+ * Description:
+ * This function is called whenever the battery device is opened.
+ *
+ ****************************************************************************/
+
+static int gauge_open(FAR struct file *filep)
+{
+ return OK;
+}
+
+/****************************************************************************
+ * Name: gauge_close
+ *
+ * Description:
+ * This routine is called when the battery device is closed.
+ *
+ ****************************************************************************/
+
+static int gauge_close(FAR struct file *filep)
+{
+ return OK;
+}
+
+/****************************************************************************
+ * Name: gauge_read
+ ****************************************************************************/
+
+static ssize_t gauge_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen)
+{
+ /* Return nothing read */
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: gauge_write
+ ****************************************************************************/
+
+static ssize_t gauge_write(FAR struct file *filep,
+ FAR const char *buffer, size_t buflen)
+{
+ /* Return nothing written */
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: gauge_ioctl
+ ****************************************************************************/
+
+static int gauge_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct bat_gauge_dev_s *priv = inode->i_private;
+ int ret = -ENOTTY;
+
+ sem_wait(&priv->batsem);
+
+ switch (cmd)
+ {
+ case BATIOC_STATE:
+ {
+ FAR enum battery_gauge_status_e *status =
+ (FAR enum battery_gauge_status_e *)(uintptr_t)arg;
+ ret = gauge_get_status(status);
+ }
+ break;
+
+ case BATIOC_VOLTAGE:
+ {
+ FAR b16_t *voltage = (FAR b16_t *)(uintptr_t)arg;
+ ret = gauge_get_vol(voltage);
+ }
+ break;
+
+ case BATIOC_CAPACITY:
+ {
+ FAR b16_t *capacity = (FAR b16_t *)(uintptr_t)arg;
+ ret = gauge_get_capacity(capacity);
+ }
+ break;
+
+ case BATIOC_ONLINE:
+ {
+ FAR bool *online = (FAR bool *)(uintptr_t)arg;
+ ret = gauge_online(online);
+ }
+ break;
+
+ default:
+ ret = -ENOTTY;
+ break;
+ }
+
+ sem_post(&priv->batsem);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_gauge_initialize
+ *
+ * Description:
+ * Initialize the CXD5247 battery driver.
+ *
+ * Input Parameters:
+ * devpath - Device file path
+ *
+ * Returned Value:
+ * Return 0 on success. Otherwise, return a negated errno.
+ *
+ ****************************************************************************/
+
+int cxd56_gauge_initialize(FAR const char *devpath)
+{
+ FAR struct bat_gauge_dev_s *priv = &g_gaugedev;
+ int ret;
+
+ /* Initialize the CXD5247 device structure */
+
+ sem_init(&priv->batsem, 0, 1);
+
+ /* Register battery driver */
+
+ ret = register_driver(devpath, &g_gaugeops, 0666, priv);
+ if (ret < 0)
+ {
+ _err("ERROR: register_driver failed: %d\n", ret);
+ return -EFAULT;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_gauge_uninitialize
+ *
+ * Description:
+ * Uninitialize the CXD5247 battery driver.
+ *
+ * Input Parameters:
+ * devpath - Device file path
+ *
+ * Returned Value:
+ * Return 0 on success. Otherwise, return a negated errno.
+ *
+ ****************************************************************************/
+
+int cxd56_gauge_uninitialize(FAR const char *devpath)
+{
+ (void) unregister_driver(devpath);
+
+ return OK;
+}
+
+#endif /* CONFIG_CXD56_GAUGE */
diff --git a/arch/arm/src/cxd56xx/cxd56_gauge.h b/arch/arm/src/cxd56xx/cxd56_gauge.h
new file mode 100644
index 00000000000..94e5e329037
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_gauge.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_gauge.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_GAUGE_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_GAUGE_H
+
+/* initialize function */
+
+int cxd56_gauge_initialize(FAR const char *devpath);
+int cxd56_gauge_uninitialize(FAR const char *devpath);
+
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_GAUGE_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_ge2d.c b/arch/arm/src/cxd56xx/cxd56_ge2d.c
new file mode 100644
index 00000000000..86ae1cc19c6
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_ge2d.c
@@ -0,0 +1,283 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_ge2d.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "up_arch.h"
+#include "chip.h"
+#include "cxd56_clock.h"
+
+#include "hardware/cxd56_ge2d.h"
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int ge2d_open(FAR struct file *filep);
+static int ge2d_close(FAR struct file *filep);
+static ssize_t ge2d_read(FAR struct file *filep, FAR char *buffer,
+ size_t len);
+static ssize_t ge2d_write(FAR struct file *filep, FAR const char *buffer,
+ size_t len);
+static int ge2d_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static int ge2d_semtake(sem_t *id);
+static void ge2d_semgive(sem_t *id);
+static int ge2d_irqhandler(int irq, FAR void *context, FAR void *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_ge2dfops =
+{
+ .open = ge2d_open,
+ .close = ge2d_close,
+ .read = ge2d_read,
+ .write = ge2d_write,
+ .seek = 0,
+ .ioctl = ge2d_ioctl,
+};
+
+static sem_t g_wait;
+static sem_t g_lock;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ge2d_semtake
+ ****************************************************************************/
+
+static int ge2d_semtake(sem_t *id)
+{
+ while (sem_wait(id) != 0)
+ {
+ ASSERT(errno == EINTR);
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Name: ge2d_semgive
+ ****************************************************************************/
+
+static void ge2d_semgive(sem_t *id)
+{
+ sem_post(id);
+}
+
+/****************************************************************************
+ * Name: ge2d_open
+ ****************************************************************************/
+
+static int ge2d_open(FAR struct file *filep)
+{
+ return 0;
+}
+
+/****************************************************************************
+ * Name: ge2d_close
+ ****************************************************************************/
+
+static int ge2d_close(FAR struct file *filep)
+{
+ return 0;
+}
+
+/****************************************************************************
+ * Name: ge2d_read
+ ****************************************************************************/
+
+static ssize_t ge2d_read(FAR struct file *filep, FAR char *buffer, size_t len)
+{
+ return 0;
+}
+
+/****************************************************************************
+ * Name: ge2d_write
+ ****************************************************************************/
+
+static ssize_t ge2d_write(FAR struct file *filep,
+ FAR const char *buffer,
+ size_t len)
+{
+ uint32_t bits;
+
+ /* GE2D wants 16 byte aligned address for operation buffer. */
+
+ if (((uintptr_t)buffer & 0xf) != 0)
+ {
+ set_errno(EINVAL);
+ return 0;
+ }
+
+ /* Get exclusive access */
+
+ ge2d_semtake(&g_lock);
+
+ /* Set operation buffer and start processing.
+ * Descriptor start address bit 0 is select to bus, always 1 (memory),
+ * can't set except 1 in this chip.
+ */
+
+ putreg32((uint32_t)(uintptr_t)buffer | 1, GE2D_ADDRESS_DESCRIPTOR_START);
+ putreg32(GE2D_EXEC, GE2D_CMD_DESCRIPTOR);
+
+ /* Enable error and completion interrupts. */
+
+ bits = GE2D_INTR_WR_ERR | GE2D_INTR_RD_ERR | GE2D_INTR_NDE | GE2D_INTR_DSD |
+ GE2D_INTR_NDF;
+ putreg32(bits, GE2D_INTR_ENABLE);
+
+ /* Wait for interrupts for processing done. */
+
+ ge2d_semtake(&g_wait);
+
+ /* Disable interrupts */
+
+ putreg32(0, GE2D_INTR_ENABLE);
+
+ ge2d_semgive(&g_lock);
+
+ return len;
+}
+
+/****************************************************************************
+ * Name: ge2d_ioctl
+ ****************************************************************************/
+
+static int ge2d_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+ int ret = -ENOTTY;
+
+ /* TODO: Should be implement features:
+ *
+ * - stop execution
+ * - debug for raster operation
+ */
+
+ switch (cmd)
+ {
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: ge2d_irqhandler
+ ****************************************************************************/
+
+static int ge2d_irqhandler(int irq, FAR void *context, FAR void *arg)
+{
+ uint32_t stat;
+
+ /* Clear interrupts */
+
+ stat = getreg32(GE2D_INTR_STAT);
+ putreg32(stat, GE2D_INTR_STAT);
+
+ /* TODO: output status to syslog */
+
+ /* Release semaphore anyway */
+
+ ge2d_semgive(&g_wait);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_ge2dinitialize
+ ****************************************************************************/
+
+int cxd56_ge2dinitialize(FAR const char *devname)
+{
+ int ret;
+
+ sem_init(&g_lock, 0, 1);
+ sem_init(&g_wait, 0, 0);
+ sem_setprotocol(&g_wait, SEM_PRIO_NONE);
+
+ ret = register_driver(devname, &g_ge2dfops, 0666, NULL);
+ if (ret != 0)
+ {
+ return ERROR;
+ }
+
+ cxd56_img_ge2d_clock_enable();
+
+ /* Disable interrupts */
+
+ putreg32(0, GE2D_INTR_ENABLE);
+
+ irq_attach(CXD56_IRQ_GE2D, ge2d_irqhandler, NULL);
+ up_enable_irq(CXD56_IRQ_GE2D);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_ge2duninitialize
+ ****************************************************************************/
+
+void cxd56_ge2duninitialize(FAR const char *devname)
+{
+ up_disable_irq(CXD56_IRQ_GE2D);
+ irq_detach(CXD56_IRQ_GE2D);
+
+ cxd56_img_ge2d_clock_disable();
+
+ sem_destroy(&g_lock);
+ sem_destroy(&g_wait);
+
+ unregister_driver(devname);
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_gpio.c b/arch/arm/src/cxd56xx/cxd56_gpio.c
index e4357774ab5..eb51075bb10 100644
--- a/arch/arm/src/cxd56xx/cxd56_gpio.c
+++ b/arch/arm/src/cxd56xx/cxd56_gpio.c
@@ -259,7 +259,7 @@ bool cxd56_gpio_read(uint32_t pin)
return ((regval & (1 << shift)) != 0);
}
-/********************************************************************************************
+/************************************************************
* Name: cxd56_gpio_status
*
* Description:
@@ -268,7 +268,7 @@ bool cxd56_gpio_read(uint32_t pin)
* Returned Value:
* OK on success; A negated errno value on failure.
*
- ********************************************************************************************/
+ *************************************************************/
int cxd56_gpio_status(uint32_t pin, cxd56_gpio_status_t *stat)
{
diff --git a/arch/arm/src/cxd56xx/cxd56_gpio.h b/arch/arm/src/cxd56xx/cxd56_gpio.h
index a94df810e18..d9cd5db8374 100644
--- a/arch/arm/src/cxd56xx/cxd56_gpio.h
+++ b/arch/arm/src/cxd56xx/cxd56_gpio.h
@@ -39,9 +39,9 @@
#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_GPIO_H
#define __ARCH_ARM_SRC_CXD56XX_CXD56_GPIO_H
-/********************************************************************************************
+/****************************************************************************
* Included Files
- ********************************************************************************************/
+ ****************************************************************************/
#include
@@ -50,13 +50,13 @@
#include "cxd56_pinconfig.h"
-/********************************************************************************************
+/****************************************************************************
* Pre-processor Definitions
- ********************************************************************************************/
+ ****************************************************************************/
-/********************************************************************************************
+/****************************************************************************
* Public Types
- ********************************************************************************************/
+ ****************************************************************************/
struct cxd56_gpio_status_s
{
@@ -66,9 +66,9 @@ struct cxd56_gpio_status_s
typedef struct cxd56_gpio_status_s cxd56_gpio_status_t;
-/********************************************************************************************
+/****************************************************************************
* Public Data
- ********************************************************************************************/
+ ****************************************************************************/
#ifndef __ASSEMBLY__
#ifdef __cplusplus
@@ -79,11 +79,11 @@ extern "C"
#define EXTERN extern
#endif
-/********************************************************************************************
+/****************************************************************************
* Public Functions
- ********************************************************************************************/
+ ****************************************************************************/
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_gpio_config
*
* Description:
@@ -93,11 +93,11 @@ extern "C"
* Returned Value:
* OK on success; A negated errno value on failure.
*
- ********************************************************************************************/
+ ****************************************************************************/
int cxd56_gpio_config(uint32_t pin, bool input_enable);
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_gpio_write
*
* Description:
@@ -106,11 +106,11 @@ int cxd56_gpio_config(uint32_t pin, bool input_enable);
* Returned Value:
* None
*
- ********************************************************************************************/
+ ****************************************************************************/
void cxd56_gpio_write(uint32_t pin, bool value);
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_gpio_write_hiz
*
* Description:
@@ -119,11 +119,11 @@ void cxd56_gpio_write(uint32_t pin, bool value);
* Returned Value:
* None
*
- ********************************************************************************************/
+ ****************************************************************************/
void cxd56_gpio_write_hiz(uint32_t pin);
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_gpio_read
*
* Description:
@@ -132,11 +132,11 @@ void cxd56_gpio_write_hiz(uint32_t pin);
* Returned Value:
* The boolean state of the input pin
*
- ********************************************************************************************/
+ ****************************************************************************/
bool cxd56_gpio_read(uint32_t pin);
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_gpio_status
*
* Description:
@@ -145,7 +145,7 @@ bool cxd56_gpio_read(uint32_t pin);
* Returned Value:
* OK on success; A negated errno value on failure.
*
- ********************************************************************************************/
+ ****************************************************************************/
int cxd56_gpio_status(uint32_t pin, cxd56_gpio_status_t *stat);
@@ -153,6 +153,6 @@ int cxd56_gpio_status(uint32_t pin, cxd56_gpio_status_t *stat);
#if defined(__cplusplus)
}
#endif
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_GPIO_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_gpioint.c b/arch/arm/src/cxd56xx/cxd56_gpioint.c
index fed9d517868..83804abc311 100644
--- a/arch/arm/src/cxd56xx/cxd56_gpioint.c
+++ b/arch/arm/src/cxd56xx/cxd56_gpioint.c
@@ -404,6 +404,7 @@ static int gpioint_handler(int irq, FAR void *context, FAR void *arg)
* pin - Pin number defined in cxd56_pinconfig.h
* gpiocfg - GPIO Interrupt Polarity and Noise Filter Configuration Value
* isr - Interrupt handler. If isr is NULL, then free an allocated handler.
+ * arg - Argument for the interrupt handler
*
* Returned Value:
* IRQ number on success; a negated errno value on failure.
@@ -413,7 +414,8 @@ static int gpioint_handler(int irq, FAR void *context, FAR void *arg)
*
****************************************************************************/
-int cxd56_gpioint_config(uint32_t pin, uint32_t gpiocfg, xcpt_t isr)
+int cxd56_gpioint_config(uint32_t pin, uint32_t gpiocfg, xcpt_t isr,
+ FAR void *arg)
{
int slot;
int irq;
@@ -450,9 +452,9 @@ int cxd56_gpioint_config(uint32_t pin, uint32_t gpiocfg, xcpt_t isr)
/* set GPIO interrupt configuration */
- if (gpiocfg & GPIOINT_TOGGLE_BOTH_MASK) {
-
- /* set GPIO pseudo both edge interrupt */
+ if (gpiocfg & GPIOINT_TOGGLE_BOTH_MASK)
+ {
+ /* set GPIO pseudo both edge interrupt */
flags = enter_critical_section();
g_bothedge |= (1 << slot);
@@ -460,9 +462,12 @@ int cxd56_gpioint_config(uint32_t pin, uint32_t gpiocfg, xcpt_t isr)
/* detect the change from the current signal */
- if (true == cxd56_gpio_read(pin)) {
+ if (true == cxd56_gpio_read(pin))
+ {
gpiocfg |= GPIOINT_SET_POLARITY(GPIOINT_LEVEL_LOW);
- } else {
+ }
+ else
+ {
gpiocfg |= GPIOINT_SET_POLARITY(GPIOINT_LEVEL_HIGH);
}
}
@@ -471,12 +476,12 @@ int cxd56_gpioint_config(uint32_t pin, uint32_t gpiocfg, xcpt_t isr)
if ((gpiocfg & GPIOINT_TOGGLE_MODE_MASK) || GPIOINT_IS_EDGE(gpiocfg))
{
- irq_attach(irq, gpioint_handler, (void *)pin); /* call intermediate handler */
+ irq_attach(irq, gpioint_handler, arg); /* call intermediate handler */
g_isr[slot] = isr;
}
else
{
- irq_attach(irq, isr, (void *)pin); /* call user handler directly */
+ irq_attach(irq, isr, arg); /* call user handler directly */
g_isr[slot] = NULL;
}
diff --git a/arch/arm/src/cxd56xx/cxd56_gpioint.h b/arch/arm/src/cxd56xx/cxd56_gpioint.h
index 8f198b1fe36..c307088b04a 100644
--- a/arch/arm/src/cxd56xx/cxd56_gpioint.h
+++ b/arch/arm/src/cxd56xx/cxd56_gpioint.h
@@ -46,8 +46,6 @@
#include
#include "chip.h"
-#ifdef CONFIG_CXD56_GPIO_IRQ
-
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -65,8 +63,8 @@
/* GPIO Interrupt Polarity Definitions */
-//#define GPIOINT_INSTANT_HIGH (0) /* Not supported */
-//#define GPIOINT_INSTANT_LOW (1) /* Not supported */
+/* #define GPIOINT_INSTANT_HIGH (0) */ /* Not supported */
+/* #define GPIOINT_INSTANT_LOW (1) */ /* Not supported */
#define GPIOINT_LEVEL_HIGH (2) /* High Level */
#define GPIOINT_LEVEL_LOW (3) /* Low Level */
#define GPIOINT_EDGE_RISE (4) /* Rising Edge */
@@ -75,9 +73,11 @@
#define GPIOINT_PSEUDO_EDGE_RISE (GPIOINT_LEVEL_HIGH | \
GPIOINT_TOGGLE_MODE_MASK)
/* Rising Edge without clear */
+
#define GPIOINT_PSEUDO_EDGE_FALL (GPIOINT_LEVEL_LOW | \
GPIOINT_TOGGLE_MODE_MASK)
/* Falling Edge without clear */
+
#define GPIOINT_PSEUDO_EDGE_BOTH (GPIOINT_TOGGLE_MODE_MASK | \
GPIOINT_TOGGLE_BOTH_MASK)
/* Both Edge without clear */
@@ -133,6 +133,7 @@ extern "C"
* pin - Pin number defined in cxd56_pinconfig.h
* gpiocfg - GPIO Interrupt Polarity and Noise Filter Configuration Value
* isr - Interrupt handler
+ * arg - Argument for the interrupt handler
*
* Returned Value:
* IRQ number on success; a negated errno value on failure.
@@ -142,7 +143,8 @@ extern "C"
*
****************************************************************************/
-int cxd56_gpioint_config(uint32_t pin, uint32_t gpiocfg, xcpt_t isr);
+int cxd56_gpioint_config(uint32_t pin, uint32_t gpiocfg, xcpt_t isr,
+ FAR void *arg);
/****************************************************************************
* Name: cxd56_gpioint_irq
@@ -209,7 +211,7 @@ void cxd56_gpioint_disable(uint32_t pin);
void cxd56_gpioint_invert(uint32_t pin);
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_gpioint_status
*
* Description:
@@ -218,7 +220,7 @@ void cxd56_gpioint_invert(uint32_t pin);
* Returned Value:
* OK on success; A negated errno value on failure.
*
- ********************************************************************************************/
+ ****************************************************************************/
int cxd56_gpioint_status(uint32_t pin, cxd56_gpioint_status_t *stat);
@@ -226,8 +228,6 @@ int cxd56_gpioint_status(uint32_t pin, cxd56_gpioint_status_t *stat);
#if defined(__cplusplus)
}
#endif
+
#endif /* __ASSEMBLY__ */
-
-#endif /* CONFIG_CXD56_GPIO_IRQ */
-
#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_GPIOINT_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_i2c.c b/arch/arm/src/cxd56xx/cxd56_i2c.c
new file mode 100644
index 00000000000..b823e092987
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_i2c.c
@@ -0,0 +1,1110 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_i2c.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include "chip.h"
+#include "up_arch.h"
+#include "up_internal.h"
+
+#include "cxd56_clock.h"
+#include "cxd56_i2c.h"
+#include "hardware/cxd56_i2c.h"
+#include "cxd56_pinconfig.h"
+
+#if defined(CONFIG_CXD56_I2C0_SCUSEQ) || defined(CONFIG_CXD56_I2C1_SCUSEQ)
+#include
+#endif
+
+#ifdef CONFIG_CXD56_I2C
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define I2C_TIMEOUT (20*1000/CONFIG_USEC_PER_TICK) /* 20 mS */
+
+#define I2C_DEFAULT_FREQUENCY 400000
+#define I2C_FIFO_MAX_SIZE 32
+
+#define I2C_INTR_ENABLE ((INTR_STOP_DET) | \
+ (INTR_TX_ABRT) | \
+ (INTR_TX_OVER) | \
+ (INTR_RX_OVER) | \
+ (INTR_RX_UNDER))
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct cxd56_i2cdev_s
+{
+ struct i2c_master_s dev; /* Generic I2C device */
+ unsigned int base; /* Base address of registers */
+ uint16_t irqid; /* IRQ for this device */
+ int8_t port; /* Port number */
+ uint32_t baseFreq; /* branch frequency */
+
+ sem_t mutex; /* Only one thread can access at a time */
+ sem_t wait; /* Place to wait for transfer completion */
+ WDOG_ID timeout; /* watchdog to timeout when bus hung */
+ uint32_t frequency; /* Current I2C frequency */
+ ssize_t reg_buff_offset;
+ ssize_t rw_size;
+
+ struct i2c_msg_s *msgs;
+
+ int error; /* Error status of each transfers */
+ int refs; /* Reference count */
+};
+
+/* Channel 0 as SCU_I2C0
+ * Channel 1 as SCU_I2C1
+ * Channel 2 as I2CM
+ */
+
+#ifdef CONFIG_CXD56_I2C0
+static struct cxd56_i2cdev_s g_i2c0dev =
+{
+ .port = 0,
+ .base = CXD56_SCU_I2C0_BASE,
+ .irqid = CXD56_IRQ_SCU_I2C0,
+ .refs = 0,
+};
+#endif
+#ifdef CONFIG_CXD56_I2C1
+static struct cxd56_i2cdev_s g_i2c1dev =
+{
+ .port = 1,
+ .base = CXD56_SCU_I2C1_BASE,
+ .irqid = CXD56_IRQ_SCU_I2C1,
+ .refs = 0,
+};
+#endif
+#ifdef CONFIG_CXD56_I2C2
+static struct cxd56_i2cdev_s g_i2c2dev =
+{
+ .port = 2,
+ .base = CXD56_I2CM_BASE,
+ .irqid = CXD56_IRQ_I2CM,
+ .refs = 0,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static inline uint32_t i2c_reg_read(struct cxd56_i2cdev_s *priv,
+ uint32_t offset);
+static inline void i2c_reg_write(struct cxd56_i2cdev_s *priv, uint32_t offset,
+ uint32_t val);
+static inline void i2c_reg_rmw(struct cxd56_i2cdev_s *dev, uint32_t offset,
+ uint32_t val, uint32_t mask);
+
+static int cxd56_i2c_disable(struct cxd56_i2cdev_s *priv);
+static void cxd56_i2c_enable(struct cxd56_i2cdev_s *priv);
+
+static int cxd56_i2c_interrupt(int irq, FAR void *context, FAR void *arg);
+static void cxd56_i2c_timeout(int argc, uint32_t arg, ...);
+static void cxd56_i2c_setfrequency(struct cxd56_i2cdev_s *priv,
+ uint32_t frequency);
+static int cxd56_i2c_transfer(FAR struct i2c_master_s *dev,
+ FAR struct i2c_msg_s *msgs, int count);
+#ifdef CONFIG_I2C_RESET
+static int cxd56_i2c_reset(FAR struct i2c_master_s * dev);
+#endif
+#if defined(CONFIG_CXD56_I2C0_SCUSEQ) || defined(CONFIG_CXD56_I2C1_SCUSEQ)
+static int cxd56_i2c_transfer_scu(FAR struct i2c_master_s *dev,
+ FAR struct i2c_msg_s *msgs, int count);
+#endif
+
+/****************************************************************************
+ * Name: cxd56_i2c_pincontrol
+ *
+ * Description:
+ * Configure the I2C pin
+ *
+ * Input Parameter:
+ * on - true: enable pin, false: disable pin
+ *
+ ****************************************************************************/
+
+static void cxd56_i2c_pincontrol(int ch, bool on)
+{
+ switch (ch)
+ {
+#ifdef CONFIG_CXD56_I2C0
+ case 0:
+ if (on)
+ {
+ CXD56_PIN_CONFIGS(PINCONFS_I2C0);
+ }
+ else
+ {
+ CXD56_PIN_CONFIGS(PINCONFS_I2C0_GPIO);
+ }
+ break;
+#endif /* CONFIG_CXD56_I2C0 */
+
+#ifdef CONFIG_CXD56_I2C1
+ case 1:
+ if (on)
+ {
+ CXD56_PIN_CONFIGS(PINCONFS_PWMB_I2C1);
+ }
+ else
+ {
+ CXD56_PIN_CONFIGS(PINCONFS_PWMB_GPIO);
+ }
+ break;
+#endif /* CONFIG_CXD56_I2C1 */
+
+#ifdef CONFIG_CXD56_I2C2
+ case 2:
+ if (on)
+ {
+ CXD56_PIN_CONFIGS(PINCONFS_SPI0B_I2C2);
+ }
+ else
+ {
+ CXD56_PIN_CONFIGS(PINCONFS_SPI0B_GPIO);
+ }
+ break;
+#endif /* CONFIG_CXD56_I2C2 */
+
+ default:
+ break;
+ }
+}
+
+/****************************************************************************
+ * I2C device operations
+ ****************************************************************************/
+
+struct i2c_ops_s cxd56_i2c_ops =
+{
+ .transfer = cxd56_i2c_transfer,
+#ifdef CONFIG_I2C_RESET
+ .reset = cxd56_i2c_reset,
+#endif
+};
+
+#if defined(CONFIG_CXD56_I2C0_SCUSEQ) || defined(CONFIG_CXD56_I2C1_SCUSEQ)
+struct i2c_ops_s cxd56_i2c_scu_ops =
+{
+ .transfer = cxd56_i2c_transfer_scu,
+#ifdef CONFIG_I2C_RESET
+ .reset = cxd56_i2c_reset,
+#endif
+};
+#endif
+
+/****************************************************************************
+ * Name: cxd56_i2c_setfrequency
+ *
+ * Description:
+ * Set the frequency for the next transfer
+ *
+ ****************************************************************************/
+
+static void cxd56_i2c_setfrequency(struct cxd56_i2cdev_s *priv,
+ uint32_t frequency)
+{
+ int32_t lcnt;
+ int32_t hcnt;
+ uint64_t lcnt64;
+ uint64_t hcnt64;
+ uint64_t speed;
+ uint64_t tLow;
+ uint64_t tHigh;
+ uint32_t base = cxd56_get_i2c_baseclock(priv->port);
+ uint32_t spklen;
+
+ ASSERT(base);
+
+ if ((priv->frequency == frequency) && (priv->baseFreq == base))
+ {
+ return;
+ }
+
+ priv->frequency = frequency;
+ priv->baseFreq = base;
+
+ base /= 1000;
+
+ switch (frequency)
+ {
+ case 100000:
+ tLow = 4700000;
+ tHigh = 4000000;
+ break;
+
+ case 400000:
+ tLow = 1300000;
+ tHigh = 600000;
+ break;
+
+ case 1000000:
+ tLow = 500000;
+ tHigh = 260000;
+ break;
+
+ default:
+ return;
+ }
+
+ if (frequency > 100000)
+ {
+ if (base < 20032)
+ {
+ spklen = 1;
+ }
+ else if (base < 40064)
+ {
+ spklen = 2;
+ }
+ else
+ {
+ spklen = 3;
+ }
+ }
+ else
+ {
+ spklen = 1;
+ }
+
+ lcnt64 = (tLow + 6500ull / 20000ull) * base;
+ lcnt = ((lcnt64 + 999999999ull) / 1000000000ull) - 1; /* ceil */
+ lcnt = lcnt < 8 ? 8 : lcnt;
+
+ hcnt64 = (tHigh - 6500ull) * base;
+ hcnt = ((hcnt64 + 999999999ull) / 1000000000ull) - 6 - spklen; /* ceil */
+ hcnt = hcnt < 6 ? 6 : hcnt;
+
+ speed =
+ 1000000000000000000ull /
+ (((lcnt + 1) * 1000000000000ull +
+ (hcnt + 6 + spklen) * 1000000000000ull) / base +
+ 20000ull / 1000ull * 1000000ull);
+
+ if (speed > (frequency * 1000ull))
+ {
+ uint64_t adj;
+ adj = ((1000000000000000000ull / (frequency * 1000ull)) -
+ (1000000000000000000ull / speed)) *
+ base;
+ hcnt += (adj + 999999999999ull) / 1000000000000ull;
+ }
+
+ /* use FS register in SS and FS mode */
+
+ i2c_reg_write(priv, CXD56_IC_FS_SCL_HCNT, hcnt);
+ i2c_reg_write(priv, CXD56_IC_FS_SCL_LCNT, lcnt);
+ i2c_reg_rmw(priv, CXD56_IC_CON, IC_SPEED_FS, IC_MAX_SPEED_MODE);
+
+ i2c_reg_write(priv, CXD56_IC_FS_SPKLEN, spklen);
+}
+
+/****************************************************************************
+ * Name: cxd56_i2c_timeout
+ *
+ * Description:
+ * Watchdog timer for timeout of I2C operation
+ *
+ ****************************************************************************/
+
+static void cxd56_i2c_timeout(int argc, uint32_t arg, ...)
+{
+ struct cxd56_i2cdev_s *priv = (struct cxd56_i2cdev_s *)arg;
+ irqstate_t flags = enter_critical_section();
+
+ priv->error = -ENODEV;
+ sem_post(&priv->wait);
+ leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: cxd56_i2c_drainrxfifo
+ *
+ * Description:
+ * Receive I2C data
+ *
+ ****************************************************************************/
+
+static void cxd56_i2c_drainrxfifo(struct cxd56_i2cdev_s *priv)
+{
+ struct i2c_msg_s *msg = priv->msgs;
+ uint32_t status;
+ uint32_t dat;
+ ssize_t i;
+
+ DEBUGASSERT(msg != NULL);
+
+ status = i2c_reg_read(priv, CXD56_IC_STATUS);
+
+ for (i = 0; i < priv->rw_size && status & STATUS_RFNE; i++)
+ {
+ dat = i2c_reg_read(priv, CXD56_IC_DATA_CMD);
+ msg->buffer[priv->reg_buff_offset + i] = dat & 0xff;
+ status = i2c_reg_read(priv, CXD56_IC_STATUS);
+ }
+
+ priv->reg_buff_offset += priv->rw_size;
+}
+
+/****************************************************************************
+ * Name: cxd56_i2c_interrupt
+ *
+ * Description:
+ * The I2C Interrupt Handler
+ *
+ ****************************************************************************/
+
+static int cxd56_i2c_interrupt(int irq, FAR void *context, FAR void *arg)
+{
+ FAR struct cxd56_i2cdev_s *priv = (FAR struct cxd56_i2cdev_s *)arg;
+ uint32_t state;
+ int ret;
+
+ state = i2c_reg_read(priv, CXD56_IC_INTR_STAT);
+
+ if (state & INTR_TX_ABRT)
+ {
+ i2c_reg_read(priv, CXD56_IC_CLR_TX_ABRT);
+ priv->error = -ENODEV;
+ }
+
+ if (state & INTR_TX_OVER)
+ {
+ i2c_reg_read(priv, CXD56_IC_CLR_TX_OVER);
+ priv->error = -EIO;
+ }
+
+ if (state & INTR_RX_OVER)
+ {
+ i2c_reg_read(priv, CXD56_IC_CLR_RX_OVER);
+ priv->error = -EIO;
+ }
+
+ if (state & INTR_RX_UNDER)
+ {
+ i2c_reg_read(priv, CXD56_IC_CLR_RX_UNDER);
+ priv->error = -EIO;
+ }
+
+ if (state & INTR_TX_EMPTY)
+ {
+ /* TX_EMPTY is automatically cleared by hardware
+ * when the buffer level goes above the threshold.
+ */
+
+ i2c_reg_rmw(priv, CXD56_IC_INTR_MASK, 0, INTR_TX_EMPTY);
+ }
+
+ if (state & INTR_RX_FULL)
+ {
+ /* RX_FULL is automatically cleared by hardware
+ * when the buffer level goes below the threshold.
+ */
+
+ i2c_reg_rmw(priv, CXD56_IC_INTR_MASK, 0, INTR_RX_FULL);
+ cxd56_i2c_drainrxfifo(priv);
+ }
+
+ if (state & INTR_STOP_DET)
+ {
+ i2c_reg_read(priv, CXD56_IC_CLR_STOP_DET);
+ }
+
+ if ((priv->error) || (state & INTR_TX_EMPTY) || (state & INTR_RX_FULL))
+ {
+ /* Failure of wd_cancel() means that the timer expired.
+ * In this case, sem_post() has already been called.
+ * Therefore, call sem_post() only when wd_cancel() succeeds.
+ */
+
+ ret = wd_cancel(priv->timeout);
+ if (ret == OK)
+ {
+ sem_post(&priv->wait);
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_i2c_receive
+ *
+ * Description:
+ * Receive data from I2C bus.
+ * Prohibit all interrupt because the STOP condition might happen
+ * if the interrupt occurs when the writing request.
+ * Actual receiving data is in RX_FULL interrupt handler.
+ *
+ * TODO : The argument "last" is not used.
+ ****************************************************************************/
+
+static int cxd56_i2c_receive(struct cxd56_i2cdev_s *priv, int last)
+{
+ struct i2c_msg_s *msg = priv->msgs;
+ int i;
+ int en;
+ ssize_t msg_length;
+ irqstate_t flags;
+
+ priv->reg_buff_offset = 0;
+
+ DEBUGASSERT(msg != NULL);
+
+ for (msg_length = msg->length; msg_length > 0; msg_length -= priv->rw_size)
+ {
+ if (msg_length <= I2C_FIFO_MAX_SIZE)
+ {
+ priv->rw_size = msg_length;
+ en = 1;
+ }
+ else
+ {
+ priv->rw_size = I2C_FIFO_MAX_SIZE;
+ en = 0;
+ }
+
+ /* update threshold value of the receive buffer */
+
+ i2c_reg_write(priv, CXD56_IC_RX_TL, priv->rw_size - 1);
+
+ for (i = 0; i < priv->rw_size - 1; i++)
+ {
+ i2c_reg_write(priv, CXD56_IC_DATA_CMD, CMD_READ);
+ }
+
+ flags = enter_critical_section();
+ wd_start(priv->timeout, I2C_TIMEOUT, cxd56_i2c_timeout, 1,
+ (uint32_t)priv);
+
+ /* Set stop flag for indicate the last data */
+
+ i2c_reg_write(priv, CXD56_IC_DATA_CMD, CMD_READ | (en ? CMD_STOP : 0));
+
+ i2c_reg_rmw(priv, CXD56_IC_INTR_MASK, INTR_RX_FULL, INTR_RX_FULL);
+ leave_critical_section(flags);
+ sem_wait(&priv->wait);
+
+ if (priv->error != OK)
+ {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: cxd56_i2c_send
+ *
+ * Description:
+ * Send data to I2C bus.
+ *
+ ****************************************************************************/
+
+static int cxd56_i2c_send(struct cxd56_i2cdev_s *priv, int last)
+{
+ struct i2c_msg_s *msg = priv->msgs;
+ ssize_t i;
+ irqstate_t flags;
+
+ DEBUGASSERT(msg != NULL);
+
+ for (i = 0; i < msg->length - 1; i++)
+ {
+ while (!(i2c_reg_read(priv, CXD56_IC_STATUS) & STATUS_TFNF));
+
+ i2c_reg_write(priv, CXD56_IC_DATA_CMD, (uint32_t)msg->buffer[i]);
+ }
+
+ while (!(i2c_reg_read(priv, CXD56_IC_STATUS) & STATUS_TFNF));
+
+ flags = enter_critical_section();
+ wd_start(priv->timeout, I2C_TIMEOUT, cxd56_i2c_timeout, 1, (uint32_t)priv);
+ i2c_reg_write(priv, CXD56_IC_DATA_CMD,
+ (uint32_t)msg->buffer[i] | (last ? CMD_STOP : 0));
+
+ /* Enable TX_EMPTY interrupt for determine transfer done. */
+
+ i2c_reg_rmw(priv, CXD56_IC_INTR_MASK, INTR_TX_EMPTY, INTR_TX_EMPTY);
+ leave_critical_section(flags);
+
+ sem_wait(&priv->wait);
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: cxd56_i2c_transfer
+ *
+ * Description:
+ * Perform a sequence of I2C transfers
+ *
+ * TODO: Multiple i2c_msg_s read operations with the same address are not
+ * currently guaranteed.
+ ****************************************************************************/
+
+static int cxd56_i2c_transfer(FAR struct i2c_master_s *dev,
+ FAR struct i2c_msg_s *msgs, int count)
+{
+ struct cxd56_i2cdev_s *priv = (struct cxd56_i2cdev_s *)dev;
+ int i;
+ int ret = 0;
+ int semval = 0;
+ int addr = -1;
+ static int wostop = 0;
+
+ DEBUGASSERT(dev != NULL);
+
+ /* Get exclusive access to the I2C bus */
+
+ sem_wait(&priv->mutex);
+
+ /* Check wait semaphore value. If the value is not 0, the transfer can not
+ * be performed normally.
+ */
+
+ ret = sem_getvalue(&priv->wait, &semval);
+ DEBUGASSERT(ret == OK && semval == 0);
+
+ /* Disable clock gating (clock enable) */
+
+ cxd56_i2c_clock_gate_disable(priv->port);
+
+ for (i = 0; i < count; i++, msgs++)
+ {
+ /* Pass msg descriptor via device context */
+
+ priv->msgs = msgs;
+ priv->error = OK;
+
+ if ((addr != msgs->addr) && !wostop)
+ {
+ cxd56_i2c_disable(priv);
+
+ cxd56_i2c_setfrequency(priv, msgs->frequency);
+
+ i2c_reg_rmw(priv, CXD56_IC_CON, IC_RESTART_EN, IC_RESTART_EN);
+ i2c_reg_write(priv, CXD56_IC_TAR, msgs->addr & 0x7f);
+
+ cxd56_i2c_enable(priv);
+ addr = msgs->addr;
+ }
+
+ if (msgs->flags & I2C_M_NOSTOP)
+ {
+ /* Don't send stop condition even if the last data */
+
+ wostop = 1;
+ }
+ else
+ {
+ wostop = 0;
+ }
+
+ if (msgs->flags & I2C_M_READ)
+ {
+ ret = cxd56_i2c_receive(priv, (wostop) ? 0 : (i + 1 == count));
+ }
+ else
+ {
+ ret = cxd56_i2c_send(priv, (wostop) ? 0 : (i + 1 == count));
+ }
+
+ if (ret < 0)
+ {
+ break;
+ }
+
+ if (priv->error != OK)
+ {
+ ret = priv->error;
+ break;
+ }
+
+ /* Clear msg descriptor for prevent illegal access in interrupt */
+
+ priv->msgs = NULL;
+ }
+
+ if (!wostop)
+ {
+ cxd56_i2c_disable(priv);
+ }
+
+ /* Enable clock gating (clock disable) */
+
+ cxd56_i2c_clock_gate_enable(priv->port);
+
+ sem_post(&priv->mutex);
+ return ret;
+}
+
+/****************************************************************************
+ * Name: cxd56_i2c_reset
+ *
+ * Description:
+ * Perform an I2C bus reset in an attempt to break loose stuck I2C devices.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_I2C_RESET
+static int cxd56_i2c_reset(FAR struct i2c_master_s *dev)
+{
+ return OK;
+}
+#endif /* CONFIG_I2C_RESET */
+
+/****************************************************************************
+ * Name: cxd56_i2c_transfer_scu
+ *
+ * Description:
+ * Perform a sequence of I2C transfers with scu oneshot sequencer.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_CXD56_I2C0_SCUSEQ) || defined(CONFIG_CXD56_I2C1_SCUSEQ)
+
+static int cxd56_i2c_scurecv(int port, int addr, uint8_t *buf, ssize_t buflen)
+{
+ uint16_t inst[2];
+ int instn;
+ int len0;
+ int len1;
+ ssize_t rem;
+ int ret = OK;
+
+ /* Ignore buffer is NULL */
+
+ if (buf == NULL)
+ {
+ return OK;
+ }
+
+ rem = buflen;
+ while (rem)
+ {
+ len0 = rem > 8 ? 8 : rem;
+ rem -= len0;
+ len1 = rem > 8 ? 8 : rem;
+ rem -= len1;
+
+ inst[0] = SCU_INST_RECV(len0);
+ if (len1)
+ {
+ inst[1] = SCU_INST_RECV(len1);
+ instn = 2;
+ }
+ else
+ {
+ instn = 1;
+ }
+
+ if (rem == 0)
+ {
+ inst[instn - 1] |= SCU_INST_LAST;
+ }
+
+ ret = scu_i2ctransfer(port, addr, inst, instn, buf, len0 + len1);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "I2C recieve failed. port %d addr %d\n",
+ port, addr);
+ break;
+ }
+
+ buf += len0 + len1;
+ }
+
+ return ret;
+}
+
+static int cxd56_i2c_scusend(int port, int addr, uint8_t *buf, ssize_t buflen)
+{
+ uint16_t inst[12];
+ ssize_t rem;
+ int i;
+ int ret = OK;
+
+ rem = buflen;
+
+ while (rem)
+ {
+ for (i = 0; i < 12 && rem > 0; i++)
+ {
+ inst[i] = SCU_INST_SEND(*buf++);
+ rem--;
+ }
+
+ if (rem == 0)
+ {
+ inst[i - 1] |= SCU_INST_LAST;
+ }
+
+ if (i > 0)
+ {
+ ret = scu_i2ctransfer(port, addr, inst, i, NULL, i);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "I2C send failed. port %d addr %d\n",
+ port, addr);
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int cxd56_i2c_transfer_scu(FAR struct i2c_master_s *dev,
+ FAR struct i2c_msg_s *msgs, int count)
+{
+ FAR struct cxd56_i2cdev_s *priv = (FAR struct cxd56_i2cdev_s *)dev;
+ ssize_t len = 0;
+ uint8_t *buf = NULL;
+ uint8_t addr = msgs->addr;
+ int i;
+ int ret = 0;
+
+ DEBUGASSERT(dev != NULL);
+
+ /* Get exclusive access to the I2C bus */
+
+ sem_wait(&priv->mutex);
+
+ /* Apply frequency for request msgs */
+
+ if (priv->frequency != msgs->frequency)
+ {
+ cxd56_i2c_clock_gate_disable(priv->port);
+ cxd56_i2c_disable(priv);
+ cxd56_i2c_setfrequency(priv, msgs->frequency);
+ i2c_reg_rmw(priv, CXD56_IC_CON, IC_RESTART_EN, IC_RESTART_EN);
+ i2c_reg_write(priv, CXD56_IC_TAR, msgs->addr & 0x7f);
+ cxd56_i2c_enable(priv);
+ cxd56_i2c_clock_gate_enable(priv->port);
+
+ priv->frequency = msgs->frequency;
+ }
+
+ for (i = 0; i < count; i++, msgs++)
+ {
+ len = msgs->length;
+ buf = msgs->buffer;
+
+ if (msgs->flags & I2C_M_READ)
+ {
+ ret = cxd56_i2c_scurecv(priv->port, addr, buf, len);
+ }
+ else
+ {
+ ret = cxd56_i2c_scusend(priv->port, addr, buf, len);
+ }
+
+ if (ret < 0)
+ {
+ break;
+ }
+ }
+
+ sem_post(&priv->mutex);
+
+ return ret;
+}
+#endif
+
+static inline uint32_t i2c_reg_read(struct cxd56_i2cdev_s *priv,
+ uint32_t offset)
+{
+ return getreg32(priv->base + offset);
+}
+
+static inline void i2c_reg_write(struct cxd56_i2cdev_s *priv, uint32_t offset,
+ uint32_t val)
+{
+ putreg32(val, priv->base + offset);
+}
+
+static inline void i2c_reg_rmw(struct cxd56_i2cdev_s *priv, uint32_t offset,
+ uint32_t val, uint32_t mask)
+{
+ uint32_t regval;
+ regval = getreg32(priv->base + offset);
+ putreg32((regval & ~mask) | val, priv->base + offset);
+}
+
+static int cxd56_i2c_disable(struct cxd56_i2cdev_s *priv)
+{
+ int retry = 25000;
+ uint32_t stat;
+
+ /* disable all interrupt */
+
+ i2c_reg_write(priv, CXD56_IC_INTR_MASK, 0x0);
+
+ /* clear all interrupt status */
+
+ i2c_reg_read(priv, CXD56_IC_CLR_INTR);
+ i2c_reg_write(priv, CXD56_IC_ENABLE, 0);
+
+ do
+ {
+ stat = i2c_reg_read(priv, CXD56_IC_ENABLE_STATUS);
+ }
+ while (--retry && (stat & ESTATUS_IC_EN));
+
+ if (!retry)
+ {
+ i2cerr("i2c wait timeout.\n");
+ return -EBUSY;
+ }
+
+ /* clear all interrupt status again */
+
+ i2c_reg_read(priv, CXD56_IC_CLR_INTR);
+
+ return 0;
+}
+
+static void cxd56_i2c_enable(struct cxd56_i2cdev_s *priv)
+{
+ i2c_reg_write(priv, CXD56_IC_INTR_MASK, I2C_INTR_ENABLE);
+ i2c_reg_write(priv, CXD56_IC_ENABLE, 1);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_i2cbus_initialize
+ *
+ * Description:
+ * Initialise an I2C device
+ *
+ ****************************************************************************/
+
+struct i2c_master_s *cxd56_i2cbus_initialize(int port)
+{
+ struct cxd56_i2cdev_s *priv;
+
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+
+#ifdef CONFIG_CXD56_I2C0
+ if (port == 0)
+ {
+ priv = &g_i2c0dev;
+# ifndef CONFIG_CXD56_I2C0_SCUSEQ
+ priv->dev.ops = &cxd56_i2c_ops;
+# else
+ priv->dev.ops = &cxd56_i2c_scu_ops;
+# endif
+ }
+ else
+#endif
+#ifdef CONFIG_CXD56_I2C1
+ if (port == 1)
+ {
+ priv = &g_i2c1dev;
+# ifndef CONFIG_CXD56_I2C1_SCUSEQ
+ priv->dev.ops = &cxd56_i2c_ops;
+# else
+ priv->dev.ops = &cxd56_i2c_scu_ops;
+# endif
+ }
+ else
+#endif
+#ifdef CONFIG_CXD56_I2C2
+ if (port == 2)
+ {
+ priv = &g_i2c2dev;
+ priv->dev.ops = &cxd56_i2c_ops;
+ }
+ else
+#endif
+ {
+ leave_critical_section(flags);
+ i2cerr("I2C Only support 0,1,2\n");
+ return NULL;
+ }
+
+ priv->refs++;
+
+ /* Test if already initialized or not */
+
+ if (1 < priv->refs)
+ {
+ leave_critical_section(flags);
+ return &priv->dev;
+ }
+
+ priv->port = port;
+ priv->frequency = 0;
+
+ cxd56_i2c_clock_enable(priv->port);
+ priv->baseFreq = cxd56_get_i2c_baseclock(priv->port);
+
+ cxd56_i2c_disable(priv);
+
+ i2c_reg_write(priv, CXD56_IC_INTR_MASK, 0x00);
+ i2c_reg_read(priv, CXD56_IC_CLR_INTR);
+
+ /* set threshold level of the Rx/Tx FIFO */
+
+ i2c_reg_write(priv, CXD56_IC_RX_TL, 0xff);
+ i2c_reg_write(priv, CXD56_IC_TX_TL, 0);
+
+ /* set hold time for margin */
+
+ i2c_reg_write(priv, CXD56_IC_SDA_HOLD, 1);
+
+ i2c_reg_write(priv, CXD56_IC_CON,
+ (IC_SLAVE_DISABLE | IC_MASTER_MODE | IC_TX_EMPTY_CTRL));
+ cxd56_i2c_setfrequency(priv, I2C_DEFAULT_FREQUENCY);
+
+ leave_critical_section(flags);
+
+ /* Configure pin */
+
+ cxd56_i2c_pincontrol(port, true);
+
+ sem_init(&priv->mutex, 0, 1);
+ sem_init(&priv->wait, 0, 0);
+
+ priv->timeout = wd_create();
+
+ /* Attach Interrupt Handler */
+
+ irq_attach(priv->irqid, cxd56_i2c_interrupt, priv);
+
+ /* Enable Interrupt Handler */
+
+ up_enable_irq(priv->irqid);
+
+ /* Enable Interrupt in SCU */
+
+ if (port == 0 || port == 1)
+ {
+ putreg32(getreg32(CXD56_SCU_BASE + 0x400) | (1u << (port + 1)),
+ CXD56_SCU_BASE + 0x400);
+ }
+
+ /* Enable clock gating (clock disable) */
+
+ cxd56_i2c_clock_gate_enable(port);
+
+ return &priv->dev;
+}
+
+/****************************************************************************
+ * Name: cxd56_i2cbus_uninitialize
+ *
+ * Description:
+ * Uninitialise an I2C device
+ *
+ ****************************************************************************/
+
+int cxd56_i2cbus_uninitialize(FAR struct i2c_master_s *dev)
+{
+ struct cxd56_i2cdev_s *priv = (struct cxd56_i2cdev_s *)dev;
+
+ /* Decrement reference count and check for underflow */
+
+ if (priv->refs == 0)
+ {
+ return ERROR;
+ }
+
+ if (--priv->refs)
+ {
+ return OK;
+ }
+
+ /* Configure pin */
+
+ cxd56_i2c_pincontrol(priv->port, false);
+
+ /* Disable clock gating (clock enable) */
+
+ cxd56_i2c_clock_gate_disable(priv->port);
+
+ cxd56_i2c_disable(priv);
+ cxd56_i2c_clock_disable(priv->port);
+
+ up_disable_irq(priv->irqid);
+ irq_detach(priv->irqid);
+
+ wd_delete(priv->timeout);
+ priv->timeout = NULL;
+ sem_destroy(&priv->mutex);
+ sem_destroy(&priv->wait);
+
+ return OK;
+}
+
+#endif
diff --git a/arch/arm/src/cxd56xx/cxd56_i2c.h b/arch/arm/src/cxd56xx/cxd56_i2c.h
new file mode 100644
index 00000000000..d6696e738e1
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_i2c.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_i2c.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_I2C_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_I2C_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+#include "hardware/cxd56_i2c.h"
+
+#ifndef __ASSEMBLY__
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_i2cbus_initialize
+ *
+ * Description:
+ * Initialize the selected I2C port. And return a unique instance of struct
+ * struct i2c_master_s. This function may be called to obtain multiple
+ * instances of the interface, each of which may be set up with a
+ * different frequency and slave address.
+ *
+ * Input Parameter:
+ * Port number (for hardware that has multiple I2C interfaces)
+ *
+ * Returned Value:
+ * Valid I2C device structure reference on succcess; a NULL on failure
+ *
+ ****************************************************************************/
+
+FAR struct i2c_master_s *cxd56_i2cbus_initialize(int port);
+
+/****************************************************************************
+ * Name: cxd56_i2cbus_uninitialize
+ *
+ * Description:
+ * De-initialize the selected I2C port, and power down the device.
+ *
+ * Input Parameter:
+ * Device structure as returned by the cxd56_i2cbus_initialize()
+ *
+ * Returned Value:
+ * OK on success, ERROR when internal reference count mismatch or dev
+ * points to invalid hardware device.
+ *
+ ****************************************************************************/
+
+int cxd56_i2cbus_uninitialize(FAR struct i2c_master_s *dev);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_I2C_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_icc.h b/arch/arm/src/cxd56xx/cxd56_icc.h
index a5d9f667f9d..230e330074b 100644
--- a/arch/arm/src/cxd56xx/cxd56_icc.h
+++ b/arch/arm/src/cxd56xx/cxd56_icc.h
@@ -96,6 +96,6 @@ void cxd56_iccinitialize(void);
#ifdef __cplusplus
}
#endif
-#endif
+#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_ICC_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_irq.c b/arch/arm/src/cxd56xx/cxd56_irq.c
index 1734e25493c..30d3c29fcf9 100644
--- a/arch/arm/src/cxd56xx/cxd56_irq.c
+++ b/arch/arm/src/cxd56xx/cxd56_irq.c
@@ -123,13 +123,6 @@ static void cxd56_dumpnvic(const char *msg, int irq)
irqinfo("NVIC (%s, irq=%d):\n", msg, irq);
irqinfo(" INTCTRL: %08x VECTAB: %08x\n", getreg32(NVIC_INTCTRL),
getreg32(NVIC_VECTAB));
-# if 0
- irqinfo(" SYSH ENABLE MEMFAULT: %08x BUSFAULT: %08x USGFAULT: %08x SYSTICK: %08x\n",
- getreg32(NVIC_SYSHCON_MEMFAULTENA),
- getreg32(NVIC_SYSHCON_BUSFAULTENA),
- getreg32(NVIC_SYSHCON_USGFAULTENA),
- getreg32(NVIC_SYSTICK_CTRL_ENABLE));
-# endif
irqinfo(" IRQ ENABLE: %08x %08x\n", getreg32(NVIC_IRQ0_31_ENABLE),
getreg32(NVIC_IRQ32_63_ENABLE));
irqinfo(" SYSH_PRIO: %08x %08x %08x\n",
@@ -360,6 +353,7 @@ void up_irqinitialize(void)
#ifdef CONFIG_ARCH_IRQPRIO
/* up_prioritize_irq(CXD56_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */
#endif
+
#ifdef CONFIG_ARMV7M_USEBASEPRI
cxd56_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY);
#endif
diff --git a/arch/arm/src/cxd56xx/cxd56_pinconfig.c b/arch/arm/src/cxd56xx/cxd56_pinconfig.c
index 5b9d4de9c68..90edf20d77d 100644
--- a/arch/arm/src/cxd56xx/cxd56_pinconfig.c
+++ b/arch/arm/src/cxd56xx/cxd56_pinconfig.c
@@ -390,7 +390,8 @@ int cxd56_pin_configs(uint32_t pinconfs[], size_t n)
if (((PIN_I2S0_BCK == pin) || (PIN_I2S1_BCK == pin)) &&
(PINCONF_MODE1 == mode))
{
- set_i2s_output_config(pin, mode, PINCONF_INPUT_ENABLED(pinconfs[i]));
+ set_i2s_output_config(pin, mode,
+ PINCONF_INPUT_ENABLED(pinconfs[i]));
}
ret = get_mode_regaddr(pin, &modereg, &shift);
@@ -408,7 +409,7 @@ int cxd56_pin_configs(uint32_t pinconfs[], size_t n)
return 0;
}
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_pin_status
*
* Description:
@@ -417,7 +418,7 @@ int cxd56_pin_configs(uint32_t pinconfs[], size_t n)
* Returned Value:
* OK on success; A negated errno value on failure.
*
- ********************************************************************************************/
+ ****************************************************************************/
int cxd56_pin_status(uint32_t pin, cxd56_pin_status_t *stat)
{
diff --git a/arch/arm/src/cxd56xx/cxd56_pinconfig.h b/arch/arm/src/cxd56xx/cxd56_pinconfig.h
index 27c6c972408..74d67796d75 100644
--- a/arch/arm/src/cxd56xx/cxd56_pinconfig.h
+++ b/arch/arm/src/cxd56xx/cxd56_pinconfig.h
@@ -39,9 +39,9 @@
#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_PINCONFIG_H
#define __ARCH_ARM_SRC_CXD56XX_CXD56_PINCONFIG_H
-/********************************************************************************************
+/****************************************************************************
* Included Files
- ********************************************************************************************/
+ ****************************************************************************/
#include
@@ -52,9 +52,9 @@
#include
#include "hardware/cxd5602_pinconfig.h"
-/********************************************************************************************
+/****************************************************************************
* Pre-processor Definitions
- ********************************************************************************************/
+ ****************************************************************************/
/* 32-bit encoded pinconf value
*
@@ -140,9 +140,9 @@
cxd56_pin_configs((p), sizeof(p) / sizeof((p)[0])); \
} while (0)
-/********************************************************************************************
+/****************************************************************************
* Public Types
- ********************************************************************************************/
+ ****************************************************************************/
struct cxd56_pin_status_s
{
@@ -154,9 +154,9 @@ struct cxd56_pin_status_s
typedef struct cxd56_pin_status_s cxd56_pin_status_t;
-/********************************************************************************************
+/****************************************************************************
* Public Data
- ********************************************************************************************/
+ ****************************************************************************/
#ifndef __ASSEMBLY__
#ifdef __cplusplus
@@ -167,11 +167,11 @@ extern "C"
#define EXTERN extern
#endif
-/********************************************************************************************
+/****************************************************************************
* Public Functions
- ********************************************************************************************/
+ ****************************************************************************/
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_pin_config
*
* Description:
@@ -183,11 +183,11 @@ extern "C"
* Returned Value:
* OK on success; A negated errno value on failure.
*
- ********************************************************************************************/
+ ****************************************************************************/
int cxd56_pin_config(uint32_t pinconf);
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_pin_configs
*
* Description:
@@ -200,11 +200,11 @@ int cxd56_pin_config(uint32_t pinconf);
* Returned Value:
* OK on success; A negated errno value on failure.
*
- ********************************************************************************************/
+ ****************************************************************************/
int cxd56_pin_configs(uint32_t pinconfs[], size_t n);
-/********************************************************************************************
+/****************************************************************************
* Name: cxd56_pin_status
*
* Description:
@@ -213,7 +213,7 @@ int cxd56_pin_configs(uint32_t pinconfs[], size_t n);
* Returned Value:
* OK on success; A negated errno value on failure.
*
- ********************************************************************************************/
+ ****************************************************************************/
int cxd56_pin_status(uint32_t pin, cxd56_pin_status_t *stat);
@@ -221,6 +221,6 @@ int cxd56_pin_status(uint32_t pin, cxd56_pin_status_t *stat);
#if defined(__cplusplus)
}
#endif
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_PINCONFIG_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_pmic.c b/arch/arm/src/cxd56xx/cxd56_pmic.c
index 67690811596..853202fe638 100644
--- a/arch/arm/src/cxd56xx/cxd56_pmic.c
+++ b/arch/arm/src/cxd56xx/cxd56_pmic.c
@@ -62,6 +62,7 @@
enum pmic_cmd_type_e
{
/* basic */
+
PMIC_CMD_READ = 0x00,
PMIC_CMD_WRITE,
PMIC_CMD_GPO,
@@ -72,7 +73,9 @@ enum pmic_cmd_type_e
PMIC_CMD_GETPREVSYS,
PMIC_CMD_SETVSYS,
PMIC_CMD_GETVSYS,
+
/* charger */
+
PMIC_CMD_GAUGE = 0x10,
PMIC_CMD_GET_USB_PORT_TYPE,
PMIC_CMD_GET_CHG_STATE,
@@ -90,7 +93,9 @@ enum pmic_cmd_type_e
PMIC_CMD_CHG_PAUSE,
PMIC_CMD_CHG_ENABLE,
PMIC_CMD_CHG_DISABLE,
+
/* power monitor */
+
PMIC_CMD_POWER_MONITOR_ENABLE = 0x30,
PMIC_CMD_POWER_MONITOR_STATUS,
PMIC_CMD_POWER_MONITOR_SET,
@@ -142,6 +147,7 @@ enum pmic_cmd_type_e
/****************************************************************************
* Private Types
****************************************************************************/
+
/* FarAPI interface structures */
struct pmic_afe_s
@@ -173,13 +179,13 @@ static struct work_s g_irqwork;
****************************************************************************/
#ifdef CONFIG_CXD56_PMIC_INT
-/************************************************************************************
+/****************************************************************************
* Name: is_notify_registerd
*
* Description:
* Return whether any notification is registered or not
*
- ************************************************************************************/
+ ****************************************************************************/
static bool is_notify_registerd(void)
{
@@ -195,13 +201,13 @@ static bool is_notify_registerd(void)
return false;
}
-/************************************************************************************
+/****************************************************************************
* Name: pmic_int_worker
*
* Description:
* Work queue for pmic interrupt
*
- ************************************************************************************/
+ ****************************************************************************/
static void pmic_int_worker(void *arg)
{
@@ -236,13 +242,13 @@ static void pmic_int_worker(void *arg)
leave_critical_section(flags);
}
-/************************************************************************************
+/****************************************************************************
* Name: pmic_int_handler
*
* Description:
* Interrupt handler for pmic interrupt
*
- ************************************************************************************/
+ ****************************************************************************/
static int pmic_int_handler(int irq, void *context, void *arg)
{
@@ -451,7 +457,7 @@ int cxd56_pmic_set_gpo_hiz(uint8_t chset)
* chset : GPO Channel number(s)
*
* Returned Value:
- * Return true if all of the specified chset are high. Otherwise, return false
+ * Return true if all of the specified chset are high. Else, return false
*
****************************************************************************/
@@ -691,17 +697,19 @@ int cxd56_pmic_get_rtc(uint64_t *count)
ret = cxd56_pmic_write(PMIC_REG_RRQ_TIME, &data, sizeof(data));
if (ret) goto error;
- do {
+ do
+ {
ret = cxd56_pmic_read(PMIC_REG_RRQ_LRQ_STATUS, &data, sizeof(data));
if (ret) goto error;
- } while (!(RRQ_TIME_STATE & data));
+ }
+ while (!(RRQ_TIME_STATE & data));
ret = cxd56_pmic_read(PMIC_REG_RTC, rtc, sizeof(rtc));
if (ret) goto error;
*count =
- (((uint64_t)((rtc[5] << 24) | (rtc[4] << 16) | (rtc[3] << 8) | rtc[2]) << 15) |
- ((rtc[1] << 8) | rtc[0]));
+ (((uint64_t)((rtc[5] << 24) | (rtc[4] << 16) | (rtc[3] << 8) |
+ rtc[2]) << 15) | ((rtc[1] << 8) | rtc[0]));
error:
return ret;
@@ -1112,7 +1120,7 @@ int cxd56_pmic_setchargecompcurrent(int current)
break;
}
- return PM_PmicControl(PMIC_CMD_SET_CHG_IFIN, (void*)val);
+ return PM_PmicControl(PMIC_CMD_SET_CHG_IFIN, (void *)val);
}
/****************************************************************************
diff --git a/arch/arm/src/cxd56xx/cxd56_pmic.h b/arch/arm/src/cxd56xx/cxd56_pmic.h
index 7712c0a9a35..52d09649136 100644
--- a/arch/arm/src/cxd56xx/cxd56_pmic.h
+++ b/arch/arm/src/cxd56xx/cxd56_pmic.h
@@ -46,8 +46,6 @@
#include
#include
-#ifdef CONFIG_CXD56_PMIC
-
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -165,7 +163,7 @@ struct pmic_mon_s
struct pmic_mon_status_s
{
- int bRun;
+ int brun;
int index;
int latest;
int total_watt;
@@ -174,8 +172,8 @@ struct pmic_mon_status_s
struct pmic_mon_set_s
{
- int clearBuf;
- int clearSum;
+ int clearbuf;
+ int clearsum;
};
struct pmic_mon_rec_s
@@ -305,7 +303,7 @@ int cxd56_pmic_set_gpo_hiz(uint8_t chset);
* chset : GPO Channel number(s)
*
* Returned Value:
- * Return true if all of the specified chset are high. Otherwise, return false
+ * Return true if all of the specified chset are high. Else, return false
*
****************************************************************************/
@@ -573,7 +571,7 @@ int cxd56_pmic_getchargestate(FAR uint8_t *state);
*
****************************************************************************/
-int cxd56_pmic_setrechargevol(int mV);
+int cxd56_pmic_setrechargevol(int mv);
/****************************************************************************
* Name: cxd56_pmic_getrechargevol
@@ -589,7 +587,7 @@ int cxd56_pmic_setrechargevol(int mV);
*
****************************************************************************/
-int cxd56_pmic_getrechargevol(FAR int *mV);
+int cxd56_pmic_getrechargevol(FAR int *mv);
/****************************************************************************
* Name: cxd56_pmic_setchargecompcurrent
@@ -755,7 +753,6 @@ int cxd56_pmic_monitor_get(FAR struct pmic_mon_log_s *ptr);
#if defined(__cplusplus)
}
#endif
-#endif /* __ASSEMBLY__ */
-#endif /* CONFIG_CXD56_PMIC */
+#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_PMIC_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_powermgr.c b/arch/arm/src/cxd56xx/cxd56_powermgr.c
new file mode 100644
index 00000000000..dace6660490
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_powermgr.c
@@ -0,0 +1,1011 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_powermgr.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "up_internal.h"
+#include "up_arch.h"
+#include "cxd56_powermgr.h"
+#include "cxd56_icc.h"
+#include "cxd56_pmic.h"
+#include "chip.h"
+#include "hardware/cxd5602_backupmem.h"
+
+#define INTC_REG_INV(n) (CXD56_INTC_BASE + 0x20 + ((n) << 2))
+#define INTC_REG_EN(n) (CXD56_INTC_BASE + 0x10 + ((n) << 2))
+
+/* bootmask control */
+
+#define NON_MASKABLE_BOOTMASK (PM_BOOT_POR_NORMAL | \
+ PM_BOOT_POR_DEADBATT | \
+ PM_BOOT_WDT_REBOOT | \
+ PM_BOOT_WDT_RESET | \
+ PM_BOOT_DEEP_USB_ATTACH | \
+ PM_BOOT_DEEP_OTHERS)
+#define DEEP_PROHIBIT_BOOTMASK (PM_BOOT_DEEP_WKUPS | \
+ PM_BOOT_DEEP_RTC)
+#define CONFIG_INT_WKUP_REG (0x38)
+#define WKUPL_ENABLE (0x2)
+#define WKUPL_DISABLE (0x0)
+
+#define MSGID_BOOT 0
+#define MSGID_FREQLOCK 1
+#define MSGID_CLK_CHG_START 2
+#define MSGID_CLK_CHG_END 3
+#define MSGID_GET_CLK 4
+#define MSGID_HOT_SLEEP 5
+#define MSGID_RESUME 6
+
+#define MQMSG_CLK_CHG_START 0
+#define MQMSG_CLK_CHG_END 1
+#define MQMSG_HOT_SLEEP 2
+
+#define CXD56_PM_SYS_CPU (0)
+#define CXD56_PM_SYS_APP (2)
+
+#define PM_CPUFREQLOCK_FLAG_INITIALIZED (0x8000)
+
+#ifdef CONFIG_CXD56_PM_DEBUG
+# define pmerr(format, ...) _err(format, ##__VA_ARGS__)
+# define pmwarn(format, ...) _warn(format, ##__VA_ARGS__)
+# define pminfo(format, ...) _info(format, ##__VA_ARGS__)
+#else
+# define pmerr(x...)
+# define pmwarn(x...)
+# define pminfo(x...)
+#endif
+
+void up_cpuctxload(void);
+int cxd56_cpu_context_sleep(void);
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cxd56_pm_target_id_s
+{
+ uint32_t sysiop;
+ uint32_t app;
+ uint32_t pmu;
+ uint32_t hostif;
+ uint32_t scu;
+ uint32_t gps;
+};
+
+struct cxd56_pm_hotsleep_info_s
+{
+ int cpu_id;
+ uint32_t entry;
+ uint64_t requested_sleeptime;
+ uint64_t sleep_starttime;
+ uint64_t wakeuptime;
+};
+
+struct cxd56_pm_message_s
+{
+ uint8_t mid;
+ uint32_t data;
+};
+
+struct pm_cbentry_s
+{
+ struct dq_entry_s dq_entry;
+ uint32_t target;
+ cxd56_pm_callback callback;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int cxd56_pm_do_callback(uint8_t id,
+ FAR struct cxd56_pm_target_id_s *table);
+static int cxd56_pm_needcallback(uint32_t target,
+ FAR struct cxd56_pm_target_id_s *table);
+static void cxd56_pm_clkchange(struct cxd56_pm_message_s *message);
+static int cxd56_pm_semtake(FAR sem_t *id);
+static void cxd56_pm_checkfreqlock(void);
+static int cxd56_pm_maintask(int argc, FAR char *argv[]);
+#if defined(CONFIG_CXD56_HOT_SLEEP)
+static void cxd56_pm_do_hotsleep(uint32_t idletime);
+static void cxd56_pm_intc_suspend(void);
+static void cxd56_pm_intc_resume(void);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct cxd56_pm_target_id_s g_target_id_table;
+static mqd_t g_queuedesc;
+static sem_t g_regcblock;
+static sem_t g_freqlock;
+static sem_t g_freqlockwait;
+static dq_queue_t g_cbqueue;
+static sq_queue_t g_freqlockqueue;
+static sq_queue_t g_wakelockqueue;
+static uint32_t g_clockcange_start;
+static int g_freqlock_flag;
+
+static struct pm_cpu_wakelock_s g_wlock =
+ PM_CPUWAKELOCK_INIT(PM_CPUWAKELOCK_TAG('P', 'M', 0));
+
+static int cxd56_pm_semtake(FAR sem_t *id)
+{
+ while (sem_wait(id) != 0)
+ {
+ if (errno != EINTR)
+ {
+ pmerr("ERR:sem_wait\n");
+ return errno;
+ }
+ }
+ return OK;
+}
+
+static int cxd56_pm_needcallback(uint32_t target,
+ FAR struct cxd56_pm_target_id_s *table)
+{
+ uint32_t mask;
+
+ switch (target & PM_DOMAIN_MASK)
+ {
+ case PM_DOMAIN_SYSIOP:
+ mask = table->sysiop;
+ break;
+ case PM_DOMAIN_HOSTIF:
+ mask = table->hostif;
+ break;
+ case PM_DOMAIN_PMU:
+ mask = table->pmu;
+ break;
+ case PM_DOMAIN_SCU:
+ mask = table->scu;
+ break;
+ case PM_DOMAIN_APP:
+ mask = table->app;
+ break;
+ case PM_DOMAIN_GPS:
+ mask = table->gps;
+ break;
+ default:
+ return 0;
+ }
+
+ return mask & target;
+}
+
+static int cxd56_pmsendmsg(int mid, uint32_t data)
+{
+ iccmsg_t msg;
+
+ msg.cpuid = 0;
+ msg.msgid = 0; /* Power manger message does not used this field. */
+ msg.protodata = mid;
+ msg.data = data;
+ return cxd56_iccsend(CXD56_PROTO_PM, &msg, 0);
+}
+
+static int cxd56_pm_do_callback(uint8_t id,
+ struct cxd56_pm_target_id_s *targets)
+{
+ FAR struct pm_cbentry_s *entry;
+ FAR dq_entry_t *cur;
+ FAR dq_entry_t *last;
+ int ret = 0;
+
+ for (cur = dq_peek(&g_cbqueue); cur; cur = dq_next(cur))
+ {
+ entry = (FAR struct pm_cbentry_s *)cur;
+ last = cur;
+ if (cxd56_pm_needcallback(entry->target, targets))
+ {
+ ret = entry->callback(id);
+ if (ret != 0)
+ {
+ break;
+ }
+ }
+ }
+
+ /* If one of the callbacks has been failed, then recovery call to previously
+ * called entries.
+ */
+
+ if (ret != 0)
+ {
+ /* Replace callback ID to recovery */
+
+ if (id == CXD56_PM_CALLBACK_ID_CLK_CHG_START)
+ {
+ id = CXD56_PM_CALLBACK_ID_CLK_CHG_END;
+ }
+ if (id == CXD56_PM_CALLBACK_ID_HOT_SLEEP)
+ {
+ id = CXD56_PM_CALLBACK_ID_HOT_BOOT;
+ }
+
+ for (cur = dq_peek(&g_cbqueue); cur != last; cur = dq_next(cur))
+ {
+ entry = (FAR struct pm_cbentry_s *)cur;
+ if (cxd56_pm_needcallback(entry->target, targets))
+ {
+ entry->callback(id);
+ }
+ }
+ }
+
+ return ret;
+}
+
+static void cxd56_pm_clkchange(struct cxd56_pm_message_s *message)
+{
+ uint8_t id;
+ int mid;
+ int ret;
+
+ switch (message->mid)
+ {
+ case MQMSG_CLK_CHG_START:
+ id = CXD56_PM_CALLBACK_ID_CLK_CHG_START;
+ mid = MSGID_CLK_CHG_START;
+ g_clockcange_start = 1;
+ break;
+ case MQMSG_CLK_CHG_END:
+ if (g_clockcange_start == 0)
+ {
+ return;
+ }
+ id = CXD56_PM_CALLBACK_ID_CLK_CHG_END;
+ mid = MSGID_CLK_CHG_END;
+ g_clockcange_start = 0;
+ break;
+ default:
+ return;
+ }
+
+ cxd56_pm_semtake(&g_regcblock);
+
+ ret = cxd56_pm_do_callback(id, &g_target_id_table);
+
+ cxd56_pmsendmsg(mid, ret);
+
+ sem_post(&g_regcblock);
+}
+
+static void cxd56_pm_checkfreqlock(void)
+{
+ FAR sq_entry_t *entry;
+ FAR struct pm_cpu_freqlock_s *lock;
+ int flag = PM_CPUFREQLOCK_FLAG_INITIALIZED;
+
+ for (entry = sq_peek(&g_freqlockqueue); entry; entry = sq_next(entry))
+ {
+ lock = (FAR struct pm_cpu_freqlock_s *)entry;
+ flag |= lock->flag & PM_CPUFREQLOCK_FLAG_LV;
+ flag |= lock->flag & PM_CPUFREQLOCK_FLAG_HV;
+ }
+
+ if (g_freqlock_flag != flag)
+ {
+ g_freqlock_flag = flag;
+ cxd56_pmsendmsg(MSGID_FREQLOCK, flag);
+ cxd56_pm_semtake(&g_freqlockwait);
+ }
+}
+
+#if defined(CONFIG_CXD56_HOT_SLEEP)
+static void cxd56_pm_intc_suspend(void)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ BKUP->irq_inv_map[i] = getreg32(INTC_REG_INV(i));
+ BKUP->irq_wake_map[i] = getreg32(INTC_REG_EN(i));
+ putreg32(0, INTC_REG_INV(i));
+ putreg32(0, INTC_REG_EN(i));
+ }
+}
+
+static void cxd56_pm_intc_resume(void)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ putreg32(BKUP->irq_inv_map[i], INTC_REG_INV(i));
+ putreg32(BKUP->irq_wake_map[i], INTC_REG_EN(i));
+ }
+}
+
+static void cxd56_pm_do_hotsleep(uint32_t idletime)
+{
+ irqstate_t flags;
+ uint64_t time;
+ uint32_t tick;
+ struct cxd56_pm_hotsleep_info_s info;
+ struct cxd56_pm_target_id_s table;
+ iccmsg_t msg;
+ int ret;
+
+ if (up_pm_count_acquire_wakelock() != 0)
+ {
+ return;
+ }
+
+ table.sysiop = PM_DOMAIN_SYSIOP | ~PM_DOMAIN_MASK;
+ table.app = PM_DOMAIN_APP | ~PM_DOMAIN_MASK;
+ table.pmu = PM_DOMAIN_PMU | ~PM_DOMAIN_MASK;
+ table.hostif = PM_DOMAIN_HOSTIF | ~PM_DOMAIN_MASK;
+ table.scu = PM_DOMAIN_SCU | ~PM_DOMAIN_MASK;
+ table.gps = PM_DOMAIN_GPS | ~PM_DOMAIN_MASK;
+
+ ret = cxd56_pm_do_callback(CXD56_PM_CALLBACK_ID_HOT_SLEEP, &table);
+ if (ret != 0)
+ {
+ return;
+ }
+
+ flags = enter_critical_section();
+
+ info.cpu_id = CXD56_PM_SYS_APP;
+ info.entry = (uint32_t)up_cpuctxload | 0x1;
+ info.requested_sleeptime = idletime;
+ info.sleep_starttime = 0;
+ info.wakeuptime = 0;
+
+ cxd56_pmsendmsg(MSGID_HOT_SLEEP, (uint32_t)(uintptr_t)&info);
+
+ cxd56_pm_intc_suspend();
+ cxd56_cpu_context_sleep();
+
+ leave_critical_section(flags);
+
+ if (info.sleep_starttime != 0)
+ {
+ time = info.wakeuptime - info.sleep_starttime;
+ tick = (time * USEC_PER_MSEC) / CONFIG_USEC_PER_TICK;
+ sched_process_timer_skip(tick);
+ }
+
+ cxd56_pm_do_callback(CXD56_PM_CALLBACK_ID_HOT_BOOT, &table);
+
+ cxd56_pm_intc_resume();
+
+ cxd56_pmsendmsg(MSGID_RESUME, 0);
+}
+#endif
+
+static int cxd56_pm_maintask(int argc, FAR char *argv[])
+{
+ int size;
+ struct cxd56_pm_message_s message;
+
+ while (1)
+ {
+ size = mq_receive(g_queuedesc, (FAR char *)&message, sizeof(message),
+ NULL);
+ if (size == sizeof(message))
+ {
+ switch (message.mid)
+ {
+ case MQMSG_CLK_CHG_START:
+ case MQMSG_CLK_CHG_END:
+ cxd56_pm_clkchange(&message);
+ break;
+ case MQMSG_HOT_SLEEP:
+#if defined(CONFIG_CXD56_HOT_SLEEP)
+ cxd56_pm_do_hotsleep(message.data);
+#endif
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
+FAR void *cxd56_pm_register_callback(uint32_t target,
+ cxd56_pm_callback callback)
+{
+ struct pm_cbentry_s *entry = NULL;
+
+ cxd56_pm_semtake(&g_regcblock);
+
+ entry = (struct pm_cbentry_s *)kmm_malloc(sizeof(struct pm_cbentry_s));
+ if (entry == NULL)
+ {
+ sem_post(&g_regcblock);
+ return NULL;
+ }
+
+ entry->target = target;
+ entry->callback = callback;
+
+ dq_addlast((FAR dq_entry_t *)entry, &g_cbqueue);
+ sem_post(&g_regcblock);
+
+ return (void *)entry;
+}
+
+void cxd56_pm_unregister_callback(FAR void *handle)
+{
+ cxd56_pm_semtake(&g_regcblock);
+
+ dq_rem((FAR dq_entry_t *)handle, &g_cbqueue);
+ kmm_free(handle);
+
+ sem_post(&g_regcblock);
+}
+
+static int cxd56_pmmsghandler(int cpuid, int protoid, uint32_t pdata,
+ uint32_t data, FAR void *userdata)
+{
+ uint32_t msgid;
+ struct cxd56_pm_message_s message;
+ int ret;
+
+ msgid = pdata;
+
+ if (msgid == MSGID_CLK_CHG_START)
+ {
+ message.mid = MQMSG_CLK_CHG_START;
+ ret = mq_send(g_queuedesc, (FAR const char *)&message, sizeof(message),
+ CXD56_PM_MESSAGE_PRIO);
+ if (ret < 0)
+ {
+ pmerr("ERR:mq_send(CLK_CHG_START)\n");
+ }
+ }
+ else if (msgid == MSGID_CLK_CHG_END)
+ {
+ message.mid = MQMSG_CLK_CHG_END;
+ ret = mq_send(g_queuedesc, (FAR const char *)&message, sizeof(message),
+ CXD56_PM_MESSAGE_PRIO);
+ if (ret < 0)
+ {
+ pmerr("ERR:mq_send(CLK_CHG_END)\n");
+ }
+ }
+ else if (msgid == MSGID_FREQLOCK)
+ {
+ sem_post(&g_freqlockwait);
+ }
+ else
+ {
+ pmerr("Unknown message %d\n", msgid);
+ }
+
+ return 0;
+}
+
+int cxd56_pm_bootup(void)
+{
+ /* BOOT indicate to M0P */
+
+ cxd56_pmsendmsg(MSGID_BOOT, (uint32_t)(uintptr_t)&g_target_id_table);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_pm_acquire_freqlock
+ *
+ * Description:
+ * Acquire the specified freqlock. If the higher freqlock is acquired, the
+ * system can clockup until it is released.
+ *
+ * Parameter:
+ * lock - the pointer of a wakelock variable
+ *
+ ****************************************************************************/
+
+void up_pm_acquire_freqlock(struct pm_cpu_freqlock_s *lock)
+{
+ FAR sq_entry_t *entry;
+
+ DEBUGASSERT(lock);
+
+ up_pm_acquire_wakelock(&g_wlock);
+
+ cxd56_pm_semtake(&g_freqlock);
+
+ for (entry = sq_peek(&g_freqlockqueue); entry; entry = sq_next(entry))
+ {
+ if (entry == (struct sq_entry_s *)lock)
+ {
+ break;
+ }
+ }
+
+ if (!entry)
+ {
+ sq_addlast((FAR sq_entry_t *)lock, &g_freqlockqueue);
+ cxd56_pm_checkfreqlock();
+ }
+
+ lock->count++;
+
+ sem_post(&g_freqlock);
+
+ up_pm_release_wakelock(&g_wlock);
+}
+
+/****************************************************************************
+ * Name: up_pm_release_freqlock
+ *
+ * Description:
+ * Release the specified freqlock. If the freqlock are released, the system
+ * can drop to the lower clock mode for power saving.
+ *
+ * Parameter:
+ * lock - the pointer of a freqlock variable
+ *
+ ****************************************************************************/
+
+void up_pm_release_freqlock(struct pm_cpu_freqlock_s *lock)
+{
+ FAR sq_entry_t *entry;
+
+ DEBUGASSERT(lock);
+
+ up_pm_acquire_wakelock(&g_wlock);
+
+ cxd56_pm_semtake(&g_freqlock);
+
+ for (entry = sq_peek(&g_freqlockqueue); entry; entry = sq_next(entry))
+ {
+ if (entry == (struct sq_entry_s *)lock)
+ {
+ lock->count--;
+ if (lock->count <= 0)
+ {
+ sq_rem(entry, &g_freqlockqueue);
+ cxd56_pm_checkfreqlock();
+ }
+ break;
+ }
+ }
+
+ sem_post(&g_freqlock);
+
+ up_pm_release_wakelock(&g_wlock);
+}
+
+/****************************************************************************
+ * Name: up_pm_get_freqlock_count
+ *
+ * Description:
+ * Get the locked count of the specified freqlock
+ *
+ * Parameter:
+ * lock - the pointer of a freqlock variable
+ *
+ * Return:
+ * the locked count of the specified freqlock
+ *
+ ****************************************************************************/
+
+int up_pm_get_freqlock_count(struct pm_cpu_freqlock_s *lock)
+{
+ FAR sq_entry_t *entry;
+ int count = 0;
+
+ DEBUGASSERT(lock);
+
+ cxd56_pm_semtake(&g_freqlock);
+
+ for (entry = sq_peek(&g_freqlockqueue); entry; entry = sq_next(entry))
+ {
+ if (entry == (struct sq_entry_s *)lock)
+ {
+ count = lock->count;
+ break;
+ }
+ }
+
+ sem_post(&g_freqlock);
+ return count;
+}
+
+/****************************************************************************
+ * Name: up_pm_acquire_wakelock
+ *
+ * Description:
+ * Acquire the specified wakelock. If any wakelock is acquired, CPU can't
+ * enter to the hot sleep state.
+ *
+ * Parameter:
+ * lock - the pointer of a wakelock variable
+ *
+ ****************************************************************************/
+
+void up_pm_acquire_wakelock(struct pm_cpu_wakelock_s *lock)
+{
+ irqstate_t flags;
+ FAR sq_entry_t *entry;
+
+ DEBUGASSERT(lock);
+
+ flags = enter_critical_section();
+
+ for (entry = sq_peek(&g_wakelockqueue); entry; entry = sq_next(entry))
+ {
+ if (entry == (struct sq_entry_s *)lock)
+ {
+ break;
+ }
+ }
+
+ if (!entry)
+ {
+ sq_addlast((FAR sq_entry_t *)lock, &g_wakelockqueue);
+ }
+
+ lock->count++;
+
+ leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: up_pm_release_wakelock
+ *
+ * Description:
+ * Release the specified wakelock. If all of the wakelock are released,
+ * CPU can enter to the hot sleep state.
+ *
+ * Parameter:
+ * lock - the pointer of a wakelock variable
+ *
+ ****************************************************************************/
+
+void up_pm_release_wakelock(struct pm_cpu_wakelock_s *lock)
+{
+ irqstate_t flags;
+ FAR sq_entry_t *entry;
+
+ DEBUGASSERT(lock);
+
+ flags = enter_critical_section();
+
+ for (entry = sq_peek(&g_wakelockqueue); entry; entry = sq_next(entry))
+ {
+ if (entry == (struct sq_entry_s *)lock)
+ {
+ lock->count--;
+ if (lock->count <= 0)
+ {
+ sq_rem(entry, &g_wakelockqueue);
+ }
+ break;
+ }
+ }
+
+ leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: up_pm_count_acquire_wakelock
+ *
+ * Description:
+ * Count the total number of wakelock
+ *
+ * Return:
+ * the total number of wakelock
+ *
+ ****************************************************************************/
+
+int up_pm_count_acquire_wakelock(void)
+{
+ irqstate_t flags;
+ int num;
+
+ flags = enter_critical_section();
+
+ num = sq_count(&g_wakelockqueue);
+
+ leave_critical_section(flags);
+
+ return num;
+}
+
+int cxd56_pm_hotsleep(int idletime)
+{
+ struct cxd56_pm_message_s message;
+ int ret;
+
+ if (up_pm_count_acquire_wakelock() != 0)
+ {
+ return -1;
+ }
+
+ message.mid = MQMSG_HOT_SLEEP;
+ message.data = (uint32_t)idletime;
+ ret = mq_send(g_queuedesc, (FAR const char *)&message, sizeof(message),
+ CXD56_PM_MESSAGE_PRIO);
+ if (ret < 0)
+ {
+ pmerr("ERR:mq_send(HOT_SLEEP)\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int cxd56_pm_initialize(void)
+{
+ struct mq_attr attr;
+ int taskid;
+ int ret;
+
+ cxd56_iccinit(CXD56_PROTO_PM);
+
+ /* Register power manager messaging protocol handler. */
+
+ cxd56_iccregisterhandler(CXD56_PROTO_PM, cxd56_pmmsghandler, NULL);
+
+ dq_init(&g_cbqueue);
+ sq_init(&g_freqlockqueue);
+ sq_init(&g_wakelockqueue);
+
+ ret = sem_init(&g_regcblock, 0, 1);
+ if (ret < 0)
+ {
+ return -EPERM;
+ }
+
+ ret = sem_init(&g_freqlock, 0, 1);
+ if (ret < 0)
+ {
+ return -EPERM;
+ }
+
+ ret = sem_init(&g_freqlockwait, 0, 0);
+ if (ret < 0)
+ {
+ return -EPERM;
+ }
+
+ attr.mq_maxmsg = 8;
+ attr.mq_msgsize = sizeof(struct cxd56_pm_message_s);
+ attr.mq_curmsgs = 0;
+ attr.mq_flags = 0;
+ g_queuedesc = mq_open("cxd56_pm_message", O_RDWR | O_CREAT, 0666, &attr);
+ if (g_queuedesc < 0)
+ {
+ return -EPERM;
+ }
+
+ taskid = task_create("cxd56_pm_task", CXD56_PM_TASK_PRIO,
+ CXD56_PM_TASK_STACKSIZE, cxd56_pm_maintask,
+ (FAR char * const *)NULL);
+ if (taskid < 0)
+ {
+ return -EPERM;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_pm_get_bootcause
+ *
+ * Description:
+ * Get the system boot cause. This boot cause indicates the cause why the
+ * system is launched from the state of power-off, deep sleep or cold sleep.
+ * Each boot cause is defined as PM_BOOT_XXX.
+ *
+ * Return:
+ * Boot cause
+ *
+ ****************************************************************************/
+
+uint32_t up_pm_get_bootcause(void)
+{
+ return BKUP->bootcause;
+}
+
+/****************************************************************************
+ * Name: up_pm_get_bootmask
+ *
+ * Description:
+ * Get the system boot mask. This boot mask indicates whether the specified
+ * bit is enabled or not as the boot cause. If a bit of boot mask is set,
+ * the boot cause is enabled. Each boot mask is defined as PM_BOOT_XXX.
+ *
+ * Return:
+ * Boot mask
+ *
+ ****************************************************************************/
+
+uint32_t up_pm_get_bootmask(void)
+{
+ return BKUP->bootmask;
+}
+
+/****************************************************************************
+ * Name: up_pm_set_bootmask
+ *
+ * Description:
+ * Enable the boot cause of the specified bit.
+ *
+ * Parameter:
+ * mask - OR of Boot mask definied as PM_BOOT_XXX
+ *
+ * Return:
+ * Updated boot mask
+ *
+ ****************************************************************************/
+
+uint32_t up_pm_set_bootmask(uint32_t mask)
+{
+ irqstate_t flags;
+
+ /* Enable emergency recovery by WKUPL
+ * only when bootmask is changed from disable to enable
+ */
+
+#ifdef CONFIG_CXD56_PMIC
+ if (!(BKUP->bootmask & PM_BOOT_DEEP_WKUPL) && (mask & PM_BOOT_DEEP_WKUPL))
+ {
+ uint8_t value = WKUPL_ENABLE;
+ cxd56_pmic_write(CONFIG_INT_WKUP_REG, &value, sizeof(value));
+ }
+#endif
+
+ flags = enter_critical_section();
+
+ BKUP->bootmask |= mask;
+
+ leave_critical_section(flags);
+
+ return BKUP->bootmask;
+}
+
+/****************************************************************************
+ * Name: up_pm_clr_bootmask
+ *
+ * Description:
+ * Disable the boot cause of the specified bit.
+ *
+ * Parameter:
+ * mask - OR of Boot mask definied as PM_BOOT_XXX
+ *
+ * Return:
+ * Updated boot mask
+ *
+ ****************************************************************************/
+
+uint32_t up_pm_clr_bootmask(uint32_t mask)
+{
+ irqstate_t flags;
+
+ /* Disable emergency recovery by WKUPL,
+ * only when bootmask is changed from enable to disable
+ */
+
+#ifdef CONFIG_CXD56_PMIC
+ if ((BKUP->bootmask & PM_BOOT_DEEP_WKUPL) && (mask & PM_BOOT_DEEP_WKUPL))
+ {
+ uint8_t value = WKUPL_DISABLE;
+ cxd56_pmic_write(CONFIG_INT_WKUP_REG, &value, sizeof(value));
+ }
+#endif
+
+ flags = enter_critical_section();
+
+ /* Check if non-maskable bit */
+
+ if (mask & NON_MASKABLE_BOOTMASK)
+ {
+ pmwarn("Can't be disabled 0x%08x\n", (mask & NON_MASKABLE_BOOTMASK));
+ mask &= ~NON_MASKABLE_BOOTMASK;
+ }
+
+ /* Make it impossible to be disable both WKUPS and RTC in DEEP */
+
+ if (((BKUP->bootmask & ~mask) & DEEP_PROHIBIT_BOOTMASK) == 0)
+ {
+ pmwarn("Can't be disabled both 0x%08x and 0x%08x\n",
+ PM_BOOT_DEEP_WKUPS, PM_BOOT_DEEP_RTC);
+ mask &= ~DEEP_PROHIBIT_BOOTMASK;
+ }
+
+ BKUP->bootmask &= ~mask;
+
+ leave_critical_section(flags);
+
+ return BKUP->bootmask;
+}
+
+/****************************************************************************
+ * Name: up_pm_sleep
+ *
+ * Description:
+ * Enter sleep mode. This function never returns.
+ *
+ * Parameter:
+ * mode - PM_SLEEP_DEEP or PM_SLEEP_COLD
+ *
+ ****************************************************************************/
+
+int up_pm_sleep(enum pm_sleepmode_e mode)
+{
+ int PM_DeepSleep(void *);
+ int PM_ColdSleep(void *);
+
+ switch (mode)
+ {
+ case PM_SLEEP_DEEP:
+ PM_DeepSleep(NULL);
+ break;
+ case PM_SLEEP_COLD:
+ PM_ColdSleep(NULL);
+ break;
+ }
+ __asm volatile ("dsb");
+ for (; ; );
+}
+
+/****************************************************************************
+ * Name: up_pm_reboot
+ *
+ * Description:
+ * System reboot. This function never returns.
+ *
+ ****************************************************************************/
+
+int up_pm_reboot(void)
+{
+ void PM_Reboot(void);
+ PM_Reboot();
+ __asm volatile ("dsb");
+ for (; ; );
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_powermgr.h b/arch/arm/src/cxd56xx/cxd56_powermgr.h
new file mode 100644
index 00000000000..2c2184a39c7
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_powermgr.h
@@ -0,0 +1,350 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_powermgr.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_POWERMGR_H
+#define __ARCH_ARM_SRC_CXD56XX_POWERMGR_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define CXD56_PM_SET_CPUID(wrd0, cpuid) ((((cpuid) & 0xF) << 28) |\
+ ((wrd0) & 0x0FFFFFFF))
+#define CXD56_PM_SET_PROTO(msg, proto) ((((proto) & 0xF) << 24) |\
+ ((msg) & 0xF0FFFFFF))
+
+#define CXD56_PM_FIFO_PROTO_PM (10)
+
+#define CXD56_PM_FIFO_MSG_ID_BOOT_INDE (0)
+#define CXD56_PM_FIFO_MSG_ID_FREQLOCK (1)
+#define CXD56_PM_FIFO_MSG_ID_CLK_CHG_START (2)
+#define CXD56_PM_FIFO_MSG_ID_CLK_CHG_END (3)
+#define CXD56_PM_FIFO_MSG_ID_GET_CLK (4)
+#define CXD56_PM_FIFO_MSG_ID_HOT_SLEEP (5)
+#define CXD56_PM_FIFO_MSG_ID_RESUME (6)
+
+#define CXD56_PM_SYS_CPU (0)
+#define CXD56_PM_SYS_APP (2)
+
+#define CXD56_PM_TASK_PRIO (200)
+#define CXD56_PM_TASK_STACKSIZE (1024)
+#define CXD56_PM_MESSAGE_PRIO (1)
+
+#define CXD56_PM_INTERNAL_MGS_CLK_CHG_START (0)
+#define CXD56_PM_INTERNAL_MGS_CLK_CHG_END (1)
+#define CXD56_PM_INTERNAL_MGS_HOT_SLEEP (2)
+
+#define CXD56_PM_CALLBACK_ID_CLK_CHG_START (0)
+#define CXD56_PM_CALLBACK_ID_CLK_CHG_END (1)
+#define CXD56_PM_CALLBACK_ID_HOT_SLEEP (2)
+#define CXD56_PM_CALLBACK_ID_HOT_BOOT (3)
+
+#define PM_CPUFREQLOCK_FLAG_INITIALIZED (0x8000)
+
+/* Data corresponding to a clock tree */
+
+/* Power DOMAIN */
+
+#define PM_DOMAIN_SELF_CPU (0x00000000ul)
+#define PM_DOMAIN_SYSIOP (0x20000000ul)
+#define PM_DOMAIN_HOSTIF (0x40000000ul)
+#define PM_DOMAIN_PMU (0x60000000ul)
+#define PM_DOMAIN_SCU (0x80000000ul)
+#define PM_DOMAIN_APP (0xA0000000ul)
+#define PM_DOMAIN_GPS (0xC0000000ul)
+#define PM_DOMAIN_MASK (0xE0000000ul)
+#define PM_DOMAIN_PLUS (0x20000000ul)
+
+/* Clock Tree Bit Data */
+
+/* SYSIOP */
+
+#define PM_CLOCK_SYS_CTRL_SEL_B (0x00010000ul) /**< 16*/
+#define PM_CLOCK_SYSPLL_DIV_B (0x00008000ul) /**< 15:CKSEL_ROOT.SWCTL_CLK_SEL_RFPLL1 */
+#define PM_CLOCK_SYS_CPU_SEL_B (0x00002000ul) /**< 13:CKSEL_ROOT.SWCTL_CLK_SEL */
+#define PM_CLOCK_SYS_CPU_DIV_B (0x00001000ul) /**< 12:CKDIV_CPU_DSP_BUS.CK_M0 */
+#define PM_CLOCK_SYS_AHB_DIV_B (0x00000800ul) /**< 11:CKDIV_CPU_DSP_BUS.CK_AHB */
+#define PM_CLOCK_SYS_APB_DIV_B (0x00000400ul) /**< 10:CKDIV_CPU_DSP_BUS.CK_APB */
+#define PM_CLOCK_SYS_COMIF_DIV_B (0x00000200ul) /**< 9;CKDIV_COM.CK_COM */
+#define PM_CLOCK_SYS_UART1_SEL_B (0x00000100ul) /**< 8:CKSEL_SYSIOP_SUB.SEL_UART1 */
+#define PM_CLOCK_SYS_SFC_DIV_B (0x00000080ul) /**< 7:CKDIV_CPU_DSP_BUS.SFC_HCLK_LOW */
+#define PM_CLOCK_PMU_RTC_PCLK_SEL_B (0x00000040ul) /**< 6:CKSEL_PMU.SEL_RTC_PCLK */
+
+/* HOSTIF */
+
+#define PM_CLOCK_HIF_SEL_B (0x00000040ul) /**< CKSEL_SYSIOP.SEL_HOST */
+#define PM_CLOCK_HIF_DIV_B (0x00000020ul) /**< CKDIV_HOSTIFC.CK_HOSTIFC */
+#define PM_CLOCK_HIF_SEL2_B (0x00000004ul) /**< CKSEL_SYSIOP.SEL_HOST2 */
+#define PM_CLOCK_HIF_UART0_SEL_B (0x00000002ul) /**< CKSEL_SYSIOP.SEL_UART0 */
+#define PM_CLOCK_HIF_I2C_SEL_B (0x00000001ul) /**< CKSEL_SYSIOP.SEL_I2CS */
+
+/* SCU */
+
+#define PM_CLOCK_SCU_XOSC_DIV_B (0x00000010ul) /**< CKSEL_SCU.SEL_SCU_XTAL */
+#define PM_CLOCK_SCU_SEL_B (0x00000004ul) /**< CKSEL_SCU.SEL_SCU */
+#define PM_CLOCK_SCU_32K_SEL_B (0x00000008ul) /**< CKSEL_SCU.SEL_SCU_32K */
+#define PM_CLOCK_SCU_HPADC_SEL_B (0x00000002ul) /**< CKDIV_SCU.SCU_U32KH */
+#define PM_CLOCK_SCU_LPADC_DIV_B (0x00000001ul) /**< CKDIV_SCU.SCU_U32KL */
+
+/* APP */
+
+#define PM_CLOCK_APP_SYSPLL_DIV_B (0x00004000ul) /**< APP_CKSEL.SWCTL_CLK_SEL_SP */
+#define PM_CLOCK_APP_CPU_SEL_B (0x00000400ul) /**< APP_CKSEL.SWCTL_CLK_SEL */
+#define PM_CLOCK_APP_AUD_MCLK_DIV_B (0x00000200ul) /**< APP_DIV.AU_MCLK */
+#define PM_CLOCK_APP_AUD_MCLK_SEL_B (0x00000100ul) /**< APP_CKSEL.AU_MCLK */
+#define PM_CLOCK_APP_AHB_GEAR_B (0x00000080ul) /**< GEAR_AHB */
+#define PM_CLOCK_APP_UART_GEAR_B (0x00000040ul) /**< GEAR_IMG_UART */
+#define PM_CLOCK_APP_SPI_GEAR_B (0x00000020ul) /**< GEAR_IMG_SPI */
+#define PM_CLOCK_APP_WSPI_GEAR_B (0x00000008ul) /**< GEAR_IMG_WSPI */
+#define PM_CLOCK_APP_SDIO_GEAR_B (0x00000004ul) /**< GEAR_PER_SDIO */
+#define PM_CLOCK_APP_USB_GEAR_B (0x00000002ul) /**< GEAR_PER_USB */
+#define PM_CLOCK_APP_VSYNC_GEAR_B (0x00000001ul) /**< GEAR_M_IMG_VENB/GEAR_N_IMG_VENB */
+#define PM_CLOCK_APP_VSYNC_GEAR_N (0x00020000ul) /**< GEAR_N_IMG_VENB */
+
+/* GPS */
+
+#define PM_CLOCK_GPS_PLL_SEL_B (0x00004000ul) /**< CKSEL_ROOT.SEL_RF_PLL_0 */
+#define PM_CLOCK_GPS_ACQ_SEL_B (0x00000200ul) /**< CKSEL_GNSS_BB.SEL_ACQ */
+#define PM_CLOCK_GPS_ITP_TRK_SEL_B (0x00000080ul) /**< CKDIV_ITP.ITP_TRK */
+#define PM_CLOCK_GPS_BB_MODE_SEL_B (0x00000400ul) /**< CKSEL_GNSS_BB.GNSS_MODE */
+#define PM_CLOCK_GPS_LOGGER_SEL_B (0x00000040ul) /**< CKSEL_GNSS_BB.SEL_LOG */
+#define PM_CLOCK_GPS_ITB_FFT_SEL_B (0x00000020ul) /**< CKSEL_GNSS_BB.SEL_ITB_FFT */
+#define PM_CLOCK_GPS_BB_SEL_B (0x00000100ul) /**< CKSEL_GNSS_BB.SEL_GNSS_BB */
+#define PM_CLOCK_GPS_PPS_SEL_B (0x00000004ul) /**< CKSEL_GNSS_BB.SEL_PPS */
+#define PM_CLOCK_GPS_CPU_DIV_B (0x00000002ul) /**< GNSS_DIV.CPU */
+#define PM_CLOCK_GPS_AHB_DIV_B (0x00000001ul) /**< GNSS_DIV.AHB */
+
+/* PMU */
+
+#define PM_CLOCK_PMU_SEL_B (0x00000004ul) /**< CKSEL_ROOT.PMU_SWCTL_CLK_SEL */
+#define PM_CLOCK_PMU_PWCTL_SEL_B (0x00000002ul) /**< CKSEL_ROOT.SWCTL_CLK_SEL_RO_RTC */
+#define PM_CLOCK_PMU_PWCTL_DIV_B (0x00000001ul) /**< CKDIV_PMU.PMUA */
+
+#define PM_CLOCK_DOMAIN_MASK ( PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B |\
+ PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_SYS_CPU_DIV_B |\
+ PM_CLOCK_SYS_AHB_DIV_B)
+
+/* Clock Tree Data */
+
+/* Target_id bit field */
+
+/* |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| */
+
+/* | Domain | Domain another bit field | */
+
+/****************************************************************************
+ * Base Define
+ *****************************************************************************/
+
+/* SYSIOP */
+
+#define PM_CLOCK_SYS_CTRL_SEL (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B)
+#define PM_CLOCK_SYSPLL_DIV (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B)
+#define PM_CLOCK_SYS_CPU_SEL (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B)
+#define PM_CLOCK_SYS_CPU_DIV (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_SYS_CPU_DIV_B)
+#define PM_CLOCK_SYS_AHB_DIV (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_SYS_CPU_DIV_B | PM_CLOCK_SYS_AHB_DIV_B)
+#define PM_CLOCK_SYS_APB_DIV (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_SYS_CPU_DIV_B | PM_CLOCK_SYS_AHB_DIV_B | PM_CLOCK_SYS_APB_DIV_B)
+#define PM_CLOCK_SYS_COMIF_DIV (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_SYS_COMIF_DIV_B)
+#define PM_CLOCK_SYS_UART1_SEL (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_SYS_COMIF_DIV_B | PM_CLOCK_SYS_UART1_SEL_B)
+#define PM_CLOCK_SYS_SFC_DIV (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_SYS_SFC_DIV_B)
+#define PM_CLOCK_PMU_RTC_PCLK_SEL (PM_DOMAIN_SYSIOP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_SYS_CPU_DIV_B| PM_CLOCK_SYS_AHB_DIV_B | PM_CLOCK_SYS_APB_DIV_B | PM_CLOCK_PMU_RTC_PCLK_SEL_B)
+
+/* HOSTIF */
+
+#define PM_CLOCK_HIF_SEL (PM_DOMAIN_HOSTIF | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_HIF_SEL_B)
+#define PM_CLOCK_HIF_DIV (PM_DOMAIN_HOSTIF | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_HIF_SEL_B | PM_CLOCK_HIF_DIV_B)
+#define PM_CLOCK_HIF_SEL2 (PM_DOMAIN_HOSTIF | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_HIF_SEL_B | PM_CLOCK_HIF_DIV_B | PM_CLOCK_SCU_XOSC_DIV_B | PM_CLOCK_HIF_SEL2_B)
+#define PM_CLOCK_HIF_UART0_SEL (PM_DOMAIN_HOSTIF | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_HIF_SEL_B | PM_CLOCK_HIF_DIV_B | PM_CLOCK_SCU_XOSC_DIV_B | PM_CLOCK_HIF_SEL2_B | PM_CLOCK_HIF_UART0_SEL_B)
+#define PM_CLOCK_HIF_I2C_SEL (PM_DOMAIN_HOSTIF | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_HIF_SEL_B | PM_CLOCK_HIF_DIV_B | PM_CLOCK_SCU_XOSC_DIV_B | PM_CLOCK_HIF_SEL2_B | PM_CLOCK_HIF_I2C_SEL_B)
+
+/* SCU */
+
+#define PM_CLOCK_SCU_XOSC_DIV (PM_DOMAIN_SCU | PM_CLOCK_SCU_XOSC_DIV_B)
+#define PM_CLOCK_SCU_SEL (PM_DOMAIN_SCU | PM_CLOCK_SCU_XOSC_DIV_B | PM_CLOCK_SCU_32K_SEL_B | PM_CLOCK_SCU_SEL_B)
+#define PM_CLOCK_SCU_32K_SEL (PM_DOMAIN_SCU | PM_CLOCK_SCU_32K_SEL_B)
+#define PM_CLOCK_SCU_HPADC_SEL (PM_DOMAIN_SCU | PM_CLOCK_SCU_32K_SEL_B | PM_CLOCK_SCU_HPADC_SEL_B)
+#define PM_CLOCK_SCU_LPADC_DIV (PM_DOMAIN_SCU | PM_CLOCK_SCU_32K_SEL_B | PM_CLOCK_SCU_LPADC_DIV_B)
+
+/* APP */
+
+#define PM_CLOCK_APP_SYSPLL_DIV (PM_DOMAIN_APP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_APP_SYSPLL_DIV_B)
+#define PM_CLOCK_APP_SEL (PM_DOMAIN_APP | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_APP_SYSPLL_DIV_B | PM_CLOCK_APP_CPU_SEL_B)
+#define PM_CLOCK_APP_AUD_MCLK_DIV (PM_DOMAIN_APP | PM_CLOCK_APP_AUD_MCLK_DIV_B)
+#define PM_CLOCK_APP_AUD_MCLK_SEL (PM_DOMAIN_APP | PM_CLOCK_APP_AUD_MCLK_DIV_B | PM_CLOCK_APP_AUD_MCLK_SEL_B)
+#define PM_CLOCK_APP_AHB_GEAR (PM_DOMAIN_APP | PM_CLOCK_SYS_CTRL_SEL_B |PM_CLOCK_APP_SYSPLL_DIV_B | PM_CLOCK_APP_CPU_SEL_B | PM_CLOCK_APP_AHB_GEAR_B)
+#define PM_CLOCK_APP_UART_GEAR (PM_DOMAIN_APP | PM_CLOCK_SYS_CTRL_SEL_B |PM_CLOCK_APP_SYSPLL_DIV_B | PM_CLOCK_APP_CPU_SEL_B | PM_CLOCK_APP_UART_GEAR_B)
+#define PM_CLOCK_APP_SPI_GEAR (PM_DOMAIN_APP | PM_CLOCK_SYS_CTRL_SEL_B |PM_CLOCK_APP_SYSPLL_DIV_B | PM_CLOCK_APP_CPU_SEL_B | PM_CLOCK_APP_SPI_GEAR_B)
+#define PM_CLOCK_APP_WSPI_GEAR (PM_DOMAIN_APP | PM_CLOCK_SYS_CTRL_SEL_B |PM_CLOCK_APP_SYSPLL_DIV_B | PM_CLOCK_APP_CPU_SEL_B | PM_CLOCK_APP_WSPI_GEAR_B)
+#define PM_CLOCK_APP_SDIO_GEAR (PM_DOMAIN_APP | PM_CLOCK_SYS_CTRL_SEL_B |PM_CLOCK_APP_SYSPLL_DIV_B | PM_CLOCK_APP_CPU_SEL_B | PM_CLOCK_APP_SDIO_GEAR_B)
+#define PM_CLOCK_APP_USB_GEAR (PM_DOMAIN_APP | PM_CLOCK_SYS_CTRL_SEL_B |PM_CLOCK_APP_SYSPLL_DIV_B | PM_CLOCK_APP_CPU_SEL_B | PM_CLOCK_APP_USB_GEAR_B)
+#define PM_CLOCK_APP_VSYNC_GEAR (PM_DOMAIN_APP | PM_CLOCK_SYS_CTRL_SEL_B |PM_CLOCK_APP_SYSPLL_DIV_B | PM_CLOCK_APP_CPU_SEL_B | PM_CLOCK_APP_VSYNC_GEAR_B)
+#define PM_CLOCK_APP_VSYNC_N_GEAR (PM_DOMAIN_APP | PM_CLOCK_APP_VSYNC_GEAR_N)
+
+/* GPS */
+
+#define PM_CLOCK_GPS_PLL_SEL (PM_DOMAIN_GPS | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_GPS_PLL_SEL_B)
+#define PM_CLOCK_GPS_ACQ_SEL (PM_DOMAIN_GPS | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_GPS_PLL_SEL_B | PM_CLOCK_GPS_BB_MODE_SEL_B | PM_CLOCK_GPS_ACQ_SEL_B)
+#define PM_CLOCK_GPS_ITP_TRK_SEL (PM_DOMAIN_GPS | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_GPS_PLL_SEL_B | PM_CLOCK_GPS_BB_MODE_SEL_B | PM_CLOCK_GPS_ACQ_SEL_B | PM_CLOCK_GPS_ITP_TRK_SEL_B)
+#define PM_CLOCK_GPS_BB_MODE_SEL (PM_DOMAIN_GPS | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_GPS_PLL_SEL_B | PM_CLOCK_GPS_BB_MODE_SEL_B)
+#define PM_CLOCK_GPS_LOGGER_SEL (PM_DOMAIN_GPS | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_GPS_PLL_SEL_B | PM_CLOCK_GPS_LOGGER_SEL_B)
+#define PM_CLOCK_GPS_ITB_FFT_SEL (PM_DOMAIN_GPS | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_GPS_PLL_SEL_B | PM_CLOCK_GPS_BB_MODE_SEL_B | PM_CLOCK_GPS_ITB_FFT_SEL_B)
+#define PM_CLOCK_GPS_BB_SEL (PM_DOMAIN_GPS | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_GPS_PLL_SEL_B | PM_CLOCK_GPS_BB_MODE_SEL_B | PM_CLOCK_GPS_BB_SEL_B)
+#define PM_CLOCK_GPS_PPS_SEL (PM_DOMAIN_GPS | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_GPS_PLL_SEL_B | PM_CLOCK_GPS_BB_MODE_SEL_B | PM_CLOCK_GPS_PPS_SEL_B)
+#define PM_CLOCK_GPS_CPU_DIV (PM_DOMAIN_GPS | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_GPS_CPU_DIV_B)
+#define PM_CLOCK_GPS_AHB_DIV (PM_DOMAIN_GPS | PM_CLOCK_SYS_CTRL_SEL_B | PM_CLOCK_SYSPLL_DIV_B | PM_CLOCK_SYS_CPU_SEL_B | PM_CLOCK_GPS_CPU_DIV_B | PM_CLOCK_GPS_AHB_DIV_B)
+
+/* PMU */
+
+#define PM_CLOCK_PMU_SEL (PM_DOMAIN_PMU | PM_CLOCK_PMU_SEL_B)
+#define PM_CLOCK_PMU_PWCTL_SEL (PM_DOMAIN_PMU | PM_CLOCK_PMU_SEL_B | PM_CLOCK_PMU_PWCTL_SEL_B)
+#define PM_CLOCK_PMU_PWCTL_DIV (PM_DOMAIN_PMU | PM_CLOCK_PMU_SEL_B | PM_CLOCK_PMU_PWCTL_SEL_B | PM_CLOCK_PMU_PWCTL_DIV_B )
+
+/****************************************************************************
+ * cxd56_pm_getclock & cxd56_pm_register_callback Interface Define
+ *****************************************************************************/
+
+#define PM_CLOCK_SYS_CTRL PM_CLOCK_SYS_CTRL_SEL
+#define PM_CLOCK_SYSPLL PM_CLOCK_SYSPLL_DIV
+#define PM_CLOCK_SYS_CPU PM_CLOCK_SYS_CPU_DIV
+#define PM_CLOCK_SYS_AHB PM_CLOCK_SYS_AHB_DIV
+#define PM_CLOCK_SYS_APB PM_CLOCK_SYS_APB_DIV
+#define PM_CLOCK_SYS_COMIF PM_CLOCK_SYS_COMIF_DIV
+#define PM_CLOCK_SYS_UART1 PM_CLOCK_SYS_UART1_SEL
+#define PM_CLOCK_SYS_SFC PM_CLOCK_SYS_SFC_DIV
+#define PM_CLOCK_XOSC (PM_DOMAIN_SYSIOP | 0x00100000ul)
+#define PM_CLOCK_RCOSC (PM_DOMAIN_SYSIOP | 0x00200000ul)
+#define PM_CLOCK_RTC (PM_DOMAIN_SYSIOP | 0x00080000ul)
+#define PM_CLOCK_PMU_I2C PM_CLOCK_PMU_RTC_PCLK_SEL
+
+/* HOSTIF */
+
+#define PM_CLOCK_HIF PM_CLOCK_HIF_SEL2
+#define PM_CLOCK_HIF_UART0 PM_CLOCK_HIF_UART0_SEL
+#define PM_CLOCK_HIF_I2C PM_CLOCK_HIF_I2C_SEL
+
+/* SCU */
+
+#define PM_CLOCK_SCU_XOSC PM_CLOCK_SCU_XOSC_DIV
+#define PM_CLOCK_SCU PM_CLOCK_SCU_SEL
+#define PM_CLOCK_SCU_32K PM_CLOCK_SCU_32K_SEL
+#define PM_CLOCK_SCU_HPADC PM_CLOCK_SCU_HPADC_SEL
+#define PM_CLOCK_SCU_LPADC PM_CLOCK_SCU_LPADC_DIV
+
+/* APP */
+
+#define PM_CLOCK_APP_SYSPLL PM_CLOCK_APP_SYSPLL_DIV
+#define PM_CLOCK_APP PM_CLOCK_APP_SEL
+#define PM_CLOCK_APP_AUD PM_CLOCK_APP_AUD_MCLK_SEL
+#define PM_CLOCK_APP_AHB PM_CLOCK_APP_AHB_GEAR
+#define PM_CLOCK_APP_CPU PM_CLOCK_APP_AHB
+#define PM_CLOCK_APP_UART PM_CLOCK_APP_UART_GEAR
+#define PM_CLOCK_APP_SPI PM_CLOCK_APP_SPI_GEAR
+#define PM_CLOCK_APP_WSPI PM_CLOCK_APP_WSPI_GEAR
+#define PM_CLOCK_APP_SDIO PM_CLOCK_APP_SDIO_GEAR
+#define PM_CLOCK_APP_USB PM_CLOCK_APP_USB_GEAR
+#define PM_CLOCK_APP_VSYNC PM_CLOCK_APP_VSYNC_GEAR
+#define PM_CLOCK_APP_VSYNC_N PM_CLOCK_APP_VSYNC_N_GEAR
+#define PM_CLOCK_APP_VSYNC_M PM_CLOCK_APP_VSYNC_GEAR
+
+/* GPS */
+
+#define PM_CLOCK_GPS_PLL PM_CLOCK_GPS_PLL_SEL
+#define PM_CLOCK_GPS_ACQ PM_CLOCK_GPS_ACQ_SEL
+#define PM_CLOCK_GPS_ITP_TRK PM_CLOCK_GPS_ITP_TRK_SEL
+#define PM_CLOCK_GPS_BB_MODE PM_CLOCK_GPS_BB_MODE_SEL
+#define PM_CLOCK_GPS_LOGGER PM_CLOCK_GPS_LOGGER_SEL
+#define PM_CLOCK_GPS_ITB_FFT PM_CLOCK_GPS_ITB_FFT_SEL
+#define PM_CLOCK_GPS_BB PM_CLOCK_GPS_BB_SEL
+#define PM_CLOCK_GPS_PPS PM_CLOCK_GPS_PPS_SEL
+#define PM_CLOCK_GPS_CPU PM_CLOCK_GPS_CPU_DIV
+#define PM_CLOCK_GPS_AHB PM_CLOCK_GPS_AHB_DIV
+
+/* PMU */
+
+#define PM_CLOCK_PMU PM_CLOCK_PMU_PWCTL_SEL
+#define PM_CLOCK_PMUA PM_CLOCK_PMU_PWCTL_DIV
+
+#define PM_CLOCK_SYS_DMAC PM_CLOCK_SYS_AHB
+#define PM_CLOCK_SYS_SAKE PM_CLOCK_SYS_AHB
+#define PM_CLOCK_SYS_KAKI PM_CLOCK_SYS_AHB
+#define PM_CLOCK_SYS_SPIM PM_CLOCK_SYS_COMIF
+#define PM_CLOCK_SYS_I2CM PM_CLOCK_SYS_COMIF
+#define PM_CLOCK_APP_DMAC PM_CLOCK_APP_AHB_GEAR
+#define PM_CLOCK_APP_SAKE PM_CLOCK_APP_AHB_GEAR
+#define PM_CLOCK_APP_KAKI PM_CLOCK_APP_AHB_GEAR
+
+#define PM_CLOCK_CPUID(id) ((0 == (id)) ? PM_CLOCK_SYS_CPU : \
+ (1 == (id)) ? PM_CLOCK_GPS_CPU : \
+ PM_CLOCK_APP_CPU)
+
+/* CPU status change callback */
+
+#define PM_CPU_STATUS_CHANGE (PM_DOMAIN_SELF_CPU | 0x10000000ul)
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+typedef int (*cxd56_pm_callback)(uint8_t id);
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void *cxd56_pm_register_callback(uint32_t target, cxd56_pm_callback callback);
+void cxd56_pm_unregister_callback(void *handle);
+int cxd56_pm_fifo_handlear(int cpuid, uint32_t data[2]);
+int cxd56_pm_main_task(int argc, FAR char *argv[]);
+int cxd56_pm_initialize(void);
+int cxd56_pm_bootup(void);
+uint32_t cxd56_pm_getclock(uint32_t target);
+int cxd56_pm_hotsleep(int idletime);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ASSEMBLY */
+#endif /* __ARCH_ARM_SRC_CXD56XX_POWERMGR_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c b/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c
new file mode 100644
index 00000000000..3b219c1c718
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c
@@ -0,0 +1,794 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "cxd56_clock.h"
+#include "cxd56_powermgr.h"
+#include "up_arch.h"
+#include "hardware/cxd56_crg.h"
+#include "hardware/cxd5602_topreg.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_CXD56_PM_DEBUG
+# define pmerr(format, ...) _err(format, ##__VA_ARGS__)
+# define pmwarn(format, ...) _warn(format, ##__VA_ARGS__)
+# define pminfo(format, ...) _info(format, ##__VA_ARGS__)
+#else
+# define pmerr(x...)
+# define pmwarn(x...)
+# define pminfo(x...)
+#endif
+
+#define PWD_STAT(val, shift) ((val >> shift) & 0x1)
+#define DSP_NUM (6)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cxd56_powermgr_procfs_file_s
+{
+ struct procfs_file_s base; /* Base open file structure */
+ int fileno;
+ int readcnt;
+};
+
+struct cxd56_powermgr_procfs_dir_s
+{
+ struct procfs_dir_priv_s base; /* Base directory private data */
+ int index;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_open(FAR struct file *filep,
+ FAR const char *relpath, int oflags, mode_t mode);
+static int cxd56_powermgr_procfs_close(FAR struct file *filep);
+static ssize_t cxd56_powermgr_procfs_read(FAR struct file *filep,
+ FAR char *buffer, size_t buflen);
+static int cxd56_powermgr_procfs_dup(FAR const struct file *oldp,
+ FAR struct file *newp);
+static int cxd56_powermgr_procfs_opendir(FAR const char *relpath,
+ FAR struct fs_dirent_s *dir);
+static int cxd56_powermgr_procfs_closedir(FAR struct fs_dirent_s *dir);
+static int cxd56_powermgr_procfs_readdir(struct fs_dirent_s *dir);
+static int cxd56_powermgr_procfs_rewinddir(struct fs_dirent_s *dir);
+static int cxd56_powermgr_procfs_stat(FAR const char *relpath,
+ FAR struct stat *buf);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+const struct procfs_operations cxd56_powermgr_procfs_operations =
+{
+ cxd56_powermgr_procfs_open, /* open */
+ cxd56_powermgr_procfs_close, /* close */
+ cxd56_powermgr_procfs_read, /* read */
+ NULL, /* write */
+ cxd56_powermgr_procfs_dup, /* dup */
+ cxd56_powermgr_procfs_opendir, /* opendir */
+ cxd56_powermgr_procfs_closedir, /* closedir */
+ cxd56_powermgr_procfs_readdir, /* readdir */
+ cxd56_powermgr_procfs_rewinddir, /* rewinddir */
+ cxd56_powermgr_procfs_stat /* stat */
+};
+
+static const struct procfs_entry_s g_powermgr_procfs1 =
+ {"pm**", &cxd56_powermgr_procfs_operations};
+static const struct procfs_entry_s g_powermgr_procfs2 =
+ {"pm/" , &cxd56_powermgr_procfs_operations};
+static FAR char *g_powermg_procfs_buffer;
+static size_t g_powermg_procfs_size;
+static size_t g_powermg_procfs_len;
+
+static const char* g_powermg_procfs_clock_source_name[]
+ = {"RCOSC", "SYSPLL", "XOSC", "RTC"};
+static const char* g_powermg_procfs_power_state[]
+ = {"-", "o"};
+static const char* g_powermg_procfs_dir[]
+ = {"clock", "power"};
+/****************************************************************************
+ * Private Function
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_step_buffer
+ *
+ * Description:
+ * step buffer position
+ *
+ ****************************************************************************/
+
+static void cxd56_powermgr_procfs_step_buffer(size_t len)
+{
+ DEBUGASSERT(g_powermg_procfs_size > (g_powermg_procfs_len + len));
+ g_powermg_procfs_len = g_powermg_procfs_len + len;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_clock_base
+ *
+ * Description:
+ * collect clock base value
+ *
+ ****************************************************************************/
+
+static void cxd56_powermgr_procfs_clock_base(void)
+{
+ uint32_t sys_clk_sel;
+ uint32_t app_clk_sel;
+ size_t len;
+
+ /* Collect clock base value */
+
+ sys_clk_sel = getreg32(CXD56_TOPREG_CKSEL_ROOT) >> 22 & 0x3;
+ app_clk_sel = getreg32(CXD56_TOPREG_APP_CKSEL) >> 8 & 0x3;
+
+ /* Store data in buffer */
+
+ len = snprintf(g_powermg_procfs_buffer + g_powermg_procfs_len,
+ g_powermg_procfs_size - g_powermg_procfs_len,
+ "Clock Source\n"
+ " SYS:%s\n"
+ " APP:%s\n\n",
+ g_powermg_procfs_clock_source_name[sys_clk_sel],
+ g_powermg_procfs_clock_source_name[app_clk_sel]);
+
+ /* Step buffer position */
+
+ cxd56_powermgr_procfs_step_buffer(len);
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_clock
+ *
+ * Description:
+ * collect clock value
+ *
+ ****************************************************************************/
+
+static void cxd56_powermgr_procfs_clock(void)
+{
+ size_t len;
+ uint32_t scu;
+ uint32_t hpadc;
+ uint32_t lpadc;
+ uint32_t gps;
+ uint32_t gpsahb;
+ uint32_t val;
+ uint32_t emmc;
+ int dsp;
+ uint32_t dsptabl[DSP_NUM];
+
+ /* collect clock value
+ * and store data in buffer
+ */
+
+ /* Check SCU clock status */
+
+ scu = cxd56_get_scu_baseclock();
+ hpadc = cxd56_get_hpadc_baseclock();
+ lpadc = cxd56_get_lpadc_baseclock();
+ val = getreg32(CXD56_TOPREG_SYSIOP_CKEN);
+ if ((val & CKEN_BRG_SCU) != CKEN_BRG_SCU)
+ {
+ scu = 0;
+ hpadc = 0;
+ lpadc = 0;
+ }
+
+ /* Check GPS clock status */
+
+ gps = cxd56_get_gps_cpu_baseclock();
+ gpsahb = cxd56_get_gps_ahb_baseclock();
+ val = getreg32(CXD56_TOPREG_GNSDSP_CKEN);
+ if (((val & GNSDSP_CKEN_P1) != GNSDSP_CKEN_P1)
+ && ((val & GNSDSP_CKEN_COP) != GNSDSP_CKEN_COP))
+ {
+ gps = 0;
+ gpsahb = 0;
+ }
+
+ /* Check DSP clock status */
+
+ val = getreg32(CXD56_CRG_CK_GATE_AHB);
+ val = (val >> 16) & 0x3f;
+ for (dsp = 0; dsp < DSP_NUM; dsp++)
+ {
+ if ((val & (1 << dsp)) == (1 << dsp))
+ {
+ dsptabl[dsp] = cxd56_get_cpu_baseclk();
+ }
+ else
+ {
+ dsptabl[dsp] = 0;
+ }
+ }
+
+ val = getreg32(CXD56_CRG_CKEN_EMMC);
+ val = val & 0x7;
+ if (val == 0x7)
+ {
+ emmc = cxd56_get_cpu_baseclk();
+ }
+ else
+ {
+ emmc = 0;
+ }
+
+ len = snprintf(g_powermg_procfs_buffer + g_powermg_procfs_len,
+ g_powermg_procfs_size - g_powermg_procfs_len,
+ "Clock Status [Hz]\n"
+ " |-RTC : %9d"" |-APP : %9d\n"
+ " |-RCOSC : %9d"" ||-DSP0 : %9d\n"
+ " |-XOSC : %9d"" ||-DSP1 : %9d\n"
+ " |-SYSPLL : %9d"" ||-DSP2 : %9d\n"
+ " |-M0P : %9d"" ||-DSP3 : %9d\n"
+ " ||-AHB : %9d"" ||-DSP4 : %9d\n"
+ " | |-APB : %9d"" ||-DSP5 : %9d\n"
+ " |-UART1 : %9d"" ||-UART2 : %9d\n"
+ " |-SFC : %9d"" ||-SPI4 : %9d\n"
+ " |-SCU : %9d"" ||-SPI5 : %9d\n"
+ " ||-LPADC : %9d"" ||-USB : %9d\n"
+ " ||-HPADC : %9d"" ||-EMMC : %9d\n"
+ " |-I2C4 : %9d"" ||-SDIO : %9d\n"
+ " |-GPS : %9d"" ||-VSYNC : %9d\n"
+ " ||-AHB : %9d\n",
+ cxd56_get_rtc_clock(), cxd56_get_appsmp_baseclock(),
+ cxd56_get_rcosc_clock(), dsptabl[0],
+ cxd56_get_xosc_clock(), dsptabl[1],
+ cxd56_get_syspll_clock(), dsptabl[2],
+ cxd56_get_sys_baseclock(), dsptabl[3],
+ cxd56_get_sys_ahb_baseclock(), dsptabl[4],
+ cxd56_get_sys_apb_baseclock(), dsptabl[5],
+ cxd56_get_com_baseclock(), cxd56_get_img_uart_baseclock(),
+ cxd56_get_sys_sfc_baseclock(), cxd56_get_img_spi_baseclock(),
+ scu, cxd56_get_img_wspi_baseclock(),
+ lpadc, cxd56_get_usb_baseclock(),
+ hpadc, emmc,
+ cxd56_get_pmui2c_baseclock(), cxd56_get_sdio_baseclock(),
+ gps, cxd56_get_img_vsync_baseclock(),
+ gpsahb);
+
+ /* Step buffer position */
+
+ cxd56_powermgr_procfs_step_buffer(len);
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_power_state
+ *
+ * Description:
+ * collect clock power state
+ *
+ ****************************************************************************/
+
+static void cxd56_powermgr_procfs_power_state(void)
+{
+ uint32_t reg_pwd_stat;
+ uint32_t reg_ana_pw_stat;
+ uint32_t rf;
+ size_t len;
+
+ /* Collect power status */
+
+ reg_pwd_stat = getreg32(CXD56_TOPREG_PWD_STAT);
+ reg_ana_pw_stat = getreg32(CXD56_TOPREG_ANA_PW_STAT);
+
+ /* Check RF_xxx power status */
+
+ rf = reg_ana_pw_stat & 0x3f0;
+ if (rf != 0)
+ {
+ rf = 1;
+ }
+
+ /* Store data in buffer */
+
+ len = snprintf(g_powermg_procfs_buffer + g_powermg_procfs_len,
+ g_powermg_procfs_size - g_powermg_procfs_len,
+ "Power Status\n"
+ "|-RCOSC : %s\n"
+ "|-XOSC : %s\n"
+ "|-SYSPLL : %s\n"
+ "|-SCU : %s\n"
+ "||-LPADC : %s\n"
+ "||-HPADC : %s\n"
+ "|-CORE : %s\n"
+ "||-GNSS_ITP : %s\n"
+ "||-SYSIOP : %s\n"
+ "| |-SYSIOP_SUB : %s\n"
+ "| |-GNSS : %s\n"
+ "| ||-RF : %s\n"
+ "| |-APP : %s\n"
+ "| ||-APP_DSP : %s\n"
+ "| ||-APP_SUB : %s\n"
+ "| ||-APP_AUD : %s\n",
+ g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 0)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 1)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 2)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 0)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 13)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 12)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 4)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 12)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 5)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 6)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 13)],
+ g_powermg_procfs_power_state[rf],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 8)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 9)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 10)],
+ g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 14)]);
+
+ /* step buffer position */
+
+ cxd56_powermgr_procfs_step_buffer(len);
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_check_path
+ *
+ * Description:
+ * Check path power manager procfs
+ *
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_check_dir(char *relpath,
+ mode_t *mode, int *level, int *fileno)
+{
+ char *temp;
+ int ret = OK;
+
+ *level = 0;
+ *mode = S_IFDIR;
+ *fileno = 0;
+ temp = strtok(relpath, "/");
+ if (strncmp (temp, "pm", 3) == 0)
+ {
+ while ((temp = strtok (NULL, "/")) != NULL)
+ {
+ *level = *level + 1;
+ if (*level == 1)
+ {
+ if (strncmp(temp, g_powermg_procfs_dir[0],
+ strlen(g_powermg_procfs_dir[0])+1) == 0)
+ {
+ *mode = S_IFREG;
+ *fileno = 1;
+ }
+ else if (strncmp(temp, g_powermg_procfs_dir[1],
+ strlen(g_powermg_procfs_dir[1])+1) == 0)
+ {
+ *mode = S_IFREG;
+ *fileno = 2;
+ }
+ else
+ {
+ ret = -ENOENT;
+ break;
+ }
+ }
+ else
+ {
+ ret = -ENOENT;
+ break;
+ }
+ }
+ }
+ else
+ {
+ ret = -ENOENT;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_open
+ *
+ * Description:
+ * Request Open power manager procfs
+ *
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_open(FAR struct file *filep,
+ FAR const char *relpath, int oflags, mode_t mode)
+{
+ FAR struct cxd56_powermgr_procfs_file_s *priv;
+ int ret;
+ mode_t getmode;
+ int level;
+ int fileno;
+ char temp[16];
+
+ pminfo("Open '%s'\n", relpath);
+
+ /* PROCFS is read-only. Any attempt to open with any kind of write
+ * access is not permitted.
+ *
+ * REVISIT: Write-able proc files could be quite useful.
+ */
+
+ if (((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0))
+ {
+ pmerr("ERROR: Only O_RDONLY supported\n");
+ return -EACCES;
+ }
+
+ memset(temp, 0, sizeof(temp));
+ snprintf(temp, sizeof(temp)-1, "%s", relpath);
+ ret = cxd56_powermgr_procfs_check_dir(temp, &getmode, &level, &fileno);
+
+ if (ret != OK)
+ {
+ return ret;
+ }
+
+ /* Allocate the open file structure */
+
+ priv = (FAR struct cxd56_powermgr_procfs_file_s *)
+ kmm_zalloc(sizeof(struct cxd56_powermgr_procfs_file_s));
+ if (!priv)
+ {
+ pmerr("ERROR: Failed to allocate file attributes\n");
+ return -ENOMEM;
+ }
+
+ priv->fileno = fileno;
+ priv->readcnt = 0;
+ filep->f_priv = (void *)priv;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_close
+ *
+ * Description:
+ * Request Close power manager procfs
+ *
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_close(FAR struct file *filep)
+{
+ pminfo("Close\n");
+
+ DEBUGASSERT(filep->f_priv);
+ kmm_free(filep->f_priv);
+ filep->f_priv = NULL;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_read
+ *
+ * Description:
+ * Request Read power manager procfs
+ *
+ ****************************************************************************/
+
+static ssize_t cxd56_powermgr_procfs_read(FAR struct file *filep,
+ FAR char *buffer, size_t buflen)
+{
+ size_t len;
+ FAR struct cxd56_powermgr_procfs_file_s *priv;
+
+ pminfo("READ buffer=%p buflen=%lu len=%lu\n", buffer,
+ (unsigned long)buflen, g_powermg_procfs_len);
+
+ DEBUGASSERT(filep && filep->f_priv);
+
+ priv = (FAR struct cxd56_powermgr_procfs_file_s *)filep->f_priv;
+
+ if (priv->fileno == 0)
+ {
+ /* pm directory */
+
+ return 0;
+ }
+
+ if (priv->readcnt == 0)
+ {
+ /* Collect data and store data in buffer */
+
+ g_powermg_procfs_buffer = buffer;
+ g_powermg_procfs_size = buflen;
+ g_powermg_procfs_len = 0;
+
+ if (priv->fileno == 1)
+ {
+ cxd56_powermgr_procfs_clock_base();
+ cxd56_powermgr_procfs_clock();
+ }
+ else
+ {
+ cxd56_powermgr_procfs_power_state();
+ }
+
+ len = g_powermg_procfs_len;
+ priv->readcnt++;
+ }
+ else
+ {
+ /* Indicate already provided all data */
+
+ len = 0;
+ priv->readcnt = 0;
+ }
+
+ return len;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_dup
+ *
+ * Description:
+ * Request Dup power manager procfs
+ *
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_dup(FAR const struct file *oldp,
+ FAR struct file *newp)
+{
+ void *oldpriv;
+ void *newpriv;
+
+ pminfo("Dup %p->%p\n", oldp, newp);
+
+ /* Recover our private data from the old struct file instance */
+
+ oldpriv = oldp->f_priv;
+ DEBUGASSERT(oldpriv);
+
+ /* Allocate a new container to hold the task and attribute selection */
+
+ newpriv = kmm_malloc(sizeof(struct cxd56_powermgr_procfs_file_s));
+ if (!newpriv)
+ {
+ pmerr("ERROR: Failed to allocate file attributes\n");
+ return -ENOMEM;
+ }
+
+ /* The copy the file attributes from the old attributes to the new */
+
+ memcpy(newpriv, oldpriv, sizeof(struct cxd56_powermgr_procfs_file_s));
+
+ /* Save the new attributes in the new file structure */
+
+ newp->f_priv = newpriv;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_stat
+ *
+ * Description:
+ * Request Stat power manager procfs
+ *
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_stat(FAR const char *relpath,
+ FAR struct stat *buf)
+{
+ int ret;
+ mode_t mode;
+ int level;
+ int fileno;
+ char temp[16];
+
+ memset(temp, 0, sizeof(temp));
+ snprintf(temp, sizeof(temp)-1, "%s", relpath);
+ ret = cxd56_powermgr_procfs_check_dir(temp, &mode, &level, &fileno);
+
+ pminfo("Stat %s %d %d %d\n", relpath, mode, level, ret);
+
+ buf->st_mode = mode | S_IROTH | S_IRGRP | S_IRUSR;
+ buf->st_size = 0;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_opendir
+ *
+ * Description:
+ * Request Opendir power manager procfs
+ *
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_opendir(FAR const char *relpath,
+ FAR struct fs_dirent_s *dir)
+{
+ FAR struct cxd56_powermgr_procfs_dir_s *procfs;
+ int ret;
+ mode_t mode;
+ int level;
+ int fileno;
+ char temp[16];
+
+ memset(temp, 0, sizeof(temp));
+ snprintf(temp, sizeof(temp)-1, "%s", relpath);
+ ret = cxd56_powermgr_procfs_check_dir(temp, &mode, &level, &fileno);
+
+ pminfo("Opendir '%s' %d %d\n", relpath, ret, level);
+
+ if (ret != OK)
+ {
+ return ret;
+ }
+ if (level > 0)
+ {
+ return -ENOENT;
+ }
+
+ procfs = (FAR struct cxd56_powermgr_procfs_dir_s *)
+ kmm_malloc(sizeof(struct cxd56_powermgr_procfs_dir_s));
+ if (!procfs)
+ {
+ pmerr("ERROR: Failed to allocate dir attributes\n");
+ return -ENOMEM;
+ }
+
+ procfs->index = 0;
+ dir->u.procfs = (FAR void *)procfs;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_closedir
+ *
+ * Description:
+ * Request Closedir power manager procfs
+ *
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_closedir(FAR struct fs_dirent_s *dir)
+{
+ FAR struct smartfs_level1_s *priv;
+
+ pminfo("Closedir\n");
+
+ DEBUGASSERT(dir && dir->u.procfs);
+ priv = dir->u.procfs;
+
+ if (priv)
+ {
+ kmm_free(priv);
+ }
+
+ dir->u.procfs = NULL;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_readdir
+ *
+ * Description:
+ * Request Readdir power manager procfs
+ *
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_readdir(struct fs_dirent_s *dir)
+{
+ FAR struct cxd56_powermgr_procfs_dir_s *procfs;
+
+ DEBUGASSERT(dir && dir->u.procfs);
+
+ procfs = (FAR struct cxd56_powermgr_procfs_dir_s *)dir->u.procfs;
+
+ pminfo("Readdir %d\n", procfs->index);
+
+ if (procfs->index > ((sizeof(g_powermg_procfs_dir)
+ / sizeof(g_powermg_procfs_dir[0])) - 1))
+ {
+ return -ENOENT;
+ }
+
+ dir->fd_dir.d_type = DTYPE_FILE;
+ strncpy(dir->fd_dir.d_name, g_powermg_procfs_dir[procfs->index],
+ strlen(g_powermg_procfs_dir[procfs->index])+1);
+ procfs->index++;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: cxd56_powermgr_procfs_rewinddir
+ *
+ * Description:
+ * Request Rewind power manager procfs
+ *
+ ****************************************************************************/
+
+static int cxd56_powermgr_procfs_rewinddir(struct fs_dirent_s *dir)
+{
+ FAR struct cxd56_powermgr_procfs_dir_s *procfs;
+
+ DEBUGASSERT(dir && dir->u.procfs);
+
+ procfs = (FAR struct cxd56_powermgr_procfs_dir_s *)dir->u.procfs;
+ pminfo("Rewind %d\n", procfs->index);
+ procfs->index = 0;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Function
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_pm_initialize_procfs
+ *
+ * Description:
+ * Initialize power manager procfs
+ *
+ ****************************************************************************/
+
+int cxd56_pm_initialize_procfs(void)
+{
+ int ret;
+ ret = procfs_register(&g_powermgr_procfs1);
+ if (ret < 0)
+ return -EPERM;
+ ret = procfs_register(&g_powermgr_procfs2);
+ if (ret < 0)
+ return -EPERM;
+ return ret;
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.h b/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.h
new file mode 100644
index 00000000000..ee58ffa266d
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_powermgr_procfs.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_POWERMGR_PROCFS_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_POWERMGR_PROCFS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+/****************************************************************************
+ * Public Function
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_pm_initialize_procfs
+ *
+ * Description:
+ * Initialize power manager procfs
+ *
+ ****************************************************************************/
+
+int cxd56_pm_initialize_procfs(void);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_POWERMGR_PROCFS_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_pwm.c b/arch/arm/src/cxd56xx/cxd56_pwm.c
new file mode 100644
index 00000000000..db3fcd9918e
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_pwm.c
@@ -0,0 +1,495 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_pwm.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "chip.h"
+#include "up_arch.h"
+
+#include "cxd56_pinconfig.h"
+#include "cxd56_clock.h"
+#include "cxd56_pwm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define PWM_REG_BASE (0x04195600)
+#define PWM_PHASE_REG_BASE (0x04195630)
+
+#define PWM_REG(ch) \
+ ( \
+ (PWM_REG_t*)(PWM_REG_BASE + (sizeof(PWM_REG_t) * (ch))) \
+ )
+
+#define PWM_PHASE_REG(ch) \
+ ( \
+ (PWM_PHASE_REG_t*) \
+ (PWM_PHASE_REG_BASE + (sizeof(PWM_PHASE_REG_t) * (ch))) \
+ )
+
+#define PWM_PARAM_OFFPERIOD_SHIFT (16)
+
+#ifndef itemsof
+# define itemsof(array) (sizeof(array)/sizeof(array[0]))
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure represents the state of one PWM channel */
+
+struct cxd56_pwm_chan_s
+{
+ const struct pwm_ops_s *ops; /* PWM operations */
+ uint8_t ch; /* PWM channel: {0..3} */
+ uint8_t prescale; /* prescale (reserved) */
+};
+
+typedef struct
+{
+ volatile uint32_t PARAM;
+ volatile uint32_t EN;
+ volatile uint32_t UPDATE;
+} PWM_REG_t;
+
+typedef struct
+{
+ volatile uint32_t PHASE;
+} PWM_PHASE_REG_t;
+
+/****************************************************************************
+ * Static Function Prototypes
+ ****************************************************************************/
+
+/* PWM driver methods */
+
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+ FAR const struct pwm_info_s *info);
+static int pwm_stop(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev,
+ int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This is the list of lower half PWM driver methods used by the upper half
+ * driver
+ */
+
+static const struct pwm_ops_s g_pwmops =
+{
+ .setup = pwm_setup,
+ .shutdown = pwm_shutdown,
+ .start = pwm_start,
+ .stop = pwm_stop,
+ .ioctl = pwm_ioctl,
+};
+
+#ifdef CONFIG_CXD56_PWM0
+static struct cxd56_pwm_chan_s g_pwm_ch0 =
+{
+ .ops = &g_pwmops,
+ .ch = CXD56_PWM_CH0,
+ .prescale = 0,
+};
+#endif
+
+#ifdef CONFIG_CXD56_PWM1
+static struct cxd56_pwm_chan_s g_pwm_ch1 =
+{
+ .ops = &g_pwmops,
+ .ch = CXD56_PWM_CH1,
+ .prescale = 0,
+};
+#endif
+
+#ifdef CONFIG_CXD56_PWM2
+static struct cxd56_pwm_chan_s g_pwm_ch2 =
+{
+ .ops = &g_pwmops,
+ .ch = CXD56_PWM_CH2,
+ .prescale = 0,
+};
+#endif
+
+#ifdef CONFIG_CXD56_PWM3
+static struct cxd56_pwm_chan_s g_pwm_ch3 =
+{
+ .ops = &g_pwmops,
+ .ch = CXD56_PWM_CH3,
+ .prescale = 0,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwm_pin_config
+ *
+ * Description:
+ * Configure PWM pin
+ *
+ * Input Parameters:
+ * channel - pwm channel number.
+ *
+ * Returned Value:
+ * OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int pwm_pin_config(uint32_t channel)
+{
+ int ret = 0;
+ uint32_t pingroupa[] = PINCONFS_PWMA;
+ uint32_t pingroupb[] = PINCONFS_PWMB;
+
+ if ((channel == CXD56_PWM_CH0) || (channel == CXD56_PWM_CH1))
+ {
+ ret = cxd56_pin_configs(pingroupa, itemsof(pingroupa));
+ }
+ else
+ {
+ ret = cxd56_pin_configs(pingroupb, itemsof(pingroupb));
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: convert_freq2period
+ *
+ * Description:
+ * Convert frequency and duty to period and offperiod of param register.
+ *
+ * Input Parameters:
+ * freq - pwm frequency [Hz]
+ * duty - duty
+ *
+ * Output Parameters:
+ * param - set value of PWM_PARAM register
+ *
+ * Returned Value:
+ * OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int convert_freq2period(uint32_t freq, ub16_t duty, uint32_t *param)
+{
+ DEBUGASSERT(param);
+
+ uint32_t pwmfreq = 0;
+ uint32_t period = 0;
+ uint32_t offperiod = 0;
+
+ /* Get frequency of pwm base clock */
+
+ pwmfreq = cxd56_get_pwm_baseclock();
+ if (pwmfreq == 0)
+ {
+ pwmerr("Unknown pwm frequency\n");
+ return -1;
+ }
+
+ /* check frequency range */
+
+ if ((freq > ((pwmfreq + 1) >> 1)) || (freq < (pwmfreq >> 16)))
+ {
+ pwmerr("Frequency out of range. %d [Effective range:%d - %d]\n",
+ freq, pwmfreq >> 16, (pwmfreq + 1) >> 1);
+ return -1;
+ }
+
+ /* check duty range */
+
+ if ((duty < 0x00000001) || (duty > 0x0000ffff))
+ {
+ pwmerr("Duty out of range. %d\n", duty);
+ return -1;
+ }
+
+ /* calcurate period and offperiod */
+
+ period = (pwmfreq * 10 / freq - 5) / 10;
+ if (period > 0xffff)
+ {
+ period = 0xffff;
+ }
+ offperiod = ((0x10000 - duty) * (period + 1) + 0x8000) >> 16;
+ if (offperiod == 0)
+ {
+ offperiod = 0;
+ }
+ else if (period < offperiod)
+ {
+ offperiod = period;
+ }
+ *param = (period & 0xffff) |
+ ((offperiod & 0xffff) << PWM_PARAM_OFFPERIOD_SHIFT);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_setup
+ *
+ * Description:
+ * This method is called when the driver is opened. The lower half driver
+ * should configure and initialize the device so that it is ready for use.
+ * It should not, however, output pulses until the start method is called.
+ *
+ * Input parameters:
+ * dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ * OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev)
+{
+ FAR struct cxd56_pwm_chan_s *priv = (FAR struct cxd56_pwm_chan_s *)dev;
+ int ret;
+
+ ret = pwm_pin_config(priv->ch);
+ if (ret < 0)
+ {
+ pwmerr("Failed to pinconf():%d\n", channel);
+ return -EINVAL;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_shutdown
+ *
+ * Description:
+ * This method is called when the driver is closed. The lower half driver
+ * stop pulsed output, free any resources, disable the timer hardware, and
+ * put the system into the lowest possible power usage state
+ *
+ * Input parameters:
+ * dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ * OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
+{
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_start
+ *
+ * Description:
+ * (Re-)initialize the timer resources and start the pulsed output
+ *
+ * Input parameters:
+ * dev - A reference to the lower half PWM driver state structure
+ * info - A reference to the characteristics of the pulsed output
+ *
+ * Returned Value:
+ * OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+ FAR const struct pwm_info_s *info)
+{
+ FAR struct cxd56_pwm_chan_s *priv = (FAR struct cxd56_pwm_chan_s *)dev;
+ uint32_t param;
+ int ret;
+
+ if (info->duty <= 0)
+ {
+ /* Output low level if duty cycle is almost 0% */
+
+ PWM_REG(priv->ch)->EN = 0x0;
+ }
+ else if (info->duty >= 65536)
+ {
+ /* Output high level if duty cycle is almost 100% */
+
+ PWM_REG(priv->ch)->PARAM = 1;
+ PWM_REG(priv->ch)->EN = 0x1;
+ }
+ else
+ {
+ ret = convert_freq2period(info->frequency, info->duty, ¶m);
+ if (ret < 0)
+ {
+ return -EINVAL;
+ }
+
+ if (PWM_REG(priv->ch)->EN & 1)
+ {
+ /* Change duty cycle dynamically if already running */
+
+ PWM_REG(priv->ch)->PARAM = param;
+ return OK;
+ }
+
+ PWM_REG(priv->ch)->EN = 0x0;
+ PWM_REG(priv->ch)->PARAM = param;
+
+ /* Since prescale is not supported, always set to a fixed value '0' */
+
+ PWM_PHASE_REG(priv->ch)->PHASE = 0x0;
+
+ PWM_REG(priv->ch)->EN = 0x1;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_stop
+ *
+ * Description:
+ * Stop the pulsed output and reset the timer resources
+ *
+ * Input parameters:
+ * dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ * OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int pwm_stop(FAR struct pwm_lowerhalf_s *dev)
+{
+ FAR struct cxd56_pwm_chan_s *priv = (FAR struct cxd56_pwm_chan_s *)dev;
+
+ PWM_REG(priv->ch)->EN = 0x0;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_ioctl
+ *
+ * Description:
+ * Lower-half logic may support platform-specific ioctl commands
+ *
+ * Input parameters:
+ * dev - A reference to the lower half PWM driver state structure
+ * cmd - The ioctl command
+ * arg - The argument accompanying the ioctl command
+ *
+ * Returned Value:
+ * OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd,
+ unsigned long arg)
+{
+ return -ENOTTY;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_pwminitialize
+ *
+ * Description:
+ * Initialize PWM channel for use with the upper_level PWM driver.
+ *
+ * Input Parameters:
+ * channel - pwm channel number.
+ *
+ * Returned Value:
+ * On success, a pointer to the CXD56 lower half PWM driver is returned.
+ * NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct pwm_lowerhalf_s *cxd56_pwminitialize(uint32_t channel)
+{
+ FAR struct cxd56_pwm_chan_s *pwmch;
+
+ switch (channel)
+ {
+#ifdef CONFIG_CXD56_PWM0
+ case CXD56_PWM_CH0:
+ pwmch = &g_pwm_ch0;
+ break;
+#endif
+#ifdef CONFIG_CXD56_PWM1
+ case CXD56_PWM_CH1:
+ pwmch = &g_pwm_ch1;
+ break;
+#endif
+#ifdef CONFIG_CXD56_PWM2
+ case CXD56_PWM_CH2:
+ pwmch = &g_pwm_ch2;
+ break;
+#endif
+#ifdef CONFIG_CXD56_PWM3
+ case CXD56_PWM_CH3:
+ pwmch = &g_pwm_ch3;
+ break;
+#endif
+ default:
+ pwmerr("Illeagal channel number:%d\n", channel);
+ return NULL;
+ }
+
+ return (FAR struct pwm_lowerhalf_s *)pwmch;
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_pwm.h b/arch/arm/src/cxd56xx/cxd56_pwm.h
new file mode 100644
index 00000000000..e04ec48e490
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_pwm.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_pwm.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_PWM_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_PWM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* PWM channel definitions **************************************************/
+
+#define CXD56_PWM_CH0 0
+#define CXD56_PWM_CH1 1
+#define CXD56_PWM_CH2 2
+#define CXD56_PWM_CH3 3
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_pwminitialize
+ *
+ * Description:
+ * Initialize PWM channel for use with the upper_level PWM driver.
+ *
+ * Input Parameters:
+ * channel - pwm channel number.
+ *
+ * Returned Value:
+ * On success, a pointer to the CXD56 lower half PWM driver is returned.
+ * NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct pwm_lowerhalf_s *cxd56_pwminitialize(uint32_t channel);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_PWM_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_rtc.c b/arch/arm/src/cxd56xx/cxd56_rtc.c
new file mode 100644
index 00000000000..1f042154309
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_rtc.c
@@ -0,0 +1,666 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_rtc.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include "up_arch.h"
+#include "cxd56_rtc.h"
+
+#include "hardware/cxd5602_topreg.h"
+#include "hardware/cxd5602_memorymap.h"
+#include "hardware/cxd5602_backupmem.h"
+#include "hardware/cxd56_rtc.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+
+#ifdef CONFIG_RTC_HIRES
+# ifndef CONFIG_RTC_FREQUENCY
+# define CONFIG_RTC_FREQUENCY 32768
+# endif
+# if CONFIG_RTC_FREQUENCY != 32768
+# error "Only lo-res CONFIG_RTC_FREQUENCY of 32.768kHz is supported"
+# endif
+#else
+# ifndef CONFIG_RTC_FREQUENCY
+# define CONFIG_RTC_FREQUENCY 1
+# endif
+# if CONFIG_RTC_FREQUENCY != 1
+# error "Only lo-res CONFIG_RTC_FREQUENCY of 1Hz is supported"
+# endif
+#endif
+
+/* convert seconds to 64bit counter value running at 32kHz */
+
+#define SEC_TO_CNT(sec) ((uint64_t)(((uint64_t)(sec)) << 15))
+
+/* convert nano-seconds to 32kHz counter less than 1 second */
+
+#define NSEC_TO_PRECNT(nsec) \
+ (((nsec) / (NSEC_PER_SEC / CONFIG_RTC_FREQUENCY)) & 0x7fff)
+
+#define MAGIC_RTC_SAVE (0x12aae190077a80ull)
+
+/* RTC clcok stable waiting time (interval x retry) */
+
+#define RTC_CLOCK_CHECK_INTERVAL (200) /* milliseconds */
+#define RTC_CLOCK_CHECK_MAX_RETRY (15)
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+struct alm_cbinfo_s
+{
+ volatile alm_callback_t ac_cb; /* Client callback function */
+ volatile FAR void *ac_arg; /* Argument to pass with the callback function */
+};
+#endif
+
+struct rtc_backup_s
+{
+ uint64_t magic;
+ int64_t reserved0;
+ int64_t offset; /* offset time from RTC HW value */
+ int64_t reserved1;
+};
+
+/************************************************************************************
+ * Private Data
+ ************************************************************************************/
+
+/* Callback to use when the alarm expires */
+
+#ifdef CONFIG_RTC_ALARM
+static struct alm_cbinfo_s g_alarmcb[RTC_ALARM_LAST];
+#endif
+
+/* Saved data for persistent RTC time */
+
+static struct rtc_backup_s *g_rtc_save;
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+volatile bool g_rtc_enabled = false;
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: rtc_dumptime
+ *
+ * Description:
+ * Dump RTC
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_DEBUG_RTC
+static void rtc_dumptime(FAR const struct timespec *tp, FAR const char *msg)
+{
+ FAR struct tm tm;
+
+ (void)gmtime_r(&tp->tv_sec, &tm);
+
+ rtcinfo("%s:\n", msg);
+ rtcinfo("RTC %u.%09u\n", tp->tv_sec, tp->tv_nsec);
+ rtcinfo("%4d/%02d/%02d %02d:%02d:%02d\n",
+ tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+#else
+# define rtc_dumptime(tp, msg)
+#endif
+
+/************************************************************************************
+ * Name: cxd56_rtc_interrupt
+ *
+ * Description:
+ * RTC interrupt service routine
+ *
+ * Input Parameters:
+ * irq - The IRQ number that generated the interrupt
+ * context - Architecture specific register save information.
+ *
+ * Returned Value:
+ * Zero (OK) on success; A negated errno value on failure.
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static int cxd56_rtc_interrupt(int irq, FAR void *context, FAR void *arg)
+{
+ FAR struct alm_cbinfo_s *cbinfo;
+ alm_callback_t cb;
+ FAR void *cb_arg;
+ uint32_t source, clear;
+ int id;
+ int ret = OK;
+
+ /* interrupt clear */
+
+ source = getreg32(CXD56_RTC0_ALMFLG);
+
+ if (source & RTCREG_ALM0_MASK)
+ {
+ id = RTC_ALARM0;
+ clear = source & RTCREG_ALM0_MASK;
+ }
+ else if (source & RTCREG_ALM1_MASK)
+ {
+ id = RTC_ALARM1;
+ clear = source & RTCREG_ALM1_MASK;
+ }
+ else if (source & RTCREG_ALM2_MASK)
+ {
+ id = RTC_ALARM2;
+ clear = source & RTCREG_ALM2_MASK;
+ }
+ else
+ {
+ rtcerr("ERROR: Invalid ALARM\n");
+ return ret;
+ }
+ putreg32(clear, CXD56_RTC0_ALMCLR);
+ putreg32(0, CXD56_RTC0_ALMOUTEN(id));
+
+ cbinfo = &g_alarmcb[id];
+
+ if (cbinfo->ac_cb != NULL)
+ {
+ /* Alarm callback */
+
+ cb = cbinfo->ac_cb;
+ cb_arg = (FAR void*)cbinfo->ac_arg;
+
+ cbinfo->ac_cb = NULL;
+ cbinfo->ac_arg = NULL;
+
+ cb(cb_arg, id);
+ }
+
+ return 0;
+}
+#endif
+
+
+/************************************************************************************
+ * Name: cxd56_rtc_initialize
+ *
+ * Description:
+ * Actually initialize the hardware RTC. This function is called in the
+ * initialization sequence, thereafter may be called when wdog timer is expired.
+ *
+ * Input Parameters:
+ * arg: Not used
+ *
+ ************************************************************************************/
+
+static void cxd56_rtc_initialize(int argc, uint32_t arg)
+{
+ struct timespec ts;
+#ifdef CONFIG_CXD56_RTC_LATEINIT
+ static WDOG_ID s_wdog = NULL;
+ static int s_retry = 0;
+
+ if (s_wdog == NULL)
+ {
+ s_wdog = wd_create();
+ }
+
+ /* Check whether RTC clock source selects the external RTC and the synchronization
+ * from the external RTC is completed.
+ */
+
+ g_rtc_save = (struct rtc_backup_s*)BKUP->rtc_saved_data;
+
+ if (((getreg32(CXD56_TOPREG_CKSEL_ROOT) & STATUS_RTC_MASK) != STATUS_RTC_SEL) ||
+ (g_rtc_save->magic != MAGIC_RTC_SAVE))
+ {
+
+ /* Retry until RTC clock is stable */
+
+ if (s_retry++ < RTC_CLOCK_CHECK_MAX_RETRY) {
+
+ rtcinfo("retry count: %d\n", s_retry);
+
+ if (OK == wd_start(s_wdog, MSEC2TICK(RTC_CLOCK_CHECK_INTERVAL),
+ (wdentry_t)cxd56_rtc_initialize, 1, (wdparm_t)NULL))
+ {
+ /* Again, this function is called recursively */
+
+ return;
+ }
+ }
+
+ rtcerr("ERROR: Use inaccurate RCRTC instead of RTC\n");
+ }
+
+ /* RTC clock is stable, or give up using the external RTC */
+
+ if (s_wdog != NULL)
+ {
+ wd_delete(s_wdog);
+ }
+#endif
+
+#ifdef CONFIG_RTC_ALARM
+ /* Configure RTC interrupt to catch overflow and alarm interrupts. */
+
+ irq_attach(CXD56_IRQ_RTC0_A0, cxd56_rtc_interrupt, NULL);
+ irq_attach(CXD56_IRQ_RTC0_A2, cxd56_rtc_interrupt, NULL);
+ irq_attach(CXD56_IRQ_RTC_INT, cxd56_rtc_interrupt, NULL);
+ up_enable_irq(CXD56_IRQ_RTC0_A0);
+ up_enable_irq(CXD56_IRQ_RTC0_A2);
+ up_enable_irq(CXD56_IRQ_RTC_INT);
+#endif
+
+ /* If saved data is invalid, clear offset information */
+
+ if (g_rtc_save->magic != MAGIC_RTC_SAVE)
+ {
+ g_rtc_save->offset = 0;
+ }
+
+ if (g_rtc_save->offset == 0)
+ {
+ /* Keep the system operating time before RTC is enabled. */
+
+ clock_systimespec(&ts);
+ }
+
+ /* Synchronize the system time to the RTC time */
+
+ clock_synchronize();
+
+ if (g_rtc_save->offset == 0)
+ {
+ /* Reflect the system operating time to RTC offset data. */
+
+ g_rtc_save->offset = SEC_TO_CNT(ts.tv_sec) | NSEC_TO_PRECNT(ts.tv_nsec);
+ }
+
+ /* Make it possible to use the RTC timer functions */
+
+ g_rtc_enabled = true;
+
+ return;
+}
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_rtc_initialize
+ *
+ * Description:
+ * Initialize the hardware RTC per the selected configuration. This function is
+ * called once during the OS initialization sequence
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtc_initialize(void)
+{
+ cxd56_rtc_initialize(1, (wdparm_t)NULL);
+ return OK;
+}
+
+/************************************************************************************
+ * Name: up_rtc_time
+ *
+ * Description:
+ * Get the current time in seconds. This is similar to the standard time()
+ * function. This interface is only required if the low-resolution RTC/counter
+ * hardware implementation selected. It is only used by the RTOS during
+ * initialization to set up the system time when CONFIG_RTC is set but neither
+ * CONFIG_RTC_HIRES nor CONFIG_RTC_DATETIME are set.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * The current time in seconds
+ *
+ ************************************************************************************/
+
+#ifndef CONFIG_RTC_HIRES
+time_t up_rtc_time(void)
+{
+ uint64_t count;
+
+ count = cxd56_rtc_count();
+ count += g_rtc_save->offset;
+ count >>= 15; /* convert to 1sec resolution */
+
+ return (time_t)count/CONFIG_RTC_FREQUENCY;
+}
+#endif
+
+/************************************************************************************
+ * Name: up_rtc_gettime
+ *
+ * Description:
+ * Get the current time from the high resolution RTC clock/counter. This interface
+ * is only supported by the high-resolution RTC/counter hardware implementation.
+ * It is used to replace the system timer.
+ *
+ * Input Parameters:
+ * tp - The location to return the high resolution time value.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_HIRES
+int up_rtc_gettime(FAR struct timespec *tp)
+{
+ uint64_t count;
+
+ count = cxd56_rtc_count();
+ count += g_rtc_save->offset;
+
+ /* Then we can save the time in seconds and fractional seconds. */
+
+ tp->tv_sec = count / CONFIG_RTC_FREQUENCY;
+ tp->tv_nsec = (count % CONFIG_RTC_FREQUENCY)*(NSEC_PER_SEC/CONFIG_RTC_FREQUENCY);
+
+ rtc_dumptime(tp, "Getting time");
+
+ return OK;
+}
+#endif
+
+/************************************************************************************
+ * Name: up_rtc_settime
+ *
+ * Description:
+ * Set the RTC to the provided time. All RTC implementations must be able to
+ * set their time based on a standard timespec.
+ *
+ * Input Parameters:
+ * tp - the time to use
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtc_settime(FAR const struct timespec *tp)
+{
+ irqstate_t flags;
+ uint64_t count;
+
+ flags = enter_critical_section();
+
+#ifdef RTC_DIRECT_CONTROL
+ /* wait until previous write request is completed */
+
+ while (RTCREG_WREQ_BUSYA_MASK & getreg32(CXD56_RTC0_WRREGREQ));
+
+ putreg32(tp->tv_sec, CXD56_RTC0_WRREGPOSTCNT);
+ putreg32(NSEC_TO_PRECNT(tp->tv_nsec), CXD56_RTC0_WRREGPRECNT);
+
+ putreg32(RTCREG_WREQ_BUSYA_MASK, CXD56_RTC0_WRREGREQ);
+
+ /* wait until write request reflected */
+
+ while (RTCREG_WREQ_BUSYB_MASK & getreg32(CXD56_RTC0_WRREGREQ));
+
+#else
+ /* Only save the difference from HW raw value */
+
+ count = SEC_TO_CNT(tp->tv_sec) | NSEC_TO_PRECNT(tp->tv_nsec);
+ g_rtc_save->offset = (int64_t)count - (int64_t)cxd56_rtc_count();
+#endif
+
+ leave_critical_section(flags);
+
+ rtc_dumptime(tp, "Setting time");
+
+ return OK;
+}
+
+/************************************************************************************
+ * Name: cxd56_rtc_count
+ *
+ * Description:
+ * Get RTC raw counter value
+ *
+ * Returned Value:
+ * 64bit counter value running at 32kHz
+ *
+ ************************************************************************************/
+
+uint64_t cxd56_rtc_count(void)
+{
+ uint64_t val;
+ irqstate_t flags;
+
+ /*
+ * The pre register is latched with reading the post rtcounter register,
+ * so these registers always have to been read in the below order,
+ * 1st post -> 2nd pre, and should be operated in atomic.
+ */
+
+ flags = enter_critical_section();
+
+ val = (uint64_t)getreg32(CXD56_RTC0_RTPOSTCNT) << 15;
+ val |= getreg32(CXD56_RTC0_RTPRECNT);
+
+ leave_critical_section(flags);
+
+ return val;
+}
+
+/************************************************************************************
+ * Name: cxd56_rtc_almcount
+ *
+ * Description:
+ * Get RTC raw alarm counter value
+ *
+ * Returned Value:
+ * 64bit alarm counter value running at 32kHz
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+uint64_t cxd56_rtc_almcount(void)
+{
+ uint64_t val;
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+
+ val = (uint64_t)getreg32(CXD56_RTC0_SETALMPOSTCNT(0)) << 15;
+ val |= (getreg32(CXD56_RTC0_SETALMPRECNT(0)) & 0x7fff);
+
+ leave_critical_section(flags);
+
+ return val;
+}
+#endif
+
+/************************************************************************************
+ * Name: cxd56_rtc_setalarm
+ *
+ * Description:
+ * Set up an alarm.
+ *
+ * Input Parameters:
+ * alminfo - Information about the alarm configuration.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+int cxd56_rtc_setalarm(FAR struct alm_setalarm_s *alminfo)
+{
+ FAR struct alm_cbinfo_s *cbinfo;
+ irqstate_t flags;
+ int ret = -EBUSY;
+ int id;
+ uint64_t count;
+
+ ASSERT(alminfo != NULL);
+ DEBUGASSERT(RTC_ALARM_LAST > alminfo->as_id);
+
+ /* Set the alarm in hardware and enable interrupts */
+
+ id = alminfo->as_id;
+ cbinfo = &g_alarmcb[id];
+
+ if (cbinfo->ac_cb == NULL)
+ {
+ /* The set the alarm */
+
+ flags = enter_critical_section();
+
+ cbinfo->ac_cb = alminfo->as_cb;
+ cbinfo->ac_arg = alminfo->as_arg;
+
+ count = SEC_TO_CNT(alminfo->as_time.tv_sec) |
+ NSEC_TO_PRECNT(alminfo->as_time.tv_nsec);
+
+ count -= g_rtc_save->offset;
+
+ /* wait until previous alarm request is completed */
+
+ while (RTCREG_ASET_BUSY_MASK & getreg32(CXD56_RTC0_SETALMPRECNT(id)));
+
+ putreg32((uint32_t)(count >> 15), CXD56_RTC0_SETALMPOSTCNT(id));
+ putreg32((uint32_t)(count & 0x7fff), CXD56_RTC0_SETALMPRECNT(id));
+
+ while (RTCREG_ALM_BUSY_MASK & getreg32(CXD56_RTC0_ALMOUTEN(id)));
+
+ putreg32(RTCREG_ALM_EN_MASK | RTCREG_ALM_ERREN_MASK,
+ CXD56_RTC0_ALMOUTEN(id));
+
+ while (RTCREG_ALM_BUSY_MASK & getreg32(CXD56_RTC0_ALMOUTEN(id)));
+
+ leave_critical_section(flags);
+
+ rtc_dumptime(&alminfo->as_time, "New Alarm time");
+ ret = OK;
+ }
+
+ return ret;
+}
+#endif
+
+/************************************************************************************
+ * Name: cxd56_rtc_cancelalarm
+ *
+ * Description:
+ * Cancel an alaram.
+ *
+ * Input Parameters:
+ * alarmid - Identifies the alarm to be cancelled
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+int cxd56_rtc_cancelalarm(enum alm_id_e alarmid)
+{
+ FAR struct alm_cbinfo_s *cbinfo;
+ irqstate_t flags;
+ int ret = -ENODATA;
+
+ DEBUGASSERT(RTC_ALARM_LAST > alarmid);
+
+ /* Set the alarm in hardware and enable interrupts */
+
+ cbinfo = &g_alarmcb[alarmid];
+
+ if (cbinfo->ac_cb != NULL)
+ {
+ /* Unset the alarm */
+
+ flags = enter_critical_section();
+
+ cbinfo->ac_cb = NULL;
+
+ while (RTCREG_ALM_BUSY_MASK & getreg32(CXD56_RTC0_ALMOUTEN(alarmid)));
+
+ putreg32(0, CXD56_RTC0_ALMOUTEN(alarmid));
+
+ leave_critical_section(flags);
+
+ ret = OK;
+ }
+
+ return ret;
+}
+#endif
diff --git a/arch/arm/src/cxd56xx/cxd56_rtc.h b/arch/arm/src/cxd56xx/cxd56_rtc.h
new file mode 100644
index 00000000000..222c122e450
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_rtc.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_rtc.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_RTC_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_RTC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+#include
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_RTC_ALARM
+
+/* The form of an alarm callback */
+
+typedef CODE void (*alm_callback_t)(FAR void *arg, unsigned int alarmid);
+
+enum alm_id_e
+{
+ RTC_ALARM0 = 0, /* RTC ALARM 0 */
+ RTC_ALARM_LAST,
+ RTC_ALARM1 = 1, /* RTC ALARM 1 */
+ RTC_ALARM2, /* RTC ALARM 2 (relative) */
+};
+
+/* Structure used to pass parmaters to set an alarm */
+
+struct alm_setalarm_s
+{
+ int as_id; /* enum alm_id_e */
+ struct timespec as_time; /* Alarm expiration time */
+ alm_callback_t as_cb; /* Callback (if non-NULL) */
+ FAR void *as_arg; /* Argument for callback */
+};
+
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/************************************************************************************
+ * Name: cxd56_rtc_count
+ *
+ * Description:
+ * Get RTC raw counter value
+ *
+ * Returned Value:
+ * 64bit counter value running at 32kHz
+ *
+ ************************************************************************************/
+
+uint64_t cxd56_rtc_count(void);
+
+/************************************************************************************
+ * Name: cxd56_rtc_almcount
+ *
+ * Description:
+ * Get RTC raw alarm counter value
+ *
+ * Returned Value:
+ * 64bit alarm counter value running at 32kHz
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+uint64_t cxd56_rtc_almcount(void);
+#endif /* CONFIG_RTC_ALARM */
+
+/************************************************************************************
+ * Name: cxd56_rtc_setalarm
+ *
+ * Description:
+ * Set up an alarm.
+ *
+ * Input Parameters:
+ * alminfo - Information about the alarm configuration.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+int cxd56_rtc_setalarm(FAR struct alm_setalarm_s *alminfo);
+#endif /* CONFIG_RTC_ALARM */
+
+/************************************************************************************
+ * Name: cxd56_rtc_cancelalarm
+ *
+ * Description:
+ * Cancel an alaram.
+ *
+ * Input Parameters:
+ * alarmid - Identifies the alarm to be cancelled
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+int cxd56_rtc_cancelalarm(enum alm_id_e alarmid);
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Name: cxd56_rtc_lowerhalf
+ *
+ * Description:
+ * Instantiate the RTC lower half driver for the STM32L4. General usage:
+ *
+ * #include
+ * #include "stm32l4_rtc.h>
+ *
+ * struct rtc_lowerhalf_s *lower;
+ * lower = stm32l4_rtc_lowerhalf();
+ * rtc_initialize(0, lower);
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * On success, a non-NULL RTC lower interface is returned. NULL is
+ * returned on any failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_DRIVER
+FAR struct rtc_lowerhalf_s *cxd56_rtc_lowerhalf(void);
+#endif /* CONFIG_RTC_DRIVER */
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_RTC_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_rtc_lowerhalf.c b/arch/arm/src/cxd56xx/cxd56_rtc_lowerhalf.c
new file mode 100644
index 00000000000..2cd73d7a5d8
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_rtc_lowerhalf.c
@@ -0,0 +1,544 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_rtc_lowerhalf.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* REVISIT: This driver is *not* thread-safe! */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "chip.h"
+#include "cxd56_rtc.h"
+
+#ifdef CONFIG_RTC_DRIVER
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+struct cxd56_cbinfo_s
+{
+ volatile rtc_alarm_callback_t cb; /* Callback when the alarm expires */
+ volatile FAR void *priv; /* Private argurment to accompany callback */
+};
+#endif
+
+/* This is the private type for the RTC state. It must be cast compatible
+ * with struct rtc_lowerhalf_s.
+ */
+
+struct cxd56_lowerhalf_s
+{
+ /* This is the contained reference to the read-only, lower-half
+ * operations vtable (which may lie in FLASH or ROM)
+ */
+
+ FAR const struct rtc_ops_s *ops;
+
+ /* Data following is private to this driver and not visible outside of
+ * this file.
+ */
+
+#ifdef CONFIG_RTC_ALARM
+ /* Alarm callback information */
+
+ struct cxd56_cbinfo_s cbinfo[RTC_ALARM_LAST];
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+/* Prototypes for static methods in struct rtc_ops_s */
+
+static int cxd56_rdtime(FAR struct rtc_lowerhalf_s *lower,
+ FAR struct rtc_time *rtctime);
+static int cxd56_settime(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct rtc_time *rtctime);
+
+#ifdef CONFIG_RTC_ALARM
+static int cxd56_setalarm(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct lower_setalarm_s *alarminfo);
+static int cxd56_setrelative(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct lower_setrelative_s *alarminfo);
+static int cxd56_cancelalarm(FAR struct rtc_lowerhalf_s *lower,
+ int alarmid);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+/* CXD56 RTC driver operations */
+
+static const struct rtc_ops_s g_rtc_ops =
+{
+ .rdtime = cxd56_rdtime,
+ .settime = cxd56_settime,
+#ifdef CONFIG_RTC_ALARM
+ .setalarm = cxd56_setalarm,
+ .setrelative = cxd56_setrelative,
+ .cancelalarm = cxd56_cancelalarm,
+#endif
+#ifdef CONFIG_RTC_IOCTL
+ .ioctl = NULL,
+#endif
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ .destroy = NULL,
+#endif
+};
+
+/* CXD56 RTC device state */
+
+static struct cxd56_lowerhalf_s g_rtc_lowerhalf =
+{
+ .ops = &g_rtc_ops,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_alarm_callback
+ *
+ * Description:
+ * This is the function that is called from the RTC driver when the alarm
+ * goes off. It just invokes the upper half drivers callback.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static void cxd56_alarm_callback(FAR void *arg, unsigned int alarmid)
+{
+ FAR struct cxd56_lowerhalf_s *lower;
+ FAR struct cxd56_cbinfo_s *cbinfo;
+ rtc_alarm_callback_t cb;
+ FAR void *priv;
+
+ DEBUGASSERT((RTC_ALARM0 <= alarmid) && (alarmid < RTC_ALARM_LAST));
+
+ lower = (struct cxd56_lowerhalf_s *)arg;
+ cbinfo = &lower->cbinfo[alarmid];
+
+ /* Sample and clear the callback information to minimize the window in
+ * time in which race conditions can occur.
+ */
+
+ cb = (rtc_alarm_callback_t)cbinfo->cb;
+ priv = (FAR void *)cbinfo->priv;
+
+ cbinfo->cb = NULL;
+ cbinfo->priv = NULL;
+
+ /* Perform the callback */
+
+ if (cb != NULL)
+ {
+ cb(priv, alarmid);
+ }
+}
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Name: cxd56_rdtime
+ *
+ * Description:
+ * Implements the rdtime() method of the RTC driver interface
+ *
+ * Input Parameters:
+ * lower - A reference to RTC lower half driver state structure
+ * rcttime - The location in which to return the current RTC time.
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned
+ * on any failure.
+ *
+ ****************************************************************************/
+
+static int cxd56_rdtime(FAR struct rtc_lowerhalf_s *lower,
+ FAR struct rtc_time *rtctime)
+{
+#if defined(CONFIG_RTC_HIRES)
+ FAR struct timespec ts;
+ int ret;
+
+ /* Get the higher resolution time */
+
+ ret = up_rtc_gettime(&ts);
+ if (ret < 0)
+ {
+ goto errout_with_errno;
+ }
+
+ /* Convert the one second epoch time to a struct tm. This operation
+ * depends on the fact that struct rtc_time and struct tm are cast
+ * compatible.
+ */
+
+ if (!gmtime_r(&ts.tv_sec, (FAR struct tm *)rtctime))
+ {
+ goto errout_with_errno;
+ }
+
+ return OK;
+
+errout_with_errno:
+ ret = get_errno();
+ DEBUGASSERT(ret > 0);
+ return -ret;
+
+#else
+ time_t timer;
+
+ /* The resolution of time is only 1 second */
+
+ timer = up_rtc_time();
+
+ /* Convert the one second epoch time to a struct tm */
+
+ if (!gmtime_r(&timer, (FAR struct tm *)rtctime))
+ {
+ int errcode = get_errno();
+ DEBUGASSERT(errcode > 0);
+ return -errcode;
+ }
+
+ return OK;
+#endif
+}
+
+/****************************************************************************
+ * Name: cxd56_settime
+ *
+ * Description:
+ * Implements the settime() method of the RTC driver interface
+ *
+ * Input Parameters:
+ * lower - A reference to RTC lower half driver state structure
+ * rcttime - The new time to set
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned
+ * on any failure.
+ *
+ ****************************************************************************/
+
+static int cxd56_settime(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct rtc_time *rtctime)
+{
+ struct timespec ts;
+
+ /* Convert the struct rtc_time to a time_t. Here we assume that struct
+ * rtc_time is cast compatible with struct tm.
+ */
+
+ ts.tv_sec = mktime((FAR struct tm *)rtctime);
+ ts.tv_nsec = 0;
+
+ /* Now set the time (to one second accuracy) */
+
+ return up_rtc_settime(&ts);
+}
+
+/****************************************************************************
+ * Name: cxd56_setalarm
+ *
+ * Description:
+ * Set a new alarm. This function implements the setalarm() method of the
+ * RTC driver interface
+ *
+ * Input Parameters:
+ * lower - A reference to RTC lower half driver state structure
+ * alarminfo - Provided information needed to set the alarm
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned
+ * on any failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static int cxd56_setalarm(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct lower_setalarm_s *alarminfo)
+{
+ FAR struct cxd56_lowerhalf_s *priv;
+ FAR struct cxd56_cbinfo_s *cbinfo;
+ struct alm_setalarm_s lowerinfo;
+ int ret = -EINVAL;
+
+ DEBUGASSERT(lower != NULL && alarminfo != NULL);
+ DEBUGASSERT((RTC_ALARM0 == alarminfo->id) || (RTC_ALARM1 == alarminfo->id));
+
+ priv = (FAR struct cxd56_lowerhalf_s *)lower;
+
+ if ((RTC_ALARM0 == alarminfo->id) || (RTC_ALARM1 == alarminfo->id))
+ {
+ /* Remember the callback information */
+
+ cbinfo = &priv->cbinfo[alarminfo->id];
+ cbinfo->cb = alarminfo->cb;
+ cbinfo->priv = alarminfo->priv;
+
+ /* Set the alarm */
+
+ lowerinfo.as_id = alarminfo->id;
+ lowerinfo.as_cb = cxd56_alarm_callback;
+ lowerinfo.as_arg = priv;
+
+ /* Convert the RTC time to a timespec (1 second accuracy) */
+
+ lowerinfo.as_time.tv_sec = mktime((FAR struct tm *)&alarminfo->time);
+ lowerinfo.as_time.tv_nsec = 0;
+
+ /* And set the alarm */
+
+ ret = cxd56_rtc_setalarm(&lowerinfo);
+ if (ret < 0)
+ {
+ cbinfo->cb = NULL;
+ cbinfo->priv = NULL;
+ }
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: cxd56_setrelative
+ *
+ * Description:
+ * Set a new alarm relative to the current time. This function implements
+ * the setrelative() method of the RTC driver interface
+ *
+ * Input Parameters:
+ * lower - A reference to RTC lower half driver state structure
+ * alarminfo - Provided information needed to set the alarm
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned
+ * on any failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static int cxd56_setrelative(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct lower_setrelative_s *alarminfo)
+{
+ struct lower_setalarm_s setalarm;
+ FAR struct timespec ts;
+ struct alm_setalarm_s lowerinfo;
+ FAR struct cxd56_lowerhalf_s *priv;
+ FAR struct cxd56_cbinfo_s *cbinfo;
+ time_t seconds;
+ int ret = -EINVAL;
+
+ DEBUGASSERT(lower != NULL && alarminfo != NULL);
+ DEBUGASSERT((RTC_ALARM0 <= alarminfo->id) && (alarminfo->id < RTC_ALARM_LAST));
+
+ if (((alarminfo->id == RTC_ALARM0) || (alarminfo->id == RTC_ALARM1)) &&
+ (alarminfo->reltime > 0))
+ {
+ /* Disable pre-emption while we do this so that we don't have to worry
+ * about being suspended and working on an old time.
+ */
+
+ sched_lock();
+
+#if defined(CONFIG_RTC_HIRES)
+ /* Get the higher resolution time */
+
+ ret = up_rtc_gettime(&ts);
+ if (ret < 0)
+ {
+ sched_unlock();
+ return ret;
+ }
+#else
+ /* The resolution of time is only 1 second */
+
+ ts.tv_sec = up_rtc_time();
+ ts.tv_nsec = 0;
+#endif
+
+ /* Add the seconds offset. Add one to the number of seconds because
+ * we are unsure of the phase of the timer.
+ */
+
+ seconds = ts.tv_sec + (alarminfo->reltime + 1);
+
+ (void)gmtime_r(&seconds, (FAR struct tm *)&setalarm.time);
+
+ /* The set the alarm using this absolute time */
+
+ setalarm.id = alarminfo->id;
+ setalarm.cb = alarminfo->cb;
+ setalarm.priv = alarminfo->priv;
+
+ ret = cxd56_setalarm(lower, &setalarm);
+
+ sched_unlock();
+ }
+ else if ((alarminfo->id == RTC_ALARM2) && (alarminfo->reltime > 0))
+ {
+ sched_lock();
+
+ priv = (FAR struct cxd56_lowerhalf_s *)lower;
+
+ /* Remember the callback information */
+
+ cbinfo = &priv->cbinfo[alarminfo->id];
+ cbinfo->cb = alarminfo->cb;
+ cbinfo->priv = alarminfo->priv;
+
+ /* Set the alarm */
+
+ lowerinfo.as_id = alarminfo->id;
+ lowerinfo.as_cb = cxd56_alarm_callback;
+ lowerinfo.as_arg = priv;
+
+ lowerinfo.as_time.tv_sec = alarminfo->reltime;
+ lowerinfo.as_time.tv_nsec = 0;
+
+ ret = cxd56_rtc_setalarm(&lowerinfo);
+ if (ret < 0)
+ {
+ cbinfo->cb = NULL;
+ cbinfo->priv = NULL;
+ }
+
+ sched_unlock();
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: cxd56_cancelalarm
+ *
+ * Description:
+ * Cancel the current alarm. This function implements the cancelalarm()
+ * method of the RTC driver interface
+ *
+ * Input Parameters:
+ * lower - A reference to RTC lower half driver state structure
+ * alarmid - the alarm id
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned
+ * on any failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static int cxd56_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid)
+{
+ FAR struct cxd56_lowerhalf_s *priv;
+ FAR struct cxd56_cbinfo_s *cbinfo;
+ int ret = -EINVAL;
+
+ DEBUGASSERT(lower != NULL);
+ DEBUGASSERT((RTC_ALARM0 <= alarmid) && (alarmid < RTC_ALARM_LAST));
+
+ priv = (FAR struct cxd56_lowerhalf_s *)lower;
+
+ if ((RTC_ALARM0 <= alarmid) && (alarmid < RTC_ALARM_LAST))
+ {
+ /* Nullify callback information to reduce window for race conditions */
+
+ cbinfo = &priv->cbinfo[alarmid];
+ cbinfo->cb = NULL;
+ cbinfo->priv = NULL;
+
+ /* Then cancel the alarm */
+
+ ret = cxd56_rtc_cancelalarm((enum alm_id_e)alarmid);
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cxd56_rtc_lowerhalf
+ *
+ * Description:
+ * Instantiate the RTC lower half driver for the CXD56. General usage:
+ *
+ * #include
+ * #include "cxd56_rtc.h"
+ *
+ * struct rtc_lowerhalf_s *lower;
+ * lower = cxd56_rtc_lowerhalf();
+ * rtc_initialize(0, lower);
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * On success, a non-NULL RTC lower interface is returned. NULL is
+ * returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct rtc_lowerhalf_s *cxd56_rtc_lowerhalf(void)
+{
+ return (FAR struct rtc_lowerhalf_s *)&g_rtc_lowerhalf;
+}
+
+#endif /* CONFIG_RTC_DRIVER */
diff --git a/arch/arm/src/cxd56xx/cxd56_scu.c b/arch/arm/src/cxd56xx/cxd56_scu.c
new file mode 100644
index 00000000000..6a1b60cb8ec
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_scu.c
@@ -0,0 +1,3499 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_scu.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * include files
+ ****************************************************************************/
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "chip.h"
+#include "up_arch.h"
+
+#include "cxd56_scufifo.h"
+#include "cxd56_clock.h"
+#include "cxd56_adc.h"
+
+#ifdef CONFIG_CXD56_UDMAC
+#include "cxd56_udmac.h"
+#include
+#endif
+
+#include "hardware/cxd56_scu.h"
+#include "hardware/cxd56_scuseq.h"
+#include "hardware/cxd56_scufifo.h"
+
+/* SCU firmware (iSoP) binary */
+
+#include "hardware/cxd5602_isop.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_CXD56_SCU_DEBUG_ERR
+#define scuerr(fmt, ...) syslog(LOG_ERR, fmt, ## __VA_ARGS__)
+#else
+#define scuerr(x, ...)
+#endif
+#ifdef CONFIG_CXD56_SCU_DEBUG_WARN
+#define scuwarn(fmt, ...) syslog(LOG_WARN, fmt, ## __VA_ARGS__)
+#else
+#define scuwarn(x, ...)
+#endif
+#ifdef CONFIG_CXD56_SCU_DEBUG_INFO
+#define scuinfo(fmt, ...) syslog(LOG_INFO, fmt, ## __VA_ARGS__)
+#else
+#define scuinfo(x, ...)
+#endif
+
+/* Sequencer has 128 instruction area (16bits/inst)
+ * We allocate statically 12 instructions for each sequencers.
+ */
+
+#define INSTRUCTION_PER_SEQ 12
+
+/* Sequencer request code */
+
+#define REQ_DONE 3
+#define REQ_SLEEP 4
+#define REQ_STOP 5
+
+/* Disable decimation by set 15 to ratio (N bit field) */
+
+#define DECIMATION_OFF 15
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ev_notify_s
+{
+ int signo; /* Signal number */
+ int pid; /* Target PID */
+ struct scuev_arg_s *arg; /* Event argument */
+ struct scufifo_s *fifo; /* Reverse reference to FIFO */
+};
+
+struct wm_notify_s
+{
+ int signo; /* Signal number */
+ int pid; /* Target PID */
+ struct scutimestamp_s *ts; /* Event argument */
+ struct scufifo_s *fifo; /* Reverse reference to FIFO */
+};
+
+/* SCU FIFO management structure */
+
+struct scufifo_s
+{
+ int8_t wid; /* FIFO ID (Write side) */
+ int8_t rid; /* FIFO ID (Read side) */
+ uint8_t type; /* Normal or Decimator */
+ int8_t mid; /* Combined MATHFUNC */
+
+ uint16_t start; /* Start of FIFO memory */
+ uint16_t size; /* Size of FIFO memory */
+
+ uint32_t interval; /* Sample interval used for timestamp calculation */
+ uint16_t adjust; /* Adjustment value used for timestamp calculation */
+
+#ifdef CONFIG_CXD56_UDMAC
+ DMA_HANDLE dma; /* DMA for reading sensing data */
+ sem_t dmawait; /* Wait semaphore for DMA complete */
+ int dmaresult; /* DMA result */
+#endif
+};
+
+/* Sequencer */
+
+struct seq_s
+{
+ int8_t id; /* Sequencer ID */
+ uint8_t type; /* Normal or Decimator */
+ uint8_t bustype; /* I2C[01] or SPI or ADC */
+ int8_t active; /* Indicate active status.
+ * When active, any APIs will be returned state
+ * error.
+ */
+ uint8_t sample; /* Bytes per sample */
+ uint8_t rate; /* Sampling rate must be 2^rate (rate = 0 - 9) */
+
+ int8_t nr_fifos; /* For decimation, max 3 decimators can be used. */
+ struct scufifo_s *fifo; /* Owned FIFO (normal only) */
+};
+
+/* Decimation FIFO */
+
+struct decimation_fifo_s
+{
+ struct scufifo_s *fifo; /* Pointer to decimation FIFO */
+ uint8_t ratio; /* Decimation ratio */
+ uint8_t leveladj; /* Output data level adjustment */
+ uint8_t forcethrough; /* Force through */
+};
+
+/* Decimator, sub class of sequencer */
+
+struct decimator_s
+{
+ struct seq_s seq; /* Inherit, must be top of the structure */
+ struct decimation_fifo_s dfifo[3]; /* Decimation FIFO */
+};
+
+struct cxd56_scudev_s
+{
+ sem_t syncwait; /* Semaphore for synchronize with SCU firmware */
+ sem_t syncexc; /* Semaphore for exclusive access to sync */
+
+ /* SCU hardware resource management bitmaps (1 = allocated) */
+
+ uint8_t decimators; /* Bitmap for decimators */
+ uint8_t sequencers; /* Bitmap for normal sequencers */
+ uint8_t mathfuncs; /* Bitmap for MATHFUNC */
+ uint8_t oneshot; /* Bitmap for Oneshots */
+
+ sem_t oneshotwait[3]; /* Semaphore for wait oneshot sequence is done */
+#ifndef CONFIG_DISABLE_SIGNAL
+ struct ev_notify_s event[3]; /* MATHFUNC event notify */
+ struct wm_notify_s wm[14]; /* Watermark notify */
+#endif
+ int currentreq;
+};
+
+struct coeff_addr_s
+{
+ uint32_t s;
+ uint32_t c0;
+ uint32_t c1;
+ uint32_t c2;
+ uint32_t c3;
+ uint32_t c4;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* SCU hardware resource management *****************************************/
+
+static int findzeroandset(FAR uint8_t *bitmap, int nbits);
+static void bitmapclear(FAR uint8_t *bitmap, int bit);
+static inline int8_t deci_alloc(void);
+static inline void deci_free(int8_t sid);
+static inline int8_t mathf_alloc(void);
+static inline void mathf_free(int8_t mid);
+static int8_t seq_alloc(void);
+static inline void seq_free(int8_t sid);
+static inline int8_t oneshot_alloc(void);
+static inline void oneshot_free(int8_t tid);
+static int seq_semtake(sem_t *id);
+static void seq_semgive(sem_t *id);
+static void seq_fifosetactive(FAR struct seq_s *seq, int fifoid);
+static void seq_fifosetinactive(FAR struct seq_s *seq, int fifoid);
+static int seq_fifoisactive(FAR struct seq_s *seq, int fifoid);
+static int seq_isactive(FAR struct seq_s *seq);
+
+/* Sequencer control ********************************************************/
+
+static FAR struct seq_s *seq_new(void);
+static FAR struct seq_s *deci_new(void);
+
+static void seq_inhibitrequest(int req, bool set);
+static void seq_sync(FAR struct seq_s *seq, int req);
+static void seq_setproperty(int sid, int slave, int dest,
+ int offset, int len);
+static void seq_setinst(int sid, int offset, int len);
+static void seq_setbus(int sid, int bustype);
+static void seq_setdataformat(int sid, int start, int size, int swap,
+ int sample);
+static void seq_setmathwritevecelenum(int sid, uint8_t elem);
+static void seq_setsignconversion(int sid, int sign);
+static void seq_setstartmode(int sid, int mode);
+static void seq_setstartinterval(int sid, int interval);
+static void seq_setstartphase(int sid, int phase);
+static void seq_startseq(int sid);
+static void seq_stopseq(int sid);
+static int seq_setadjustment(FAR struct seq_s *seq, struct adjust_xyz_s *adj);
+static int seq_setfilter(FAR struct scufifo_s *fifo, int pos,
+ struct iir_filter_s iir[2]);
+static int seq_seteventnotifier(FAR struct scufifo_s *fifo,
+ struct scuev_notify_s *ev);
+static void seq_offsetgainenable(int sid, bool enable);
+static int seq_start(FAR struct seq_s *seq, int fifoid);
+static int seq_stop(FAR struct seq_s *seq, int fifoid);
+static int seq_setsamplingrate(FAR struct seq_s *seq, uint8_t samplingrate);
+static int seq_fifoinit(FAR struct seq_s *seq, int fifoid, uint16_t fsize);
+static void seq_fifofree(FAR struct scufifo_s *fifo);
+static inline struct scufifo_s *seq_getfifo(FAR struct seq_s *seq,
+ int fifoid);
+static void seq_setdecimation(int wid, uint8_t ratio, uint8_t leveladj,
+ uint8_t forcethrough);
+static int seq_setwatermark(FAR struct seq_s *seq, int fifoid,
+ FAR struct scufifo_wm_s *wm);
+#ifndef CONFIG_DISABLE_SIGNAL
+static void convert_firsttimestamp(struct scutimestamp_s *tm,
+ uint16_t interval, uint16_t sample,
+ uint16_t adjust);
+static void latest_timestamp(struct scufifo_s *fifo, uint32_t interval,
+ struct scutimestamp_s *tm, uint16_t *samples);
+static void seq_gettimestamp(struct scufifo_s *fifo,
+ struct scutimestamp_s *tm);
+#endif
+
+static int seq_oneshot(int bustype, int slave, FAR uint16_t *inst,
+ uint32_t nr_insts, FAR uint8_t *buffer, int len);
+static void seq_setfifomode(FAR struct seq_s *seq, int fifoid, int enable);
+#ifdef CONFIG_CXD56_UDMAC
+static void seq_fifodmadone(DMA_HANDLE handle, uint8_t status, void *arg);
+#endif
+static uint16_t seq_remakeinstruction(int bustype, uint16_t inst);
+
+/* Mathfunction *************************************************************/
+
+static void mathf_enable(int8_t mid, uint8_t wid);
+static void mathf_disable(int8_t mid);
+static inline void mathf_set_coeff(uint32_t caddr,
+ FAR struct iir_coeff_s *c);
+static void mathf_setiirfilter(int mid, int n,
+ FAR struct iir_filter_s *filter);
+
+/* Interrupt handlers *******************************************************/
+
+static int seq_scuirqhandler(int irq, FAR void *context, FAR void *arg);
+static void seq_handlefifointr(FAR struct cxd56_scudev_s *priv,
+ uint32_t intr);
+static void seq_handlemathfintr(FAR struct cxd56_scudev_s *priv,
+ uint32_t intr);
+static void seq_handleoneshot(FAR struct cxd56_scudev_s *priv,
+ uint32_t intr);
+static void seq_handleisopdoneintr(FAR struct cxd56_scudev_s *priv,
+ uint32_t intr);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct cxd56_scudev_s g_scudev;
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* SCU firmware (iSoP) */
+
+extern const unsigned long scuIsopProgArray[];
+extern const unsigned long sizeOfscuIsopProgArray;
+
+/* XXX: Convert coefficiencies register address. */
+
+#define __CADDR(m, n) \
+ { \
+ .s = SCU_MATHFUNC_PARAM_##m##_##n, \
+ .c0 = SCU_MATHFUNC_PARAM_C0_##m##_##n##_MSB, \
+ .c1 = SCU_MATHFUNC_PARAM_C1_##m##_##n##_MSB, \
+ .c2 = SCU_MATHFUNC_PARAM_C2_##m##_##n##_MSB, \
+ .c3 = SCU_MATHFUNC_PARAM_C3_##m##_##n##_MSB, \
+ .c4 = SCU_MATHFUNC_PARAM_C4_##m##_##n##_MSB, \
+ }
+
+static const struct coeff_addr_s g_caddrs[3][2] =
+{
+ {
+ __CADDR(0, 0),
+ __CADDR(0, 1)
+ },
+ {
+ __CADDR(1, 0),
+ __CADDR(1, 1)
+ },
+ {
+ __CADDR(2, 0),
+ __CADDR(2, 1)
+ }
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: seq_semtake
+ ****************************************************************************/
+
+static int seq_semtake(sem_t *id)
+{
+ while (sem_wait(id) != 0)
+ {
+ ASSERT(errno == EINTR);
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Name: seq_semgive
+ ****************************************************************************/
+
+static void seq_semgive(sem_t *id)
+{
+ sem_post(id);
+}
+
+/****************************************************************************
+ * Name: seq_fifosetactive
+ ****************************************************************************/
+
+static void seq_fifosetactive(FAR struct seq_s *seq, int fifoid)
+{
+ irqstate_t flags = enter_critical_section();
+ seq->active |= 1 << fifoid;
+ leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: seq_fifosetinactive
+ ****************************************************************************/
+
+static void seq_fifosetinactive(FAR struct seq_s *seq, int fifoid)
+{
+ irqstate_t flags = enter_critical_section();
+ seq->active &= ~(1 << fifoid);
+ leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: seq_fifoisactive
+ ****************************************************************************/
+
+static int seq_fifoisactive(FAR struct seq_s *seq, int fifoid)
+{
+ irqstate_t flags = enter_critical_section();
+ int8_t active = seq->active;
+ leave_critical_section(flags);
+ return active & (1 << fifoid);
+}
+
+/****************************************************************************
+ * Name: seq_isactive
+ ****************************************************************************/
+
+static int seq_isactive(FAR struct seq_s *seq)
+{
+ irqstate_t flags = enter_critical_section();
+ int8_t active = seq->active;
+ leave_critical_section(flags);
+ return active;
+}
+
+/****************************************************************************
+ * Name: findzeroandset
+ *
+ * Description:
+ * Find zero bit from LSB and set when found.
+ *
+ * Input Parameters:
+ * bitmap - Bitmap for searching
+ * nbits - Size of bitmap in bits
+ *
+ * Returned value:
+ * Bit number of set 1. -1 is not found.
+ *
+ ****************************************************************************/
+
+static int findzeroandset(FAR uint8_t *bitmap, int nbits)
+{
+ int i;
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+ for (i = 0; i < nbits; i++)
+ {
+ if (!(*bitmap & (1 << i)))
+ {
+ *bitmap |= 1 << i;
+ leave_critical_section(flags);
+ return i;
+ }
+ }
+
+ leave_critical_section(flags);
+ return -1;
+}
+
+/****************************************************************************
+ * Name: bitmapclear
+ *
+ * Description:
+ * Common atomic bit clear
+ *
+ ****************************************************************************/
+
+static void bitmapclear(FAR uint8_t *bitmap, int bit)
+{
+ irqstate_t flags = enter_critical_section();
+ *bitmap &= ~(1 << bit);
+ leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: deci_alloc
+ *
+ * Description:
+ * Allocate sequencer for decimation.
+ *
+ * Returned Value:
+ * Sequencer ID is returned on success. -1 is returned on failure.
+ *
+ ****************************************************************************/
+
+static inline int8_t deci_alloc(void)
+{
+ int8_t ret;
+ ret = findzeroandset(&g_scudev.decimators, 2);
+ if (ret >= 0)
+ {
+ /* Wakeup SCU anyway if sequencer allocated successfully */
+
+ seq_inhibitrequest(REQ_SLEEP, true);
+ }
+ return ret;
+}
+
+/****************************************************************************
+ * Name: deci_free
+ *
+ * Description:
+ * Free sequencer for decimation.
+ *
+ ****************************************************************************/
+
+static void deci_free(int8_t sid)
+{
+ DEBUGASSERT(sid == 0 || sid == 1);
+ bitmapclear(&g_scudev.decimators, sid);
+ if (!g_scudev.decimators && !g_scudev.sequencers)
+ {
+ /* SCU goes sleep when no sequencers running */
+
+ seq_inhibitrequest(REQ_SLEEP, false);
+ }
+}
+
+/****************************************************************************
+ * Name: mathf_alloc
+ *
+ * Description:
+ * Allocate MATHFUNC filter. MATHFUNC is max 3.
+ *
+ * Returned Value:
+ * Allocated MATHFUNC ID is returned on success. -1 is returned on failure.
+ *
+ ****************************************************************************/
+
+static inline int8_t mathf_alloc(void)
+{
+ return findzeroandset(&g_scudev.mathfuncs, 3);
+}
+
+/****************************************************************************
+ * Name: mathf_free
+ *
+ * Description:
+ * Free MATHFUNC
+ *
+ ****************************************************************************/
+
+static inline void mathf_free(int8_t mid)
+{
+ DEBUGASSERT(mid >= 0 && mid < 3);
+ bitmapclear(&g_scudev.mathfuncs, mid);
+}
+
+/****************************************************************************
+ * Name: seq_alloc
+ *
+ * Description:
+ * Allocate sequencer
+ *
+ * Returned Value:
+ * Allocated sequencer ID is returned on success. -1 is returned on failure.
+ *
+ ****************************************************************************/
+
+static int8_t seq_alloc(void)
+{
+ int8_t sid = findzeroandset(&g_scudev.sequencers, 8);
+ if (sid < 0)
+ {
+ return -1;
+ }
+
+ /* Wakeup SCU anyway if sequencer allocated successfully */
+
+ seq_inhibitrequest(REQ_SLEEP, true);
+
+ return sid + 2;
+}
+
+/****************************************************************************
+ * Name: seq_free
+ *
+ * Description:
+ * Free sequencer
+ *
+ ****************************************************************************/
+
+static void seq_free(int8_t sid)
+{
+ DEBUGASSERT(sid >= 2 && sid < 10);
+ bitmapclear(&g_scudev.sequencers, sid - 2);
+ if (!g_scudev.decimators && !g_scudev.sequencers)
+ {
+ /* SCU goes sleep when no sequencers running */
+
+ seq_inhibitrequest(REQ_SLEEP, false);
+ }
+}
+
+/****************************************************************************
+ * Name: oneshot_alloc
+ *
+ * Description:
+ * Allocate oneshot sequencer
+ *
+ * Returned Value:
+ * Oneshot ID
+ *
+ ****************************************************************************/
+
+static inline int8_t oneshot_alloc(void)
+{
+ return findzeroandset(&g_scudev.oneshot, 3);
+}
+
+/****************************************************************************
+ * Name: oneshot_free
+ *
+ * Description:
+ * Free oneshot sequencer
+ *
+ * Input Parameters:
+ * tid - Oneshot ID (0-2)
+ *
+ ****************************************************************************/
+
+static inline void oneshot_free(int8_t tid)
+{
+ DEBUGASSERT(tid >= 0 && tid < 3);
+ bitmapclear(&g_scudev.oneshot, tid);
+}
+
+/****************************************************************************
+ * Name: seq_inhibitrequest
+ *
+ * Description:
+ * Get the contents of the SPI register at offset
+ * Holy terrible SEQ_ACCESS_INHIBIT register's bit field name is
+ * different from actual function.
+ *
+ * Input Parameters:
+ * req - REQ_DONE, REQ_SLEEP, REQ_STOP
+ * inhibit - false (release) or true (set)
+ *
+ * Returned Value:
+ * The contents of the 32-bit register
+ *
+ ****************************************************************************/
+
+static void seq_inhibitrequest(int req, bool set)
+{
+ uint32_t val;
+ val = getreg32(SCU_SEQ_ACCESS_INHIBIT) & ~(1 << req);
+ if (set)
+ {
+ val |= 1 << req;
+ }
+
+ putreg32(val, SCU_SEQ_ACCESS_INHIBIT);
+}
+
+/****************************************************************************
+ * Name: seq_setdecimation
+ *
+ * Description:
+ * Set decimation configurations
+ *
+ * Input Parameters:
+ * wid - FIFO ID (write side)
+ * ratio - Decimation ratio
+ * leveladj - Output data level adjustment (2^n)
+ * forcethrough - Bypassing decimation calculation (not same as ratio x1)
+ *
+ ****************************************************************************/
+
+static void seq_setdecimation(int wid, uint8_t ratio, uint8_t leveladj,
+ uint8_t forcethrough)
+{
+ uint32_t val;
+ uint32_t addr;
+ int shift;
+
+ shift = 8 * (wid & 3);
+ addr = wid < 4 ? SCU_DECIMATION_PARAM0 : SCU_DECIMATION_PARAM1;
+
+ val = getreg32(addr) & ~(0xff << shift);
+ val |= (ratio & 0xf) << shift; /* N */
+ val |= (leveladj & 0x3) << (shift + 4); /* LEVEL_ADJ */
+ val |= (forcethrough & 1) << (shift + 7);
+ putreg32(val, addr);
+}
+
+/****************************************************************************
+ * Name: seq_setproperty
+ *
+ * Description:
+ * Set sequencer property parameters
+ *
+ * Input Parameters:
+ * sid - Sequender ID
+ * slave - Slave select (SPI) or address (I2C)
+ * dest - Output buffer (1 - 3, oneshot only)
+ * offset - Instruction start offset
+ * len - Instruction length
+ *
+ ****************************************************************************/
+
+static void seq_setproperty(int sid, int slave, int out, int offset, int len)
+{
+ uint32_t val;
+ val = slave & 0x3ff;
+ val |= (out & 0x3) << 12;
+ val |= (offset & 0x7f) << 16;
+ val |= (len & 0xf) << 24;
+ putreg32(val, SCUSEQ_PROPERTY(sid));
+}
+
+/****************************************************************************
+ * Name: seq_setinst
+ *
+ * Description:
+ * Set instruction and its length to sequencer property
+ *
+ * Input Parameters:
+ * sid - Sequender ID
+ * offset - Instruction start offset
+ * len - Instruction length
+ *
+ ****************************************************************************/
+
+static void seq_setinst(int sid, int offset, int len)
+{
+ uint32_t val;
+ val = getreg32(SCUSEQ_PROPERTY(sid)) & ~((0xf << 24) | (0x7f << 16));
+ val |= (offset & 0x7f) << 16;
+ val |= (len & 0xf) << 24;
+ putreg32(val, SCUSEQ_PROPERTY(sid));
+}
+
+/****************************************************************************
+ * Name: seq_setbus
+ *
+ * Description:
+ * Set source bus type for sequencer
+ *
+ * Input Parameters:
+ * sid - Sequencer ID
+ * bustype - Bus type (SCU_BUS_*)
+ *
+ ****************************************************************************/
+
+static void seq_setbus(int sid, int bustype)
+{
+ uint32_t val;
+ uint32_t mask;
+ uint32_t bit;
+
+ bit = 1 << sid;
+ mask = bit | bit << 10 | bit << 20;
+ switch (bustype)
+ {
+ case SCU_BUS_I2C0:
+ {
+ bit <<= 10;
+ }
+ break;
+ case SCU_BUS_I2C1:
+ {
+ bit <<= 20;
+ }
+ break;
+ case SCU_BUS_SPI:
+ break;
+ case SCU_BUS_LPADC0:
+ case SCU_BUS_LPADC1:
+ case SCU_BUS_LPADC2:
+ case SCU_BUS_LPADC3:
+ case SCU_BUS_HPADC0:
+ case SCU_BUS_HPADC1:
+ default:
+ return;
+ }
+
+ val = getreg32(SCUSEQ_SRC_SEL) & ~mask;
+ putreg32(val | bit, SCUSEQ_SRC_SEL);
+}
+
+/****************************************************************************
+ * Name: seq_setdataformat
+ *
+ * Description:
+ * Reading sensor data format
+ *
+ * Input Parameters:
+ * sid - Sequencer ID
+ * start - Sensor data start offset in sequencer picked
+ * bps - Bytes per sample
+ * swap - Wwap bytes
+ * elem - Number of elements in sample
+ *
+ ****************************************************************************/
+
+static void seq_setdataformat(int sid, int start, int bps, int swap, int elem)
+{
+ uint32_t val;
+ val = start & 0xf;
+ val |= (bps & 0xf) << 4;
+ val |= (swap & 0x1) << 16;
+ val |= (elem & 0x3) << 28;
+ putreg32(val, SCUSEQ_OUT_FORMAT(sid));
+}
+
+/****************************************************************************
+ * Name: seq_setmathwritevecelenum
+ *
+ * Description:
+ * Set number of elements in sample
+ * (MATH_WRITE_VEC_ELE_NUM field in SEQ_OUT_FORMAT_n)
+ *
+ * Input Parameters:
+ * sid - Sequencer ID
+ * elem - Number of elements in sample
+ *
+ ****************************************************************************/
+
+static void seq_setmathwritevecelenum(int sid, uint8_t elem)
+{
+ uint32_t val;
+
+ DEBUGASSERT(elem > 0 && elem <= 3);
+
+ val = getreg32(SCUSEQ_OUT_FORMAT(sid));
+ val = (val & ~(0x3 << 28)) | ((elem - 1) & 0x3) << 28;
+ putreg32(val, SCUSEQ_OUT_FORMAT(sid));
+}
+
+/****************************************************************************
+ * Name: seq_setsignconversion
+ *
+ * Description:
+ * Enable or disable sensor data sign conversion feature for preprocessing.
+ *
+ * Input Parameters:
+ * sid - Sequencer ID
+ * sign - 0 to no conversion, 1 to convert unsigned to signed
+ *
+ ****************************************************************************/
+
+static void seq_setsignconversion(int sid, int sign)
+{
+ uint32_t val;
+ int shift = sid < 2 ? sid * 4 : sid + 6;
+
+ val = getreg32(SCU_UNSIGNED_TO_SIGNED);
+ val &= ~(1 << shift);
+ putreg32(val | (sign << shift), SCU_UNSIGNED_TO_SIGNED);
+}
+
+/****************************************************************************
+ * Name: seq_setstartmode
+ *
+ * Description:
+ * Set sequencer start mode
+ *
+ * Input Parameters:
+ * sid - Sequencer ID
+ * mode - Start mode
+ *
+ ****************************************************************************/
+
+static void seq_setstartmode(int sid, int mode)
+{
+ uint32_t val;
+ uint32_t shift;
+
+ shift = sid * 2;
+ val = getreg32(SCU_START_MODE1) & ~(3 << shift);
+ putreg32(val | (mode << shift), SCU_START_MODE1);
+}
+
+/****************************************************************************
+ * Name: seq_setstartinterval
+ *
+ * Description:
+ * Set sequencer interval
+ *
+ * Input Parameters:
+ * sid - Sequencer ID
+ * interval - Interval
+ *
+ ****************************************************************************/
+
+static void seq_setstartinterval(int sid, int interval)
+{
+ uint32_t addr = SCU_START_INTERVAL3_0 + (sid & 0xc);
+ uint32_t val;
+ uint32_t shift;
+
+ shift = (sid & 3) * 8;
+ val = getreg32(addr) & ~(0xf << shift);
+ putreg32(val | (interval << shift), addr);
+}
+
+/****************************************************************************
+ * Name: seq_setstartphase
+ *
+ * Description:
+ * Set sequencer start phase.
+ * This function always set to zero right now. I don't know what this
+ * parameter affects for.
+ *
+ * Input Parameters:
+ * sid - Sequencer ID
+ * phase - Phase value
+ *
+ ****************************************************************************/
+
+static void seq_setstartphase(int sid, int phase)
+{
+ uint32_t addr = SCU_START_PHASE1_0 + ((sid & 0xe) << 1);
+ uint32_t val;
+ uint32_t shift;
+
+ shift = (sid & 1) * 16;
+ val = getreg32(addr) & ~(0x1ff << shift);
+ putreg32(val | (phase << shift), addr);
+}
+
+/****************************************************************************
+ * Name: seq_startseq
+ *
+ * Description:
+ * Start sequencer
+ *
+ * Input Parameters:
+ * sid - Sequencer ID
+ *
+ ****************************************************************************/
+
+static void seq_startseq(int sid)
+{
+ uint32_t val;
+ val = getreg32(SCU_START_MODE0);
+ putreg32(val | (1 << sid), SCU_START_MODE0);
+}
+
+/****************************************************************************
+ * Name: seq_stopseq
+ *
+ * Description:
+ * Stop sequencer
+ *
+ * Input Parameters:
+ * sid - Sequencer ID
+ *
+ ****************************************************************************/
+
+static void seq_stopseq(int sid)
+{
+ uint32_t val;
+ val = getreg32(SCU_START_MODE0);
+ putreg32(val & ~(1 << sid), SCU_START_MODE0);
+}
+
+/****************************************************************************
+ * Name: seq_oneshot
+ *
+ * Description:
+ * Perform one shot feature, this function can be use for any register
+ * access to connected sensors. (e.g. configure power mode)
+ * This function use empty sequencer temporarily, other than allocated
+ * sequencer to the sensor device driver. Thus, this function fails when
+ * all of normal sequencers are allocated.
+ *
+ * Input Parameters:
+ * bustype - One of SCU_BUS_SPI, SCU_BUS_I2C0 and SCU_BUS_I2C1
+ * slave - Slave select (SPI) or address (I2C)
+ * inst - Pointer to series of read/write instruction array
+ * nr_insts - Number of instructions
+ * buffer - Receive data buffer
+ * len - Length of receive data buffer
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success. A negated errno value is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static int seq_oneshot(int bustype, int slave, FAR uint16_t *inst,
+ uint32_t nr_insts, FAR uint8_t *buffer, int len)
+{
+ struct cxd56_scudev_s *priv = &g_scudev;
+ irqstate_t flags;
+ int sid;
+ int tid;
+ int istart;
+ int i;
+ int ret = OK;
+ uint16_t lastinst;
+
+ ASSERT(bustype == SCU_BUS_SPI || bustype == SCU_BUS_I2C0 ||
+ bustype == SCU_BUS_I2C1);
+
+ if (nr_insts > INSTRUCTION_PER_SEQ)
+ {
+ return -EINVAL;
+ }
+
+ /* If buffer is non NULL, check receive length is valid */
+
+ if (buffer && (len <= 0 || len > 16))
+ {
+ return -EINVAL;
+ }
+
+ flags = enter_critical_section();
+ sid = seq_alloc();
+ if (sid < 0)
+ {
+ leave_critical_section(flags);
+ return -ENOENT;
+ }
+
+ tid = oneshot_alloc();
+ if (tid < 0)
+ {
+ seq_free(sid);
+ leave_critical_section(flags);
+ return -ENOENT;
+ }
+ leave_critical_section(flags);
+
+ /* Remake last instruction, if needed. */
+
+ lastinst = seq_remakeinstruction(bustype, inst[nr_insts - 1]);
+
+ /* Copy sequencer instruction */
+
+ istart = sid * INSTRUCTION_PER_SEQ;
+ for (i = 0; i < nr_insts - 1; i++)
+ {
+ putreg16(inst[i], SCUSEQ_INSTRUCTION(istart + i));
+ }
+ putreg16(lastinst, SCUSEQ_INSTRUCTION(istart + nr_insts - 1));
+
+ /* Setup sequencer as oneshot mode
+ * Oneshot mode is special function, so can not be use to MATHFUNC,
+ * sign conversion and offset/gain adjustment.
+ */
+
+ seq_setbus(sid, bustype);
+ seq_setproperty(sid, slave, tid + 1, istart, nr_insts - 1);
+ seq_setsignconversion(sid, 0);
+ seq_offsetgainenable(sid, false);
+ seq_setdataformat(sid, 0, buffer ? len - 1 : 0, 0, 0);
+
+ /* Mode set "Stop" */
+
+ seq_setstartmode(sid, 0);
+
+ /* Set fixed value interval (0xa) for one shot sequencer */
+
+ seq_setstartinterval(sid, 0xa);
+
+ /* Enable interrupt for one shot sequencer */
+
+ putreg32(1 << (tid + 24), SCU_INT_ENABLE_MAIN);
+
+ scuinfo("Sequencer start.\n");
+
+ /* Start sequencer as one shot mode */
+
+ seq_startseq(sid);
+ putreg32(1 << sid, SCU_SINGLE_EXE);
+
+ /* Wait for one shot is done */
+
+ seq_semtake(&priv->oneshotwait[tid]);
+
+ /* Disable interrupt for one shot sequencer */
+
+ putreg32(1 << (tid + 24), SCU_INT_DISABLE_MAIN);
+
+ scuinfo("Sequencer done.\n");
+
+ if (buffer)
+ {
+ /* Copy sequencer output results to user buffer.
+ * XXX: Sequencer output RAM offset is differ from document.
+ */
+
+ memcpy(buffer, (void *)(SCUSEQ_RAM_OUT_DATA0 + (0x10 * tid)), len);
+ }
+
+ /* Stop sequencer */
+
+ seq_stopseq(sid);
+
+ /* Destroy oneshot resources */
+
+ flags = enter_critical_section();
+ oneshot_free(tid);
+ seq_free(sid);
+ leave_critical_section(flags);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: seq_enableoffsetgain
+ *
+ * Description:
+ * Enable offset/gain preprocessing
+ *
+ ****************************************************************************/
+
+static void seq_offsetgainenable(int sid, bool enable)
+{
+ uint32_t val;
+ int n = sid < 2 ? sid * 4 : sid + 6;
+
+ val = getreg32(SCU_OFST_GAIN_EN);
+ if (enable)
+ {
+ val |= 1 << n;
+ }
+ else
+ {
+ val &= ~(1 << n);
+ }
+ putreg32(val, SCU_OFST_GAIN_EN);
+}
+
+/****************************************************************************
+ * Name: seq_start
+ *
+ * Description:
+ * Start sequencer. This function is for SCUIOC_START.
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * fifoid - FIFO ID (0-2, decimator only)
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success. A negated errno value is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static int seq_start(FAR struct seq_s *seq, int fifoid)
+{
+ struct scufifo_s *fifo;
+ uint32_t interval;
+
+ DEBUGASSERT(seq);
+ DEBUGASSERT(fifoid >= 0 && fifoid < 3);
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ struct decimator_s *deci = (struct decimator_s *)seq;
+ struct decimation_fifo_s *dfifo = &deci->dfifo[fifoid];
+
+ /* Avoid confilict for DECIMATION_PARAM register access with SCU */
+
+ if (seq_isactive(seq))
+ {
+ seq_sync(&deci->seq, REQ_STOP);
+ }
+
+ seq_setdecimation(dfifo->fifo->wid, dfifo->ratio, dfifo->leveladj,
+ dfifo->forcethrough);
+ fifo = dfifo->fifo;
+
+ interval = dfifo->ratio + seq->rate;
+
+ /* Prevent SCU freeze by frequently REQ_STOP */
+
+ if (seq_isactive(seq))
+ {
+ up_udelay(100);
+ }
+ }
+ else
+ {
+ fifo = seq->fifo;
+ interval = seq->rate;
+ }
+
+ if (!fifo)
+ {
+ return -EPERM;
+ }
+
+ if (!seq_isactive(seq))
+ {
+ if (!(seq->bustype & 0x10))
+ {
+ /* Calculate timestamp interval prediv * (2 ^ interval) */
+
+ fifo->interval = CONFIG_CXD56_SCU_PREDIV * (1 << interval);
+ fifo->adjust = 0;
+
+ /* Go sequencer */
+
+ seq_setstartmode(seq->id, 1);
+ seq_setstartinterval(seq->id, seq->rate);
+ seq_setstartphase(seq->id, 1);
+ seq_startseq(seq->id);
+ }
+ else
+ {
+ uint32_t mask;
+ uint32_t val;
+
+ /* Calculate timestamp interval for ADC */
+
+ cxd56_adc_getinterval(seq->bustype, &fifo->interval, &fifo->adjust);
+
+ /* Enable ADC */
+
+ mask = 0x1 << (24 + (seq->bustype & 0x7));
+ val = getreg32(SCUSEQ_ADC_PROPERTY) & ~mask;
+ val |= (0x1 << (24 + (seq->bustype & 0x7)));
+ putreg32(val, SCUSEQ_ADC_PROPERTY);
+ }
+ }
+
+ seq_fifosetactive(seq, fifoid);
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: seq_stop
+ *
+ * Description:
+ * Stop sequencer (external API)
+ *
+ ****************************************************************************/
+
+static int seq_stop(FAR struct seq_s *seq, int fifoid)
+{
+ struct scufifo_s *fifo;
+ uint32_t val;
+
+ DEBUGASSERT(seq);
+ DEBUGASSERT(fifoid >= 0 && fifoid < 3);
+
+ fifo = seq_getfifo(seq, fifoid);
+
+ if (fifo == NULL)
+ {
+ scuerr("missing FIFO\n");
+ return -EPERM;
+ }
+
+ if (!seq_isactive(seq))
+ {
+ return OK;
+ }
+
+ val = getreg32(SCUFIFO_R_CTRL1(fifo->rid));
+ putreg32(val & ~(1 << 24), SCUFIFO_R_CTRL1(fifo->rid));
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ seq_sync(seq, REQ_STOP);
+
+ /* Set ratio to 15 to disable decimator */
+
+ seq_setdecimation(fifo->wid, DECIMATION_OFF, 0, 0);
+
+ /* Prevent SCU freeze by frequently REQ_STOP */
+
+ up_udelay(100);
+ }
+
+ seq_fifosetinactive(seq, fifoid);
+
+ /* If all of FIFOs are stopped, then stop sequencer. */
+
+ if (!seq_isactive(seq))
+ {
+ if (!(seq->bustype & 0x10))
+ {
+ seq_setstartmode(seq->id, 0);
+ seq_stopseq(seq->id);
+
+ /* Wait for stop done */
+
+ seq_sync(seq, REQ_DONE);
+ }
+ else
+ {
+ /* Disable ADC */
+
+ uint32_t mask = 0x1 << (24 + (seq->bustype & 0x7));
+ val = getreg32(SCUSEQ_ADC_PROPERTY) & ~mask;
+ putreg32(val, SCUSEQ_ADC_PROPERTY);
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: mathf_enable
+ *
+ * Description:
+ * Enable MATHFUNC to specified FIFO
+ *
+ * Input Parameters:
+ * mid - MATHFUNC ID
+ * wid - FIFO ID (Write side)
+ *
+ ****************************************************************************/
+
+static void mathf_enable(int8_t mid, uint8_t wid)
+{
+ uint32_t val;
+
+ val = getreg32(SCU_MATHFUNC_SEL);
+ val &= ~(0xf << (mid * 8));
+ val |= 1 << ((mid * 8) + 4);
+ putreg32(val | (wid << (mid * 8)), SCU_MATHFUNC_SEL);
+ putreg32(1 << mid, SCU_MATHFUNC_CLR);
+}
+
+/****************************************************************************
+ * Name: mathf_disable
+ *
+ * Description:
+ * Disable MATHFUNC
+ *
+ * Input Parameters:
+ * mid - MATHFUNC ID
+ *
+ ****************************************************************************/
+
+static void mathf_disable(int8_t mid)
+{
+ uint32_t val;
+ val = getreg32(SCU_MATHFUNC_SEL);
+ val &= ~(1 << ((mid * 8) + 4));
+ putreg32(val, SCU_MATHFUNC_SEL);
+}
+
+/****************************************************************************
+ * Name: mathf_set_coeff
+ *
+ * Description:
+ * Set 1 coefficiency value
+ *
+ ****************************************************************************/
+
+static inline void mathf_set_coeff(uint32_t caddr, FAR struct iir_coeff_s *c)
+{
+ putreg32(c->h, caddr);
+ putreg32((c->l & 0x3) << 30, caddr + 4);
+}
+
+/****************************************************************************
+ * Name: mathf_setiirfilter
+ *
+ * Description:
+ * Set series of coefficiencies for 2 IIR filters
+ *
+ * Input Parameters:
+ * mid - MATHFUNC ID
+ * n - Filter ID
+ * filter - IIR filter setting
+ *
+ ****************************************************************************/
+
+static void mathf_setiirfilter(int mid, int n,
+ FAR struct iir_filter_s *filter)
+{
+ const struct coeff_addr_s *caddr;
+
+ caddr = g_caddrs[mid];
+
+ putreg32((filter->ishift & 0x7) | ((filter->oshift & 0x7) << 8),
+ caddr[0].s);
+
+ mathf_set_coeff(caddr[n].c0, &filter->coeff[0]);
+ mathf_set_coeff(caddr[n].c1, &filter->coeff[1]);
+ mathf_set_coeff(caddr[n].c2, &filter->coeff[2]);
+ mathf_set_coeff(caddr[n].c3, &filter->coeff[3]);
+ mathf_set_coeff(caddr[n].c4, &filter->coeff[4]);
+}
+
+/****************************************************************************
+ * Name: seq_setsamplingrate
+ *
+ * Description:
+ * Set sequencer sampling rate
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * samplingrate - Sampling rate. Sampling rate is based on
+ * 32768 Hz / predivider.
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success. A negated errno value is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static int seq_setsamplingrate(FAR struct seq_s *seq, uint8_t samplingrate)
+{
+ DEBUGASSERT(seq);
+
+ if (samplingrate > 9)
+ {
+ return -EINVAL;
+ }
+ seq->rate = samplingrate;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: seq_sync
+ *
+ * Description:
+ * Send specific request to SCU firmware
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * req - Request code for SCU firmware (REQ_*)
+ *
+ ****************************************************************************/
+
+static void seq_sync(FAR struct seq_s *seq, int req)
+{
+ FAR struct cxd56_scudev_s *priv = &g_scudev;
+
+ seq_semtake(&priv->syncexc);
+
+ /* Save current request */
+
+ priv->currentreq = req;
+
+ putreg32(1 << 27, SCU_INT_CLEAR_MAIN);
+ putreg32(1 << 27, SCU_INT_ENABLE_MAIN);
+
+ putreg32(seq->id & 0xf, SCUSEQ_SYNCRO_CPU2ISOP);
+
+ /* Send request to SCU */
+
+ seq_inhibitrequest(req, true);
+
+ /* Wait for interrupt from SCU firmware */
+
+ seq_semtake(&priv->syncwait);
+
+ priv->currentreq = 0;
+
+ seq_semgive(&priv->syncexc);
+}
+
+/****************************************************************************
+ * Name: seq_handlefifintr
+ *
+ * Description:
+ * Handle FIFO overrun error
+ *
+ ****************************************************************************/
+
+static void seq_handlefifointr(FAR struct cxd56_scudev_s *priv, uint32_t intr)
+{
+ uint32_t bit;
+ int i;
+#ifndef CONFIG_DISABLE_SIGNAL
+ struct wm_notify_s *notify;
+# ifdef CONFIG_CAN_PASS_STRUCTS
+ union sigval value;
+# endif
+#endif
+
+ if ((intr & 0x007ffe00) == 0)
+ {
+ return;
+ }
+
+ /* Each FIFO almost full interrupt cause are starts with 9 */
+
+ for (i = 0, bit = 1 << 9; i < 14; i++, bit <<= 1)
+ {
+ if (intr & bit)
+ {
+ /* Clear interrupt */
+
+ putreg32(bit, SCU_INT_CLEAR_MAIN);
+
+#ifndef CONFIG_DISABLE_SIGNAL
+ notify = &priv->wm[i];
+
+ if (notify->ts)
+ {
+ seq_gettimestamp(notify->fifo, notify->ts);
+ }
+
+ DEBUGASSERT(notify->pid != 0);
+
+# ifdef CONFIG_CAN_PASS_STRUCTS
+ value.sival_ptr = notify->ts;
+ (void)sigqueue(notify->pid, notify->signo, value);
+# else
+ (void)sigqueue(notify->pid, notify->signo, (FAR void *)notify->ts);
+# endif
+#endif
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: seq_handlemathfintr
+ *
+ * Description:
+ * Handle MATHFUNC rise and fall event interrupts
+ *
+ ****************************************************************************/
+
+static void seq_handlemathfintr(FAR struct cxd56_scudev_s *priv,
+ uint32_t intr)
+{
+ int i;
+ uint32_t bit;
+ uint32_t rise;
+ uint32_t fall;
+#ifndef CONFIG_DISABLE_SIGNAL
+ struct ev_notify_s *notify;
+ int detected = 0;
+#endif
+
+ rise = (intr >> 6) & 0x7;
+ fall = (intr >> 28) & 0x7;
+
+ if (rise == 0 && fall == 0)
+ {
+ return;
+ }
+
+ for (i = 0, bit = 1; i < 3; i++, bit <<= 1)
+ {
+#ifndef CONFIG_DISABLE_SIGNAL
+ notify = &priv->event[i];
+#endif
+ /* Detect rise event */
+
+ if (rise & bit)
+ {
+ putreg32(bit << 6, SCU_INT_CLEAR_MAIN);
+
+#ifndef CONFIG_DISABLE_SIGNAL
+ /* Get rise event occurred timestamp */
+
+ if (notify->arg)
+ {
+ notify->arg->ts.sec =
+ getreg32(SCU_EVENT_TIMESTAMP0_R_MSB + (i * 8));
+ notify->arg->ts.tick =
+ getreg32(SCU_EVENT_TIMESTAMP0_R_LSB + (i * 8));
+ notify->arg->type = SCU_EV_RISE;
+ }
+ detected = 1;
+#endif
+ }
+
+ /* Detect fall event */
+
+ if (fall & bit)
+ {
+ putreg32(bit << 28, SCU_INT_CLEAR_MAIN);
+
+#ifndef CONFIG_DISABLE_SIGNAL
+ /* Get fall event occurred timestamp */
+
+ if (notify->arg)
+ {
+ notify->arg->ts.sec =
+ getreg32(SCU_EVENT_TIMESTAMP0_F_MSB + (i * 8));
+ notify->arg->ts.tick =
+ getreg32(SCU_EVENT_TIMESTAMP0_F_LSB + (i * 8));
+ notify->arg->type = SCU_EV_FALL;
+ }
+ detected = 1;
+#endif
+ }
+
+#ifndef CONFIG_DISABLE_SIGNAL
+ if (detected)
+ {
+ DEBUGASSERT(notify->pid != 0);
+
+# ifdef CONFIG_CAN_PASS_STRUCTS
+ union sigval value;
+ value.sival_ptr = notify->arg;
+ (void)sigqueue(notify->pid, notify->signo, value);
+# else
+ (void)sigqueue(notify->pid, notify->signo, (FAR void *)notify->arg);
+# endif
+ detected = 0;
+ }
+#endif
+ }
+}
+
+/****************************************************************************
+ * Name: seq_handleoneshot
+ *
+ * Description:
+ * Handle one shot sequencer done interrupt
+ *
+ ****************************************************************************/
+
+static void seq_handleoneshot(FAR struct cxd56_scudev_s *priv, uint32_t intr)
+{
+ uint32_t bit;
+ int i;
+
+ if ((intr & 0x07000000) == 0)
+ {
+ return;
+ }
+
+ for (i = 0, bit = 1 << 24; i < 3; i++, bit <<= 1)
+ {
+ if (intr & bit)
+ {
+ putreg32(bit, SCU_INT_CLEAR_MAIN);
+
+ seq_semgive(&priv->oneshotwait[i]);
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: seq_handleisopdoneintr
+ *
+ * Description:
+ * Handle interrupts response against request for SCU firmware
+ *
+ ****************************************************************************/
+
+static void seq_handleisopdoneintr(FAR struct cxd56_scudev_s *priv,
+ uint32_t intr)
+{
+ /* Detect ISOP3 as done or stop. */
+
+ if (intr & (1 << 27))
+ {
+ DEBUGASSERT(priv->currentreq != 0);
+
+ seq_inhibitrequest(priv->currentreq, false);
+
+ putreg32(1 << 27, SCU_INT_DISABLE_MAIN);
+ putreg32(1 << 27, SCU_INT_CLEAR_MAIN);
+
+ seq_semgive(&priv->syncwait);
+ }
+}
+
+/****************************************************************************
+ * Name: seq_scuirqhandler
+ *
+ * Description:
+ * Root interrupt handler for many SCU interrupts
+ *
+ ****************************************************************************/
+
+static int seq_scuirqhandler(int irq, FAR void *context, FAR void *arg)
+{
+ FAR struct cxd56_scudev_s *priv = arg;
+ uint32_t intr;
+ uint32_t ierr0;
+ uint32_t ierr1;
+ uint32_t ierr2;
+ int i;
+
+ intr = getreg32(SCU_INT_MASKED_STT_MAIN);
+ ierr0 = getreg32(SCU_INT_MASKED_STT_ERR_0);
+ ierr1 = getreg32(SCU_INT_MASKED_STT_ERR_1);
+ ierr2 = getreg32(SCU_INT_MASKED_STT_ERR_2);
+
+ seq_handlefifointr(priv, intr);
+
+ seq_handlemathfintr(priv, intr);
+
+ seq_handleoneshot(priv, intr);
+
+ seq_handleisopdoneintr(priv, intr);
+
+ /* Detect all FIFO overrun errors */
+
+ if (ierr0 != 0)
+ {
+ scuerr("err0: %08x\n", ierr0);
+ ierr0 = (ierr0 >> 9) & 0x3fff;
+ for (i = 0; i < 14; i++)
+ {
+ if ((ierr0 & (0x1 << i)) != 0)
+ {
+ /* Clear FIFO overrun error */
+
+ putreg32(getreg32(SCUFIFO_R_CTRL1(i)) | SCUFIFO_OVERRUNCLR,
+ SCUFIFO_R_CTRL1(i));
+ }
+ }
+ }
+
+ /**
+ * Detect all FIFO underrun errors
+ * This error may not happened because check reading bytes at seq_read().
+ * Thus, it is a program error when ERR1 detected.
+ */
+
+ if (ierr1 != 0)
+ {
+ scuerr("err1: %08x\n", ierr1);
+ ierr1 = (ierr1 >> 9) & 0x3fff;
+ for (i = 0; i < 14; i++)
+ {
+ if ((ierr1 & (0x1 << i)) != 0)
+ {
+ /* Clear FIFO underrun error */
+
+ putreg32(getreg32(SCUFIFO_R_CTRL1(i)) | SCUFIFO_UNDERRUNCLR,
+ SCUFIFO_R_CTRL1(i));
+ }
+ }
+ }
+
+ /* Detect sequencer error */
+
+ if (ierr2 != 0)
+ {
+ scuerr("err2: %08x\n", ierr2);
+ ierr2 &= 0x03ff;
+ for (i = 0; i < 10; i++)
+ {
+ if (ierr2 & (1 << i))
+ {
+ seq_stopseq(i);
+ }
+ }
+ putreg32(0x03ff, SCU_INT_CLEAR_ERR_2);
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: seq_new
+ *
+ * Description:
+ * Create new sequencer instance
+ *
+ * Returned Value:
+ * Created sequencer instance or NULL
+ *
+ ****************************************************************************/
+
+static FAR struct seq_s *seq_new(void)
+{
+ FAR struct seq_s *seq;
+ int sid;
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+ sid = seq_alloc();
+ if (sid < 0)
+ {
+ /* Sequencer is full */
+
+ leave_critical_section(flags);
+ return NULL;
+ }
+ leave_critical_section(flags);
+
+ seq = (FAR struct seq_s *)kmm_malloc(sizeof(struct seq_s));
+ if (!seq)
+ {
+ seq_free(sid);
+ return NULL;
+ }
+ memset(seq, 0, sizeof(struct seq_s));
+
+ seq->id = sid;
+
+ return seq;
+}
+
+/****************************************************************************
+ * Name: deci_new
+ *
+ * Description:
+ * Create new decimator instance
+ *
+ * Returned Value:
+ * Created decimator instance or NULL
+ *
+ ****************************************************************************/
+
+static FAR struct seq_s *deci_new(void)
+{
+ FAR struct decimator_s *deci;
+ int sid;
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+ sid = deci_alloc();
+ if (sid < 0)
+ {
+ /* Sequencer is full */
+
+ leave_critical_section(flags);
+ return NULL;
+ }
+ leave_critical_section(flags);
+
+ deci = (FAR struct decimator_s *)kmm_malloc(sizeof(struct decimator_s));
+ if (!deci)
+ {
+ deci_free(sid);
+ return NULL;
+ }
+ memset(deci, 0, sizeof(struct decimator_s));
+
+ deci->seq.id = sid;
+
+ return &deci->seq;
+}
+
+/****************************************************************************
+ * Name: seq_fifoinit
+ *
+ * Description:
+ * Initialize sequencer output FIFO
+ *
+ * Input Parameters:
+ * seq - Sequencer instance
+ * fifoid - FIFO ID (decimator only)
+ * fsize - Allocate FIFO memory size
+ *
+ ****************************************************************************/
+
+static int seq_fifoinit(FAR struct seq_s *seq, int fifoid, uint16_t fsize)
+{
+ FAR struct scufifo_s *fifo;
+ FAR struct decimator_s *deci = (FAR struct decimator_s *)seq;
+ int wid;
+ int rid;
+ uint32_t val;
+ uint32_t mask;
+ uint16_t start;
+ uint16_t samples;
+
+ DEBUGASSERT(seq);
+ DEBUGASSERT(fifoid >= 0 && fifoid < 3);
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ if (deci->dfifo[fifoid].fifo)
+ {
+ return OK;
+ }
+ }
+ else
+ {
+ if (seq->fifo)
+ {
+ /* FIFO already initialized */
+
+ return OK;
+ }
+ }
+
+ fifo = (FAR struct scufifo_s *)kmm_malloc(sizeof(struct scufifo_s));
+ if (!fifo)
+ {
+ return -ENOMEM;
+ }
+
+ memset(fifo, 0, sizeof(struct scufifo_s));
+
+ /* Setup FIFO, normal FIFO wid and rid are based on 8 and 4 respectively. */
+
+ start = scufifo_memalloc(fsize);
+ if (start == FIFOMEM_INVALID)
+ {
+ kmm_free(fifo);
+ return -ENOMEM;
+ }
+
+ /**
+ * FIFO IDs (* is unavailable)
+ * D = Decimation FIFO
+ * N = Normal FIFO
+ *
+ * sid wid name rid name
+ * 0 0 D0_W0*
+ * 1 D0_W1 0 D0_R1
+ * 2 D0_W2 1 D0_R2
+ * 3 D0_W3 12 D0_R3
+ * 1 4 D1_W0*
+ * 5 D1_W1 2 D1_R1
+ * 6 D1_W2 3 D1_R2
+ * 7 D1_W3 13 D1_R3
+ *
+ * 2 8 N0_W 4 N0_R1
+ * 3 9 N1_W 5 N0_R1
+ * 4 10 N2_W 6 N0_R1
+ * 5 11 N3_W 7 N0_R1
+ * 6 12 N4_W 8 N0_R1
+ * 7 13 N5_W 9 N0_R1
+ * 8 14 N6_W 10 N0_R1
+ * 9 15 N7_W 11 N0_R1
+ */
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ wid = fifoid + 1 + (seq->id * 4);
+ if (fifoid < 2)
+ {
+ rid = fifoid + (seq->id * 2);
+ }
+ else
+ {
+ rid = seq->id + 12;
+ }
+
+ if (!seq_isactive(seq))
+ {
+ /* Additionally, reset first stage of decimation logic
+ * when other decimator not used.
+ */
+
+ putreg32(1 << (seq->id * 4), SCU_DEC_CLR);
+ }
+
+ /* Reset decimator */
+
+ putreg32(1 << wid, SCU_DEC_CLR);
+ }
+ else
+ {
+ wid = seq->id + 6;
+ rid = seq->id + 2;
+ }
+
+ /* Set FIFO start offset and its size */
+
+ DEBUGASSERT(seq->sample);
+ samples = fsize / seq->sample;
+ putreg32((uint32_t)start << 16 | (samples - 1), SCUFIFO_W_CTRL0(wid));
+
+ /* Set 1 sample size and FIFO reset */
+
+ val = seq->sample - 1;
+ val |= (1 << 16);
+ putreg32(val, SCUFIFO_W_CTRL1(wid));
+
+ /* Set watermark */
+
+ putreg32(0xffff, SCUFIFO_R_CTRL0(rid));
+
+ /* Perform enable FIFO outlet, reset and clear error */
+
+ val = (1 << 24) | (1 << 16) | (1 << 8) | 3;
+ putreg32(val, SCUFIFO_R_CTRL1(rid));
+
+ /* Clear write event control */
+
+ putreg32(0, SCUSEQ_FIFOWREVNTCTRL(wid));
+
+ /* Save instance data */
+
+ fifo->start = start;
+ fifo->size = fsize;
+ fifo->wid = wid;
+ fifo->rid = rid;
+ fifo->mid = -1;
+
+#ifdef CONFIG_CXD56_UDMAC
+ /* Allocate DMA for read sensing data */
+
+ fifo->dma = cxd56_udmachannel();
+
+ /* Initialize DMA done wait semaphore */
+
+ sem_init(&fifo->dmawait, 0, 0);
+ fifo->dmaresult = -1;
+#endif
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ FAR struct decimation_fifo_s *dec = &deci->dfifo[fifoid];
+ dec->fifo = fifo;
+ dec->ratio = 0;
+ dec->leveladj = 0;
+ dec->forcethrough = 1;
+ }
+ else
+ {
+ seq->fifo = fifo;
+ }
+
+ if (seq->bustype & 0x10)
+ {
+ /* Set wid to ADC_PROPERTY */
+
+ mask = 0xf << (4 * (seq->bustype & 0x7));
+ val = getreg32(SCUSEQ_ADC_PROPERTY) & ~mask;
+ val |= (wid << (4 * (seq->bustype & 0x7)));
+ putreg32(val, SCUSEQ_ADC_PROPERTY);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: seq_fifofree
+ *
+ * Description:
+ * Free sequencer output FIFO
+ *
+ * Input Parameters:
+ * fifo - An instance of FIFO
+ *
+ ****************************************************************************/
+
+static void seq_fifofree(FAR struct scufifo_s *fifo)
+{
+ int wid;
+ int rid;
+ int mid;
+
+ if (!fifo)
+ {
+ return;
+ }
+
+#ifdef CONFIG_CXD56_UDMAC
+ /* Free DMA */
+
+ cxd56_udmafree(fifo->dma);
+#endif
+
+ wid = fifo->wid;
+ rid = fifo->rid;
+ mid = fifo->mid;
+
+ if (mid >= 0 && mid < 3)
+ {
+ putreg32(3, SCUSEQ_FIFOWREVNTCTRL(wid));
+ putreg32(0, SCU_EVENT_INTR_ENABLE(mid));
+ putreg32(0x9 << mid, SCU_FIFO_WRITE_CTRL);
+ putreg32(1 << mid, SCU_EVENT_STT);
+
+ putreg32((1 << (wid + 28)) | (1 << (wid + 6)), SCU_INT_DISABLE_MAIN);
+
+ mathf_disable(mid);
+ mathf_free(mid);
+ }
+
+ /* Disable watermark interrupt anyway */
+
+ putreg32(1 << (rid + 9), SCU_INT_DISABLE_MAIN);
+
+ /* Make sure want to be FIFO disabled */
+
+ putreg32(0, SCUFIFO_R_CTRL1(rid));
+
+ scufifo_memfree(fifo->start);
+
+#ifdef CONFIG_CXD56_UDMAC
+ sem_destroy(&fifo->dmawait);
+#endif
+
+ kmm_free(fifo);
+}
+
+/****************************************************************************
+ * Name: seq_getfifo
+ *
+ * Description:
+ * Utility for ease of obtaining FIFO instans from sequencer.
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * fifoid - FIFO ID (decimator only)
+ *
+ ****************************************************************************/
+
+static inline struct scufifo_s *seq_getfifo(FAR struct seq_s *seq, int fifoid)
+{
+ DEBUGASSERT(fifoid >= 0 && fifoid < 3);
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ struct decimator_s *deci = (struct decimator_s *)seq;
+ return deci->dfifo[fifoid].fifo;
+ }
+ else
+ {
+ return seq->fifo;
+ }
+}
+
+/****************************************************************************
+ * Name: seq_setadjustment
+ *
+ * Description:
+ * Set parameters for offset/gain adjustment, preprocessing of sequencer.
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * adj - offset/gain adjustment parameter by 3 axis
+ *
+ ****************************************************************************/
+
+static int seq_setadjustment(FAR struct seq_s *seq,
+ FAR struct adjust_xyz_s *adj)
+{
+ int sid;
+ uint32_t val;
+
+ DEBUGASSERT(seq);
+
+ /* offset/gain parameters can be set when sequencer not running */
+
+ if (seq_isactive(seq))
+ {
+ return -EBUSY;
+ }
+
+ sid = seq->id;
+
+ /* Set offset/gain adjustment parameters for each 3 axis data */
+
+ val = adj->x.offset | ((uint32_t)adj->x.gain << 16);
+ putreg32(val, SCUSEQ_MATH_PROC_OFST_GAIN_X(sid));
+
+ val = adj->y.offset | ((uint32_t)adj->y.gain << 16);
+ putreg32(val, SCUSEQ_MATH_PROC_OFST_GAIN_Y(sid));
+
+ val = adj->z.offset | ((uint32_t)adj->z.gain << 16);
+ putreg32(val, SCUSEQ_MATH_PROC_OFST_GAIN_Z(sid));
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: seq_setfilter
+ *
+ * Description:
+ * Set MATHFUNC IIR filter feature
+ *
+ * Input Paramters:
+ * fifo - An instance of FIFO
+ * pos - Where to IIR filter inserted
+ * iir - IIR filter coefficiencies
+ *
+ ****************************************************************************/
+
+static int seq_setfilter(FAR struct scufifo_s *fifo, int pos,
+ FAR struct iir_filter_s iir[2])
+{
+ int mid;
+
+ DEBUGASSERT(fifo);
+
+ if (fifo->mid < 0)
+ {
+ mid = mathf_alloc();
+ if (mid < 0)
+ {
+ return -ENOENT;
+ }
+
+ fifo->mid = mid;
+ mathf_enable(mid, fifo->wid);
+ }
+ else
+ {
+ mid = fifo->mid;
+ }
+
+ putreg32(pos, SCU_MATHFUNC_POS(mid));
+
+ mathf_setiirfilter(mid, 0, &iir[0]);
+ mathf_setiirfilter(mid, 1, &iir[1]);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: seq_seteventnotifier
+ *
+ * Description:
+ * Set event notifier
+ *
+ * Input Parameters:
+ * fifo - An instance of FIFO
+ * ev - Event notify setting
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success. A negated errno value is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static int seq_seteventnotifier(FAR struct scufifo_s *fifo,
+ FAR struct scuev_notify_s *ev)
+{
+ struct cxd56_scudev_s *priv = &g_scudev;
+ uint32_t val;
+ uint32_t thresh;
+ uint32_t count0;
+ uint32_t count1;
+ uint32_t delaysample;
+ int riseint;
+ int fallint;
+ int mid;
+#ifndef CONFIG_DISABLE_SIGNAL
+ irqstate_t flags;
+#endif
+
+ DEBUGASSERT(fifo && ev);
+
+ /* Math Function must be assigned first. */
+
+ if (fifo->mid < 0)
+ {
+ return -ENOENT;
+ }
+ mid = fifo->mid;
+
+#ifndef CONFIG_DISABLE_SIGNAL
+ /* Save signal number and target PID */
+
+ flags = enter_critical_section();
+ priv->event[mid].signo = ev->signo;
+ priv->event[mid].pid = getpid();
+ priv->event[mid].arg = ev->arg;
+ priv->event[mid].fifo = fifo;
+ leave_critical_section(flags);
+#endif
+
+ thresh = count0 = count1 = delaysample = 0;
+ riseint = fallint = 0;
+
+ thresh = ev->rise.threshold;
+ count0 = ev->rise.count0;
+ count1 = ev->rise.count1;
+ delaysample = ev->rise.delaysamples;
+
+ thresh |= ev->fall.threshold << 16;
+ count0 |= ev->fall.count0 << 16;
+ count1 |= ev->fall.count1 << 16;
+ delaysample |= ev->fall.delaysamples << 16;
+
+ if (ev->ctrl & SCU_EV_RISE_EN)
+ {
+ riseint = 1;
+ }
+
+ if (ev->ctrl & SCU_EV_FALL_EN)
+ {
+ fallint = 1;
+ }
+
+ putreg32(thresh, SCU_EVENT_PARAM_THRESH(mid));
+ putreg32(count0, SCU_EVENT_PARAM_COUNT0(mid));
+ putreg32(count1, SCU_EVENT_PARAM_COUNT1(mid));
+ putreg32(delaysample, SCU_EVENT_PARAM_DELAY_SAMPLE(mid));
+
+ /* Enable interrupt */
+
+ putreg32(fallint << 8 | riseint, SCU_EVENT_INTR_ENABLE(mid));
+
+ val = (ev->ctrl & SCU_EV_OUTMASK) >> SCU_EV_OUTSHIFT;
+ val |= (mid & 0x3) << 4;
+ val |= (ev->ctrl & SCU_EV_WRITESAMPLEMASK) << 8;
+ val |= ev->ctrl & SCU_EV_OUT8BITS ? 1 << 24 : 0;
+
+ putreg32(val, SCUSEQ_FIFOWREVNTCTRL(fifo->wid));
+
+ val = riseint << (mid + 6);
+ val |= fallint << (mid + 28);
+ putreg32(val, SCU_INT_ENABLE_MAIN);
+
+ putreg32(1 << mid, SCU_EVENT_STT);
+
+ return OK;
+}
+
+#ifndef CONFIG_DISABLE_SIGNAL
+
+/****************************************************************************
+ * Name: seq_setwatermark
+ *
+ * Description:
+ * Set watermark value for specified FIFO
+ *
+ ****************************************************************************/
+
+static int seq_setwatermark(FAR struct seq_s *seq, int fifoid,
+ FAR struct scufifo_wm_s *wm)
+{
+ FAR struct cxd56_scudev_s *priv = &g_scudev;
+ struct scufifo_s *fifo = seq_getfifo(seq, fifoid);
+ struct wm_notify_s *notify;
+ int rid;
+ irqstate_t flags;
+
+ DEBUGASSERT(fifo && wm);
+
+ if (wm->watermark == 0)
+ {
+ return -EINVAL;
+ }
+
+ rid = fifo->rid;
+
+ notify = &priv->wm[rid];
+
+ flags = enter_critical_section();
+ notify->signo = wm->signo;
+ notify->pid = getpid();
+ notify->ts = wm->ts;
+ notify->fifo = fifo;
+
+ /* Set watermark */
+
+ putreg32(wm->watermark, SCUFIFO_R_CTRL0(rid));
+
+ /* Enable FIFO almost full interrupt */
+
+ putreg32(1 << (rid + 9), SCU_INT_ENABLE_MAIN);
+
+ leave_critical_section(flags);
+
+ scuinfo("watermark = %04x, PID = %d, signo = %d\n", wm->watermark,
+ notify->pid, notify->signo);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: convert_firsttimestamp
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+static void convert_firsttimestamp(struct scutimestamp_s *tm,
+ uint16_t interval,
+ uint16_t sample, uint16_t adjust)
+{
+ uint32_t delta;
+ uint32_t tick;
+ uint16_t mod;
+
+ if (sample == 0 || interval == 0)
+ return;
+
+ mod = sample & 0x7;
+
+ if (adjust && mod)
+ {
+ delta = interval * (sample + (8 - mod));
+ if (adjust == 1)
+ {
+ if (mod <= 2)
+ {
+ delta -= 2;
+ }
+ else if (mod <= 5)
+ {
+ delta -= 1;
+ }
+ }
+ }
+ else
+ {
+ delta = interval * sample;
+ }
+
+ tick = tm->tick;
+ if (tick < delta)
+ {
+ tick += 0x80000000u - delta;
+ tm->tick = (tick & 0x00007fff);
+ tm->sec = tm->sec + (tick >> 15) - (0x80000000u >> 15);
+ }
+ else
+ {
+ tm->tick = tm->tick - delta;
+ }
+}
+
+/****************************************************************************
+ * Name: latest_timestamp
+ *
+ * Description:
+ * Get latest timestamp when data stored into FIFO.
+ *
+ ****************************************************************************/
+
+static void latest_timestamp(struct scufifo_s *fifo, uint32_t interval,
+ struct scutimestamp_s *tm, uint16_t *samples)
+{
+ struct scutimestamp_s pre;
+ struct scutimestamp_s post;
+ uint16_t pres;
+ uint16_t posts;
+ int rid = fifo->rid;
+ int wid = fifo->wid;
+
+ /* Get number of samples and timestamp twice for adapt roll over */
+
+ pres = getreg32(SCUFIFO_R_STATUS0(rid)) & 0xffff;
+ pre.sec = getreg32(SCUFIFO_W_TIMESTAMP0(wid));
+ pre.tick = getreg16(SCUFIFO_W_TIMESTAMP1(wid));
+
+ posts = getreg32(SCUFIFO_R_STATUS0(rid)) & 0xffff;
+ post.sec = getreg32(SCUFIFO_W_TIMESTAMP0(wid));
+ post.tick = getreg16(SCUFIFO_W_TIMESTAMP1(wid));
+
+ if (pres == posts)
+ {
+ *samples = pres;
+ tm->sec = pre.sec;
+ tm->tick = pre.tick;
+ }
+ else
+ {
+ *samples = posts;
+ tm->sec = post.sec;
+ tm->tick = post.tick;
+ if (tm->tick >= interval)
+ {
+ tm->tick -= interval;
+ }
+ else
+ {
+ tm->sec -= 1;
+ tm->tick += 0x8000 - interval;
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: gettimestamp
+ *
+ * Description:
+ * Get timestamp of head of FIFO sensing data.
+ *
+ ****************************************************************************/
+
+static void seq_gettimestamp(struct scufifo_s *fifo,
+ struct scutimestamp_s *tm)
+{
+ uint16_t sample;
+ uint16_t adjust = fifo->adjust;
+ uint32_t interval = fifo->interval;
+
+ latest_timestamp(fifo, interval, tm, &sample);
+
+ convert_firsttimestamp(tm, interval, sample, adjust);
+}
+#else
+#define seq_setwatermark(seq, fifoid, wm) (-ENOSYS)
+#endif
+
+/****************************************************************************
+ * Name: seq_setfifomode
+ *
+ * Description:
+ * Enable or disable FIFO overwrite mode.
+ *
+ ****************************************************************************/
+
+static void seq_setfifomode(FAR struct seq_s *seq, int fifoid, int enable)
+{
+ FAR struct scufifo_s *fifo = seq_getfifo(seq, fifoid);
+ uint32_t val;
+ irqstate_t flags;
+#ifndef CONFIG_DISABLE_SIGNAL
+ FAR struct cxd56_scudev_s *priv = &g_scudev;
+ FAR struct wm_notify_s *notify = &priv->wm[fifo->rid];
+ bool iswtmk = false;
+#endif
+
+ DEBUGASSERT(fifo);
+
+ scuinfo("FIFO mode %d wid %d\n", enable, fifo->wid);
+
+#ifndef CONFIG_DISABLE_SIGNAL
+ if (notify->ts)
+ {
+ iswtmk = true;
+ }
+#endif
+
+ flags = enter_critical_section();
+
+ /* control SCU FIFO overwrite */
+
+ val = getreg32(SCUFIFO_W_CTRL1(fifo->wid));
+ val &= ~(0x1 << 4);
+ if (enable)
+ {
+ val |= (0x1 << 4);
+ }
+ putreg32(val, SCUFIFO_W_CTRL1(fifo->wid));
+
+ if (enable)
+ {
+ /* disable overrun err interrupt */
+
+ val = 0x1 << (fifo->rid + 9);
+ putreg32(val, SCU_INT_DISABLE_ERR_0);
+
+#ifndef CONFIG_DISABLE_SIGNAL
+
+ /* disable almostfull interrupt */
+
+ if (iswtmk)
+ {
+ putreg32(val, SCU_INT_DISABLE_MAIN);
+ }
+#endif
+ }
+ else
+ {
+ /* clear overrun err */
+
+ putreg32(getreg32(SCUFIFO_R_CTRL1(fifo->rid)) | SCUFIFO_OVERRUNCLR,
+ SCUFIFO_R_CTRL1(fifo->rid));
+
+ /* enable overrun err interrupt */
+
+ val = 0x1 << (fifo->rid + 9);
+ putreg32(val, SCU_INT_ENABLE_ERR_0);
+
+#ifndef CONFIG_DISABLE_SIGNAL
+
+ /* enable almostfull interrupt */
+
+ if (iswtmk)
+ {
+ val = 0x1 << (fifo->rid + 9);
+ putreg32(val, SCU_INT_ENABLE_MAIN);
+ }
+#endif
+ }
+ leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: seq_remakeinstruction
+ *
+ * Description:
+ * Workaround for the sequencer last instruction issue.
+ * If the last instruction is i2c write, clear TERMINATE bit.
+ *
+ ****************************************************************************/
+
+static uint16_t seq_remakeinstruction(int bustype, uint16_t inst)
+{
+ uint16_t ret = inst;
+
+ if (bustype == SCU_BUS_I2C0 || bustype == SCU_BUS_I2C1)
+ {
+ /* When the instruction is write, clear TERMINATE bit */
+
+ if (!(ret & (1 << 8)))
+ {
+ ret &= ~SCU_INST_TERM;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: scu_hwinit
+ ****************************************************************************/
+
+static void scu_hwinit(void)
+{
+ int i;
+
+ /* Request don't sleep */
+
+ seq_inhibitrequest(REQ_SLEEP, true);
+
+ /* Disable all interrupts */
+
+ putreg32(0xffffffff, SCU_INT_DISABLE_MAIN);
+ putreg32(0xffffffff, SCU_INT_CLEAR_MAIN);
+ putreg32(0x0, SCU_LEVEL_SEL_MAIN);
+
+ for (i = 0; i < 10; i++)
+ {
+ putreg32(0x08000000, SCUSEQ_MATH_PROC_OFST_GAIN_X(i));
+ putreg32(0x08000000, SCUSEQ_MATH_PROC_OFST_GAIN_Y(i));
+ putreg32(0x08000000, SCUSEQ_MATH_PROC_OFST_GAIN_Z(i));
+ }
+ putreg32(0, SCU_OFST_GAIN_EN);
+
+ putreg32(0x0f0f0f00, SCU_DECIMATION_PARAM0);
+ putreg32(0x0f0f0f00, SCU_DECIMATION_PARAM1);
+ putreg32(0xff, SCU_DEC_CLR);
+
+ for (i = 0; i < 3; i++)
+ {
+ putreg32(0, SCU_EVENT_INTR_ENABLE(i));
+ }
+
+ /* Reset MATHFUNC */
+
+ putreg32(0, SCU_MATHFUNC_SEL);
+ putreg32(0x7, SCU_MATHFUNC_CLR);
+
+ /* Clear MATHFUNC EVENT... */
+
+ putreg32(0x3f, SCU_FIFO_WRITE_CTRL);
+ putreg32(0x7, SCU_EVENT_STT);
+
+ /* Reset all of FIFOs I/O */
+
+ for (i = 0; i < 16; i++)
+ {
+ putreg32(3, SCUSEQ_FIFOWREVNTCTRL(i));
+ putreg32(0, SCUFIFO_W_CTRL0(i));
+ putreg32(0x00010000, SCUFIFO_W_CTRL1(i));
+ putreg32(0, SCUFIFO_W_CTRL1(i));
+ }
+ for (i = 0; i < 14; i++)
+ {
+ putreg32(0x00010003, SCUFIFO_R_CTRL1(i));
+ putreg32(0, SCUFIFO_R_CTRL1(i));
+ }
+
+ /* Decimation FIFO selection.
+ * All of decimation FIFO I/O linked to each IDs.
+ */
+
+ putreg32(0x00e400e4, SCUFIFO_DECI_PARTITION_SEL);
+
+ /* Enable SPI and I2C[01] interrupts */
+
+ putreg32(7, SCU_INT_ENABLE_MAIN);
+
+ /* Wait for sequencer ready */
+
+ while (!(getreg32(SCU_SEQ_ENABLE_ALL) & 2));
+
+ putreg32(((CONFIG_CXD56_SCU_PREDIV - 1) << 8), SCU_START_CTRL_COMMON);
+
+ putreg32(1, SCU_SEQ_ENABLE_ALL);
+
+ /* Enable SCU sleep */
+
+ seq_inhibitrequest(REQ_SLEEP, false);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: scu_spitransfer
+ ****************************************************************************/
+
+int scu_spitransfer(int slavesel, FAR uint16_t *inst, uint32_t nr_insts,
+ FAR uint8_t *buffer, int len)
+{
+ return seq_oneshot(SCU_BUS_SPI, slavesel, inst, nr_insts, buffer, len);
+}
+
+/****************************************************************************
+ * Name: scu_i2ctransfer
+ ****************************************************************************/
+
+int scu_i2ctransfer(int port, int slave, FAR uint16_t *inst,
+ uint32_t nr_insts, FAR uint8_t *buffer, int len)
+{
+ int bustype;
+
+ if (port == 0)
+ {
+ bustype = SCU_BUS_I2C0;
+ }
+ else if (port == 1)
+ {
+ bustype = SCU_BUS_I2C1;
+ }
+ else
+ {
+ return -ENODEV;
+ }
+
+ return seq_oneshot(bustype, slave, inst, nr_insts, buffer, len);
+}
+
+/****************************************************************************
+ * Name: seq_open
+ *
+ * Description:
+ * Open sequencer. This API should be call from board initialize or from
+ * drivers.
+ *
+ * Input Parameters:
+ * type - A type of sequencer (SEQ_TYPE_NORMAL or SEQ_TYPE_DECI)
+ * bustype - A type of bus under SCU (SCU_BUS_I2C0, SCU_BUS_I2C1 or
+ * SCU_BUS_SPI)
+ *
+ ****************************************************************************/
+
+FAR struct seq_s *seq_open(int type, int bustype)
+{
+ FAR struct seq_s *seq;
+
+ if (type == SEQ_TYPE_DECI)
+ {
+ seq = deci_new();
+ }
+ else
+ {
+ seq = seq_new();
+ }
+ if (!seq)
+ {
+ return NULL;
+ }
+
+ seq->bustype = bustype;
+ seq->type = type;
+
+ seq_setbus(seq->id, bustype);
+
+ /* Disable all of data preprocessing */
+
+ seq_offsetgainenable(seq->id, false);
+ seq_setsignconversion(seq->id, 0);
+
+ return seq;
+}
+
+/****************************************************************************
+ * Name: seq_setinstruction
+ *
+ * Description:
+ * Set instruction set array for sequencer execution.
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * inst - Pointer of instruction array
+ * nr_insts - Number of instructions
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success. A negated errno value is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int seq_setinstruction(FAR struct seq_s *seq, const uint16_t *inst,
+ uint16_t nr_insts)
+{
+ int istart;
+ int i;
+ uint16_t lastinst;
+
+ if (nr_insts > INSTRUCTION_PER_SEQ)
+ {
+ return -EINVAL;
+ }
+
+ /* Remake last instruction, if needed. */
+
+ lastinst = seq_remakeinstruction(seq->bustype, *(inst + nr_insts - 1));
+
+ /* Copy cyclic running instruction */
+
+ istart = seq->id * INSTRUCTION_PER_SEQ;
+ for (i = 0; i < nr_insts - 1; i++)
+ {
+ putreg16(inst[i], SCUSEQ_INSTRUCTION(istart + i));
+ }
+ putreg16(lastinst, SCUSEQ_INSTRUCTION(istart + nr_insts - 1));
+
+ /* Set instruction parameters */
+
+ seq_setinst(seq->id, istart, nr_insts - 1);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: seq_setbytespersample
+ *
+ * Description:
+ * Set sample data format
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * sample - Size of sample (e.g. 16 bit 3 axis data = 6)
+ * offset - Start offset of sampling data
+ * elemsize - Size of 1 element (e.g. 16 bit 3 axis data = 2)
+ * swapbyte - Enable/Disable byte swapping if available
+ *
+ ****************************************************************************/
+
+void seq_setsample(FAR struct seq_s *seq, uint8_t sample, uint8_t offset,
+ uint8_t elemsize, bool swapbyte)
+{
+ DEBUGASSERT(seq);
+
+ seq->sample = sample;
+
+ seq_setdataformat(seq->id, offset, sample - 1, swapbyte ? 1 : 0, elemsize);
+}
+
+/****************************************************************************
+ * Name: seq_setaddress
+ *
+ * Description:
+ * Set slave ID or address
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * slave_addr - In SPI, slave select ID. In I2C, bus address.
+ *
+ ****************************************************************************/
+
+void seq_setaddress(FAR struct seq_s *seq, uint32_t slave_addr)
+{
+ seq_setproperty(seq->id, slave_addr, 0, 0, 0);
+}
+
+#ifdef CONFIG_CXD56_UDMAC
+/****************************************************************************
+ * Name: seq_fifodmadone
+ *
+ * Description:
+ * Callback function for receive DMA done
+ *
+ ****************************************************************************/
+
+static void seq_fifodmadone(DMA_HANDLE handle, uint8_t status, void *arg)
+{
+ struct scufifo_s *fifo = (struct scufifo_s *)arg;
+ fifo->dmaresult = status;
+ seq_semgive(&fifo->dmawait);
+}
+#else
+/****************************************************************************
+ * Name: seq_read8
+ ****************************************************************************/
+
+static inline void seq_read8(uint32_t addr, FAR uint8_t *buffer, int length)
+{
+ int i;
+
+ for (i = 0; i < length; i++)
+ {
+ *buffer++ = getreg8(addr);
+ }
+}
+
+/****************************************************************************
+ * Name: seq_read16
+ ****************************************************************************/
+
+static inline void seq_read16(uint32_t addr, FAR uint16_t *buffer, int length)
+{
+ int i;
+
+ for (i = 0; i < length / 2; i++)
+ {
+ *buffer++ = getreg16(addr);
+ }
+}
+
+/****************************************************************************
+ * Name: seq_read32
+ ****************************************************************************/
+
+static inline void seq_read32(uint32_t addr, FAR uint32_t *buffer, int length)
+{
+ int i;
+
+ for (i = 0; i < length / 4; i++)
+ {
+ *buffer++ = getreg32(addr);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: seq_read
+ *
+ * Description:
+ * Read sensor data from sequencer FIFO
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * fifoid - FIFO ID (decimator only)
+ * buffer - Pointer to data receive buffer
+ * length - Length of buffer
+ *
+ * Returned Value:
+ * Number of bytes of read data
+ *
+ ****************************************************************************/
+
+int seq_read(FAR struct seq_s *seq, int fifoid, FAR char *buffer, int length)
+{
+ struct scufifo_s *fifo;
+ uint32_t outlet;
+ int avail;
+#ifdef CONFIG_CXD56_UDMAC
+ dma_config_t config;
+ uint32_t dstbuf;
+ char *dst;
+ int maxlen = 1024;
+ int dmalen;
+ int rest;
+ int need_wakelock=0;
+ struct pm_cpu_wakelock_s wlock;
+ wlock.info = PM_CPUWAKELOCK_TAG('S', 'C', 0);
+ wlock.count = 0;
+#else
+ int i;
+#endif
+#ifdef CONFIG_CXD56_SCU_DEBUG
+ uint32_t status;
+#endif
+ DEBUGASSERT(seq);
+ DEBUGASSERT(fifoid >= 0 && fifoid < 3);
+
+ fifo = seq_getfifo(seq, fifoid);
+
+ DEBUGASSERT(fifo);
+
+ outlet = SCUFIFO_FIFO_DATA(fifo->rid);
+
+ avail = getreg32(SCUFIFO_R_STATUS0(fifo->rid));
+ scuinfo("Available %d samples\n", avail);
+#ifdef CONFIG_CXD56_SCU_DEBUG
+ status = getreg32(SCUFIFO_R_STATUS1(fifo->rid));
+ scuinfo("Status: %08x\n", status);
+#endif
+ avail *= seq->sample;
+ length = MIN(avail, length);
+ if (length == 0)
+ {
+ return 0;
+ }
+
+#ifdef CONFIG_CXD56_UDMAC
+ /* Get sensor data from FIFO by uDMAC (PL230) */
+ /* TODO: Check DMA transfer limit or restart DMA to get all data. */
+
+ config.channel_cfg = CXD56_UDMA_SINGLE;
+ if (buffer != NULL)
+ {
+ config.channel_cfg |= CXD56_UDMA_MEMINCR;
+ dst = buffer;
+ }
+ else
+ {
+ config.channel_cfg |= CXD56_UDMA_NOINCR;
+ dst = (char *)&dstbuf;
+ }
+
+ if (length & 1)
+ {
+ config.channel_cfg |= CXD56_UDMA_XFERSIZE_BYTE;
+ }
+ else if (length & 2)
+ {
+ config.channel_cfg |= CXD56_UDMA_XFERSIZE_HWORD;
+ maxlen = 2048;
+ }
+ else
+ {
+ config.channel_cfg |= CXD56_UDMA_XFERSIZE_WORD;
+ maxlen = 4096;
+ }
+ if (((uint32_t)dst >= CXD56_RAM_BASE)
+ && ((uint32_t)dst <= (CXD56_RAM_BASE + CXD56_RAM_SIZE)))
+ {
+ need_wakelock = 1;
+ up_pm_acquire_wakelock(&wlock);
+ }
+ rest = length;
+ while (rest > 0)
+ {
+ dmalen = MIN(rest, maxlen);
+ cxd56_rxudmasetup(fifo->dma, outlet, (uintptr_t)dst, dmalen, config);
+ cxd56_udmastart(fifo->dma, seq_fifodmadone, fifo);
+
+ /* Wait for DMA is done */
+
+ seq_semtake(&fifo->dmawait);
+ if (fifo->dmaresult)
+ {
+ /* ERROR */
+
+ length = length - rest;
+ break;
+ }
+ dst += dmalen;
+ rest -= dmalen;
+ }
+ if (need_wakelock)
+ {
+ up_pm_release_wakelock(&wlock);
+ }
+#else
+ /* Get sensor data from FIFO by PIO */
+
+ if (length & 1)
+ {
+ if (buffer != NULL)
+ {
+ seq_read8(outlet, (FAR uint8_t *)buffer, length);
+ }
+ else
+ {
+ for (i = 0; i < length; i++)
+ {
+ getreg8(outlet);
+ }
+ }
+ }
+ else if (length & 2)
+ {
+ if (buffer != NULL)
+ {
+ seq_read16(outlet, (FAR uint16_t *)buffer, length);
+ }
+ else
+ {
+ for (i = 0; i < length / 2; i++)
+ {
+ getreg16(outlet);
+ }
+ }
+ }
+ else
+ {
+ if (buffer != NULL)
+ {
+ seq_read32(outlet, (FAR uint32_t *)buffer, length);
+ }
+ else
+ {
+ for (i = 0; i < length / 4; i++)
+ {
+ getreg32(outlet);
+ }
+ }
+ }
+#endif
+
+ return length;
+}
+
+/****************************************************************************
+ * Name: seq_ioctl
+ *
+ * Description:
+ * Lower ioctl handler. SCU supported driver must call this API from it's
+ * ioctl().
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ * fifoid - FIFO ID (0 - 3, decimator only)
+ * cmd - SCU ioctl command (SCUIOC_*)
+ * arg - Arguments for cmd
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success. A negated errno value is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int seq_ioctl(FAR struct seq_s *seq, int fifoid, int cmd, unsigned long arg)
+{
+ int ret = OK;
+
+ if (fifoid < 0 || fifoid > 2)
+ {
+ set_errno(-EINVAL);
+ return -1;
+ }
+
+ scuinfo("cmd = %04x, arg = %08x\n", cmd, arg);
+
+ switch (cmd)
+ {
+ /* Set FIFO memory and initialize it. Arg: uint16_t */
+
+ case SCUIOC_SETFIFO:
+ {
+ ret = seq_fifoinit(seq, fifoid, (uint16_t)arg);
+ }
+ break;
+
+ /* Free FIFO memory. Arg: none */
+
+ case SCUIOC_FREEFIFO:
+ {
+ struct decimator_s *deci = (struct decimator_s *)seq;
+ FAR struct scufifo_s *fifo;
+
+ /* Check sequencer already stopped. */
+
+ if (seq_fifoisactive(seq, fifoid))
+ {
+ ret = -EBUSY;
+ break;
+ }
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ fifo = deci->dfifo[fifoid].fifo;
+ deci->dfifo[fifoid].fifo = NULL;
+ }
+ else
+ {
+ fifo = seq->fifo;
+ seq->fifo = NULL;
+ }
+ seq_fifofree(fifo);
+ }
+ break;
+
+ /* Set sampling rate. Arg: uint8_t */
+
+ case SCUIOC_SETSAMPLE:
+ {
+ ret = seq_setsamplingrate(seq, arg);
+ }
+ break;
+
+ /**
+ * Enable/disable sign conversion feature
+ * Arg: unsigned long, 0 = off, other = on
+ */
+
+ case SCUIOC_SETSIGNCONV:
+ {
+ seq_setsignconversion(seq->id, arg);
+ }
+ break;
+
+ /**
+ * Enable offset/gain adjustment preprocessing.
+ * Arg: Pointer of adjust_xyz_t
+ * If arg is null, just enable offset/gain (use current setting value).
+ */
+
+ case SCUIOC_SETOGADJUST:
+ {
+ if (arg)
+ {
+ FAR struct adjust_xyz_s *p =
+ (FAR struct adjust_xyz_s *)(uintptr_t)arg;
+ ret = seq_setadjustment(seq, p);
+ if (!ret)
+ {
+ seq_offsetgainenable(seq->id, true);
+ }
+ }
+ else
+ {
+ seq_offsetgainenable(seq->id, true);
+ }
+ }
+ break;
+
+ /**
+ * Disable offset/gain adjustment preprocessing.
+ * Arg: None
+ */
+
+ case SCUIOC_CLROGADJUST:
+ {
+ seq_offsetgainenable(seq->id, false);
+ }
+ break;
+
+ /**
+ * Set IIR filter position and coefficiencies.
+ * Arg: Pointer of struct math_filter_s
+ */
+
+ case SCUIOC_SETFILTER:
+ {
+ FAR struct math_filter_s *f =
+ (FAR struct math_filter_s *)(uintptr_t)arg;
+ FAR struct scufifo_s *fifo = seq_getfifo(seq, fifoid);
+
+ if (seq_fifoisactive(seq, fifoid))
+ {
+ ret = -EBUSY;
+ break;
+ }
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ FAR struct decimator_s *dec = (struct decimator_s *)seq;
+ fifo = dec->dfifo[fifoid].fifo;
+ }
+
+ ret = seq_setfilter(fifo, f->pos, f->filter);
+ }
+ break;
+
+ /**
+ * Set event notifier
+ * Arg: Pointer of struct scuev_notify_s
+ */
+
+ case SCUIOC_SETNOTIFY:
+ {
+ FAR struct scuev_notify_s *en =
+ (FAR struct scuev_notify_s *)(uintptr_t)arg;
+ FAR struct scufifo_s *fifo = seq_getfifo(seq, fifoid);
+
+ if (seq_fifoisactive(seq, fifoid))
+ {
+ ret = -EBUSY;
+ break;
+ }
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ FAR struct decimator_s *dec = (struct decimator_s *)seq;
+ fifo = dec->dfifo[fifoid].fifo;
+ }
+
+ ret = seq_seteventnotifier(fifo, en);
+ }
+ break;
+
+ /**
+ * Set number of elements per sample for mathfunc
+ * Arg: uint8_t
+ */
+
+ case SCUIOC_SETELEMENTS:
+ {
+ seq_setmathwritevecelenum(seq->id, (uint8_t)arg);
+ }
+ break;
+
+ /**
+ * Set decimation parameters
+ * Arg: Pointer of struct decimation_s
+ */
+
+ case SCUIOC_SETDECIMATION:
+ {
+ FAR struct decimation_s *d =
+ (FAR struct decimation_s *)(uintptr_t)arg;
+ FAR struct decimator_s *deci = (FAR struct decimator_s *)seq;
+ FAR struct decimation_fifo_s *dfifo = &deci->dfifo[fifoid];
+
+ if (!(seq->type & SEQ_TYPE_DECI))
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ /**
+ * Now only save decimation parameters because decimation parameter
+ * cannot be set while sequencer running.
+ */
+
+ dfifo->ratio = d->ratio;
+ dfifo->leveladj = d->leveladj;
+ dfifo->forcethrough = d->forcethrough;
+ }
+ break;
+
+ /**
+ * Set FIFO watermark
+ * Arg: Pointer of struct scufifo_wm_s
+ */
+
+ case SCUIOC_SETWATERMARK:
+ {
+ FAR struct scufifo_wm_s *wm =
+ (FAR struct scufifo_wm_s *)(uintptr_t)arg;
+
+ ret = seq_setwatermark(seq, fifoid, wm);
+ }
+ break;
+
+ /* Sequencer start */
+
+ case SCUIOC_START:
+ {
+ ret = seq_start(seq, fifoid);
+ }
+ break;
+
+ /* Sequencer stop */
+
+ case SCUIOC_STOP:
+ {
+ seq_stop(seq, fifoid);
+ }
+ break;
+
+ /* Set FIFO overwrite mode */
+
+ case SCUIOC_SETFIFOMODE:
+ {
+ seq_setfifomode(seq, fifoid, arg);
+ }
+ break;
+
+ /* Delete FIFO data */
+
+ case SCUIOC_DELFIFODATA:
+ {
+ ret = seq_read(seq, fifoid, NULL, (uint16_t)arg);
+ }
+ break;
+
+ default:
+ scuerr("Unrecognized cmd: %d\n", cmd);
+ ret = -EIO;
+ break;
+ }
+
+ if (ret < 0)
+ {
+ set_errno(-ret);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: seq_close
+ *
+ * Description:
+ * Close sequencer
+ *
+ * Input Parameters:
+ * seq - An instance of sequencer
+ *
+ ****************************************************************************/
+
+void seq_close(FAR struct seq_s *seq)
+{
+ irqstate_t flags;
+
+ DEBUGASSERT(seq);
+
+ if (seq->type & SEQ_TYPE_DECI)
+ {
+ FAR struct decimator_s *deci = (FAR struct decimator_s *)seq;
+ int i;
+
+ flags = enter_critical_section();
+ deci_free(seq->id);
+ leave_critical_section(flags);
+
+ for (i = 0; i < 3; i++)
+ {
+ seq_fifofree(deci->dfifo[i].fifo);
+ deci->dfifo[i].fifo = NULL;
+ }
+ }
+ else
+ {
+ flags = enter_critical_section();
+ seq_free(seq->id);
+ leave_critical_section(flags);
+
+ seq_fifofree(seq->fifo);
+ seq->fifo = NULL;
+ }
+
+ kmm_free(seq);
+}
+
+/****************************************************************************
+ * Name: scu_initialize
+ ****************************************************************************/
+
+void scu_initialize(void)
+{
+ struct cxd56_scudev_s *priv = &g_scudev;
+ int i;
+
+#ifdef CONFIG_CXD56_UDMAC
+ cxd56_udmainitialize();
+#endif
+
+ memset(priv, 0, sizeof(struct cxd56_scudev_s));
+
+ sem_init(&priv->syncwait, 0, 0);
+ sem_init(&priv->syncexc, 0, 1);
+
+ for (i = 0; i < 3; i++)
+ {
+ sem_init(&priv->oneshotwait[i], 0, 0);
+ }
+
+ scufifo_initialize();
+
+ /**
+ * If SCU clock has been already enabled, keep SCU running without loading
+ * and reset of SCU firmware.
+ */
+
+ if (false == cxd56_scuseq_clock_is_enabled())
+ {
+ /**
+ * Enable SCU clock. This process must do before loading firmware
+ * because SCU instruction RAM is not accessible.
+ */
+
+ cxd56_scuseq_clock_enable();
+
+ /* Load firmware & clear data RAM */
+
+ memcpy((void *)CXD56_SCU_SEQ_IRAM_BASE, scuIsopProgArray,
+ sizeOfscuIsopProgArray);
+ memset((void *)CXD56_SCU_SEQ_DRAM_BASE, 0, 0x324);
+
+ /* Release SCU reset to bring up SCU firmware */
+
+ cxd56_scuseq_release_reset();
+
+ /* Initialize SCU registers */
+
+ scu_hwinit();
+ }
+
+ /* Enable error interrupt */
+
+ putreg32(0x007ffe00, SCU_INT_ENABLE_ERR_0);
+ putreg32(0x03ff, SCU_INT_ENABLE_ERR_2);
+
+ /* Enable SCU IRQ */
+
+ irq_attach(CXD56_IRQ_SCU_3, seq_scuirqhandler, &g_scudev);
+ up_enable_irq(CXD56_IRQ_SCU_3);
+}
+
+/****************************************************************************
+ * Name: scu_uninitialize
+ ****************************************************************************/
+
+void scu_uninitialize(void)
+{
+ struct cxd56_scudev_s *priv = &g_scudev;
+ int i;
+
+ /* Request don't sleep */
+
+ seq_inhibitrequest(REQ_SLEEP, true);
+
+ up_disable_irq(CXD56_IRQ_SCU_3);
+
+ cxd56_scuseq_clock_disable();
+
+ sem_destroy(&priv->syncwait);
+ sem_destroy(&priv->syncexc);
+
+ for (i = 0; i < 3; i++)
+ {
+ sem_destroy(&priv->oneshotwait[i]);
+ }
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_scufifo.c b/arch/arm/src/cxd56xx/cxd56_scufifo.c
new file mode 100644
index 00000000000..8aa5c7110fa
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_scufifo.c
@@ -0,0 +1,214 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_scufifo.c
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * include files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include "chip.h"
+#include "up_arch.h"
+
+#include "cxd56_scufifo.h"
+#include "hardware/cxd56_scufifo.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define FIFOMEMSIZE 40960
+
+#define __unused __attribute__((unused))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct memchunk
+{
+ struct memchunk *next;
+ uint16_t start;
+ uint16_t size;
+};
+
+struct fifomem
+{
+ struct memchunk chunk[14];
+ struct memchunk *allocated;
+ struct memchunk *freelist;
+ uint16_t size;
+};
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+struct fifomem g_fifomem;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: fifomem_alloc
+ *
+ * Description:
+ * Allocate FIFO memory
+ *
+ ****************************************************************************/
+
+uint16_t scufifo_memalloc(uint16_t size)
+{
+ struct memchunk *c;
+ struct memchunk *last;
+ uint16_t start;
+
+ if (g_fifomem.size < size)
+ {
+ return FIFOMEM_INVALID;
+ }
+
+ if (g_fifomem.freelist == NULL)
+ {
+ return FIFOMEM_INVALID;
+ }
+
+ start = 0;
+ last = NULL;
+ for (c = g_fifomem.allocated; c; c = c->next)
+ {
+ start = c->start + c->size;
+ last = c;
+ if (c->next && c->next->start - start > size)
+ {
+ break;
+ }
+ }
+
+ if (start + size > g_fifomem.size)
+ {
+ return FIFOMEM_INVALID;
+ }
+
+ /* Remove from free list */
+
+ c = g_fifomem.freelist;
+ g_fifomem.freelist = c->next;
+
+ /* Append file chunk */
+
+ if (last == NULL)
+ {
+ g_fifomem.allocated = c;
+ c->next = NULL;
+ }
+ else
+ {
+ c->next = last->next;
+ last->next = c;
+ }
+
+ c->start = start;
+ c->size = size;
+
+ return start;
+}
+
+/****************************************************************************
+ * Name: scufifo_memfree
+ *
+ * Description:
+ * Free allocated FIFO memory
+ *
+ ****************************************************************************/
+
+void scufifo_memfree(uint16_t start)
+{
+ struct memchunk *c;
+ struct memchunk *prev;
+
+ prev = g_fifomem.allocated;
+ for (c = g_fifomem.allocated; c; c = c->next)
+ {
+ if (c->start == start)
+ {
+ if (g_fifomem.allocated == c)
+ {
+ g_fifomem.allocated = c->next;
+ }
+ else
+ {
+ prev->next = c->next;
+ }
+
+ c->next = g_fifomem.freelist;
+ g_fifomem.freelist = c;
+ break;
+ }
+ prev = c;
+ }
+}
+
+/****************************************************************************
+ * Name: scufifo_initialize
+ *
+ * Description:
+ * Initialize FIFO memory allocator
+ *
+ ****************************************************************************/
+
+void scufifo_initialize(void)
+{
+ struct memchunk *c;
+ int i;
+
+ g_fifomem.allocated = NULL;
+ g_fifomem.freelist = g_fifomem.chunk;
+ g_fifomem.size = FIFOMEMSIZE;
+
+ for (i = 1, c = g_fifomem.freelist; i < 14; i++, c = c->next)
+ {
+ c->size = 0;
+ c->next = &g_fifomem.chunk[i];
+ }
+ c->next = NULL;
+}
diff --git a/arch/arm/src/cxd56xx/cxd56_scufifo.h b/arch/arm/src/cxd56xx/cxd56_scufifo.h
new file mode 100644
index 00000000000..a4031693f3e
--- /dev/null
+++ b/arch/arm/src/cxd56xx/cxd56_scufifo.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+ * arch/arm/src/cxd56xx/cxd56_scufifo.h
+ *
+ * Copyright 2018 Sony Semiconductor Solutions Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sony Semiconductor Solutions Corporation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_SCUFIFO_H
+#define __ARCH_ARM_SRC_CXD56XX_CXD56_SCUFIFO_H
+
+/****************************************************************************
+ * include files
+ ****************************************************************************/
+
+#define FIFOMEM_INVALID 0xffff
+
+/****************************************************************************
+ * Name: scufifo_initialize
+ *
+ * Description:
+ * Initialize SCU FIFO memory management
+ *
+ ****************************************************************************/
+
+void scufifo_initialize(void);
+
+/****************************************************************************
+ * Name: scufifo_memalloc
+ *
+ * Description:
+ * Allocate SCU FIFO memory
+ *
+ * Input Parameters:
+ * size - Request memory size
+ *
+ * Returned Value:
+ * Allocated FIFO memory start offset. If error, return FIFOMEM_INVALID.
+ *
+ ****************************************************************************/
+
+uint16_t scufifo_memalloc(uint16_t size);
+
+/****************************************************************************
+ * Name: scufifo_memfree
+ *
+ * Description:
+ * Free allocated SCU FIFO memory
+ *
+ * Input Parameters:
+ * start - Start offset of FIFO memory
+ *
+ ****************************************************************************/
+
+void scufifo_memfree(uint16_t start);
+
+#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_SCUFIFO_H */
diff --git a/arch/arm/src/cxd56xx/cxd56_sdhci.c b/arch/arm/src/cxd56xx/cxd56_sdhci.c
index a8129144be2..ecc679f89eb 100644
--- a/arch/arm/src/cxd56xx/cxd56_sdhci.c
+++ b/arch/arm/src/cxd56xx/cxd56_sdhci.c
@@ -104,8 +104,8 @@
* the board.h file
*
* NOTE: These settings are not currently used. Since there are only four
- * frequencies, it makes more sense to just "can" the fixed frequency prescaler
- * and divider values.
+ * frequencies, it makes more sense to just "can" the fixed frequency
+ * prescaler and divider values.
*/
#ifndef CONFIG_CXD56_IDMODE_FREQ
@@ -259,6 +259,7 @@ struct sdio_softc_s
struct sdio_function_s
{
/* common members */
+
FAR struct sdio_softc_s *sc; /* card slot softc */
sdio_irqhandler_t *irq_callback; /* function callback */
int number; /* I/O function number or -1, 0 for func0,1 for func1... */
@@ -273,6 +274,7 @@ struct cxd56_sdiodev_s
struct sdio_dev_s dev; /* Standard, base SDIO interface */
/* CXD56xx-specific extensions */
+
/* Event support */
sem_t waitsem; /* Implements event waiting */
@@ -355,9 +357,11 @@ struct cxd56_sdhcregs_s
static void cxd56_takesem(struct cxd56_sdiodev_s *priv);
#define cxd56_givesem(priv) (sem_post(&(priv)->waitsem))
-static void cxd56_configwaitints(struct cxd56_sdiodev_s *priv, uint32_t waitints,
- sdio_eventset_t waitevents, sdio_eventset_t wkupevents);
-static void cxd56_configxfrints(struct cxd56_sdiodev_s *priv, uint32_t xfrints);
+static void cxd56_configwaitints(struct cxd56_sdiodev_s *priv,
+ uint32_t waitints, sdio_eventset_t waitevents,
+ sdio_eventset_t wkupevents);
+static void cxd56_configxfrints(struct cxd56_sdiodev_s *priv,
+ uint32_t xfrints);
/* DMA Helpers **************************************************************/
@@ -385,8 +389,10 @@ static void cxd56_datadisable(void);
static void cxd56_transmit(struct cxd56_sdiodev_s *priv);
static void cxd56_receive(struct cxd56_sdiodev_s *priv);
static void cxd56_eventtimeout(int argc, uint32_t arg);
-static void cxd56_endwait(struct cxd56_sdiodev_s *priv, sdio_eventset_t wkupevent);
-static void cxd56_endtransfer(struct cxd56_sdiodev_s *priv, sdio_eventset_t wkupevent);
+static void cxd56_endwait(struct cxd56_sdiodev_s *priv,
+ sdio_eventset_t wkupevent);
+static void cxd56_endtransfer(struct cxd56_sdiodev_s *priv,
+ sdio_eventset_t wkupevent);
/* Interrupt Handling *******************************************************/
@@ -413,12 +419,12 @@ static int cxd56_sdio_attach(FAR struct sdio_dev_s *dev);
/* Command/Status/Data Transfer */
-static int cxd56_sdio_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
- uint32_t arg);
-static void cxd56_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
- unsigned int nblocks);
-static int cxd56_sdio_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
- size_t nbytes);
+static int cxd56_sdio_sendcmd(FAR struct sdio_dev_s *dev,
+ uint32_t cmd, uint32_t arg);
+static void cxd56_blocksetup(FAR struct sdio_dev_s *dev,
+ unsigned int blocklen, unsigned int nblocks);
+static int cxd56_sdio_recvsetup(FAR struct sdio_dev_s *dev,
+ FAR uint8_t *buffer, size_t nbytes);
static int cxd56_sdio_sendsetup(FAR struct sdio_dev_s *dev,
FAR const uint8_t *buffer, uint32_t nbytes);
static int cxd56_sdio_cancel(FAR struct sdio_dev_s *dev);
@@ -435,8 +441,8 @@ static int cxd56_sdio_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
static void cxd56_sdio_waitenable(FAR struct sdio_dev_s *dev,
sdio_eventset_t eventset);
-static sdio_eventset_t
- cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
+static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev,
+ uint32_t timeout);
static void cxd56_sdio_callbackenable(FAR struct sdio_dev_s *dev,
sdio_eventset_t eventset);
static int cxd56_sdio_registercallback(FAR struct sdio_dev_s *dev,
@@ -456,19 +462,21 @@ static int cxd56_sdio_dmasendsetup(FAR struct sdio_dev_s *dev,
static int cxd56_sdio_enable_cardint(void);
static int cxd56_sdio_register_irq(FAR struct sdio_dev_s *dev, int func_num,
FAR sdio_irqhandler_t * handler);
-static int cxd56_sdio_function_disable(FAR struct sdio_dev_s *dev, int func_num);
-static int cxd56_sdio_function_enable(FAR struct sdio_dev_s *dev, int func_num);
+static int cxd56_sdio_function_disable(FAR struct sdio_dev_s *dev,
+ int func_num);
+static int cxd56_sdio_function_enable(FAR struct sdio_dev_s *dev,
+ int func_num);
static int cxd56_sdio_readb(FAR struct sdio_dev_s *dev, int func_num,
- uint32_t addr, FAR uint8_t * rdata);
+ uint32_t addr, FAR uint8_t * rdata);
static int cxd56_sdio_writeb(FAR struct sdio_dev_s *dev, int func_num,
- uint32_t addr, uint8_t data, FAR uint8_t * rdata);
-static int cxd56_sdio_read(FAR struct sdio_dev_s *dev, int func_num, uint32_t addr,
- FAR uint8_t * data, uint32_t size);
-static int cxd56_sdio_write(FAR struct sdio_dev_s *dev, int func_num, uint32_t addr,
- FAR uint8_t * data, uint32_t size);
+ uint32_t addr, uint8_t data, FAR uint8_t * rdata);
+static int cxd56_sdio_read(FAR struct sdio_dev_s *dev, int func_num,
+ uint32_t addr, FAR uint8_t * data, uint32_t size);
+static int cxd56_sdio_write(FAR struct sdio_dev_s *dev, int func_num,
+ uint32_t addr, FAR uint8_t * data, uint32_t size);
static int cxd56_sdhci_irq_handler(FAR struct sdio_dev_s *dev);
static int cxd56_sdio_get_cis(FAR struct sdio_dev_s *dev, int func_num,
- FAR struct sdio_cis_s * cis);
+ FAR struct sdio_cis_s * cis);
#endif /* CONFIG_CXD56_SDIO_ENABLE_MULTIFUNCTION */
/* Initialization/uninitialization/reset ************************************/
@@ -535,7 +543,7 @@ static struct cxd56_sdhcregs_s g_sampleregs[DEBUG_NSAMPLES];
/* DMA */
#ifdef CONFIG_SDIO_DMA
-static FAR uint32_t cxd56_sdhci_adma_dscr[CXD56_SDIO_MAX_LEN_ADMA_DSCR*2];
+static FAR uint32_t cxd56_sdhci_adma_dscr[CXD56_SDIO_MAX_LEN_ADMA_DSCR * 2];
#endif
/****************************************************************************
@@ -591,7 +599,8 @@ static void cxd56_takesem(struct cxd56_sdiodev_s *priv)
*
****************************************************************************/
-static void cxd56_configwaitints(struct cxd56_sdiodev_s *priv, uint32_t waitints,
+static void cxd56_configwaitints(struct cxd56_sdiodev_s *priv,
+ uint32_t waitints,
sdio_eventset_t waitevents,
sdio_eventset_t wkupevent)
{
@@ -628,12 +637,14 @@ static void cxd56_configwaitints(struct cxd56_sdiodev_s *priv, uint32_t waitints
*
****************************************************************************/
-static void cxd56_configxfrints(struct cxd56_sdiodev_s *priv, uint32_t xfrints)
+static void cxd56_configxfrints(struct cxd56_sdiodev_s *priv,
+ uint32_t xfrints)
{
irqstate_t flags;
flags = enter_critical_section();
priv->xfrints = xfrints;
- putreg32(priv->xfrints | priv->waitints | SDHCI_INT_CINT,CXD56_SDHCI_IRQSIGEN);
+ putreg32(priv->xfrints | priv->waitints | SDHCI_INT_CINT,
+ CXD56_SDHCI_IRQSIGEN);
leave_critical_section(flags);
}
@@ -652,7 +663,8 @@ static void cxd56_configxfrints(struct cxd56_sdiodev_s *priv, uint32_t xfrints)
#ifdef CONFIG_SDIO_XFRDEBUG
static void cxd56_sampleinit(void)
{
- memset(g_sampleregs, 0xff, DEBUG_NSAMPLES * sizeof(struct cxd56_sdhcregs_s));
+ memset(g_sampleregs, 0xff, DEBUG_NSAMPLES *
+ sizeof(struct cxd56_sdhcregs_s));
}
#endif
@@ -751,9 +763,12 @@ static void cxd56_dumpsample(struct cxd56_sdiodev_s *priv,
#ifdef CONFIG_SDIO_XFRDEBUG
static void cxd56_dumpsamples(struct cxd56_sdiodev_s *priv)
{
- cxd56_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP], "Before setup");
- cxd56_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP], "After setup");
- cxd56_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER], "End of transfer");
+ cxd56_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP],
+ "Before setup");
+ cxd56_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP],
+ "After setup");
+ cxd56_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER],
+ "End of transfer");
}
#endif
@@ -791,7 +806,6 @@ static void cxd56_dataconfig(struct cxd56_sdiodev_s *priv, bool bwrite,
unsigned int blocksize, unsigned int nblocks,
unsigned int timeout)
{
- //unsigned int watermark;
uint32_t regval = 0;
/* Set the data timeout value in the SDHCI_SYSCTL field to the selected value */
@@ -880,7 +894,8 @@ static void cxd56_transmit(struct cxd56_sdiodev_s *priv)
putreg32(SDHCI_INT_BWR, CXD56_SDHCI_IRQSTAT);
- while (priv->remaining > 0 && (getreg32(CXD56_SDHCI_PRSSTAT) & SDHCI_PRSSTAT_BWEN) != 0)
+ while (priv->remaining > 0 &&
+ (getreg32(CXD56_SDHCI_PRSSTAT) & SDHCI_PRSSTAT_BWEN) != 0)
{
/* Is there a full word remaining in the user buffer? */
@@ -964,7 +979,8 @@ static void cxd56_receive(struct cxd56_sdiodev_s *priv)
putreg32(SDHCI_INT_BRR, CXD56_SDHCI_IRQSTAT);
- while (priv->remaining > 0 && (getreg32(CXD56_SDHCI_PRSSTAT) & SDHCI_PRSSTAT_BREN) != 0)
+ while (priv->remaining > 0 &&
+ (getreg32(CXD56_SDHCI_PRSSTAT) & SDHCI_PRSSTAT_BREN) != 0)
{
/* Read the next word from the RX buffer */
@@ -994,7 +1010,6 @@ static void cxd56_receive(struct cxd56_sdiodev_s *priv)
}
}
}
-
}
/****************************************************************************
@@ -1056,7 +1071,8 @@ static void cxd56_eventtimeout(int argc, uint32_t arg)
*
****************************************************************************/
-static void cxd56_endwait(struct cxd56_sdiodev_s *priv, sdio_eventset_t wkupevent)
+static void cxd56_endwait(struct cxd56_sdiodev_s *priv,
+ sdio_eventset_t wkupevent)
{
/* Cancel the watchdog timeout */
@@ -1091,7 +1107,8 @@ static void cxd56_endwait(struct cxd56_sdiodev_s *priv, sdio_eventset_t wkupeven
*
****************************************************************************/
-static void cxd56_endtransfer(struct cxd56_sdiodev_s *priv, sdio_eventset_t wkupevent)
+static void cxd56_endtransfer(struct cxd56_sdiodev_s *priv,
+ sdio_eventset_t wkupevent)
{
#ifdef CONFIG_SDIO_DMA
uint32_t regval;
@@ -1130,7 +1147,8 @@ static void cxd56_endtransfer(struct cxd56_sdiodev_s *priv, sdio_eventset_t wkup
/* Mark the transfer finished */
- if ((priv->waitevents & wkupevent & (SDIOWAIT_TRANSFERDONE | SDIOWAIT_RESPONSEDONE)) == 0)
+ if ((priv->waitevents & wkupevent &
+ (SDIOWAIT_TRANSFERDONE | SDIOWAIT_RESPONSEDONE)) == 0)
{
priv->remaining = 0;
}
@@ -1193,8 +1211,6 @@ static int cxd56_interrupt(int irq, FAR void *context, FAR void *arg)
/* Clear all pending interrupts */
- //putreg32(enabled, CXD56_SDHCI_IRQSTAT);
-
/* Handle in progress, interrupt driven data transfers ********************/
pending = enabled & priv->xfrints;
@@ -1238,7 +1254,8 @@ static int cxd56_interrupt(int irq, FAR void *context, FAR void *arg)
{
/* Terminate the transfer with an error */
- mcerr("ERROR: Data block CRC failure, remaining: %d\n", priv->remaining);
+ mcerr("ERROR: Data block CRC failure, remaining: %d\n",
+ priv->remaining);
cxd56_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
}
@@ -1258,10 +1275,13 @@ static int cxd56_interrupt(int irq, FAR void *context, FAR void *arg)
{
/* Handle card interrupt events */
- putreg32(getreg32(CXD56_SDHCI_IRQSIGEN) & (~SDHCI_INT_CINT), CXD56_SDHCI_IRQSIGEN);
- putreg32(getreg32(CXD56_SDHCI_IRQSTATEN) & (~SDHCI_INT_CINT), CXD56_SDHCI_IRQSTATEN);
+ putreg32(getreg32(CXD56_SDHCI_IRQSIGEN) & (~SDHCI_INT_CINT),
+ CXD56_SDHCI_IRQSIGEN);
+ putreg32(getreg32(CXD56_SDHCI_IRQSTATEN) & (~SDHCI_INT_CINT),
+ CXD56_SDHCI_IRQSTATEN);
work_cancel(HPWORK, &priv->cbwork);
- (void)work_queue(HPWORK, &priv->cbwork, (worker_t)cxd56_sdhci_irq_handler, &priv->dev, 0);
+ (void)work_queue(HPWORK, &priv->cbwork,
+ (worker_t)cxd56_sdhci_irq_handler, &priv->dev, 0);
}
#endif /* CONFIG_CXD56_SDIO_ENABLE_MULTIFUNCTION */
@@ -1276,7 +1296,8 @@ static int cxd56_interrupt(int irq, FAR void *context, FAR void *arg)
{
/* Yes.. Is their a thread waiting for response done? */
- if ((priv->waitevents & (SDIOWAIT_CMDDONE | SDIOWAIT_RESPONSEDONE)) != 0)
+ if ((priv->waitevents &
+ (SDIOWAIT_CMDDONE | SDIOWAIT_RESPONSEDONE)) != 0)
{
/* Yes.. mask further interrupts and wake the thread up */
@@ -1396,6 +1417,7 @@ static void cxd56_sdio_sdhci_reset(FAR struct sdio_dev_s *dev)
*/
/* Reset state data */
+
sem_init(&priv->waitsem, 0, 1);
priv->waitwdog = wd_create();
DEBUGASSERT(priv->waitwdog);
@@ -1538,7 +1560,7 @@ static void cxd56_sdio_frequency(uint32_t frequency)
}
else
{
- for (i=1; i<0x3ff; i++)
+ for (i = 1; i < 0x3ff; i++)
{
if (baseclk / (2 * i) < frequency)
{
@@ -1551,12 +1573,15 @@ static void cxd56_sdio_frequency(uint32_t frequency)
regval = getreg32(CXD56_SDHCI_SYSCTL);
regval &= ~SDHCI_SYSCTL_GENSEL;
regval &= ~(SDHCI_SYSCTL_SDCLKFS_MASK | SDHCI_SYSCTL_SDCLKFSUP_MASK);
- regval |= (divisor << SDHCI_SYSCTL_SDCLKFS_SHIFT) & SDHCI_SYSCTL_SDCLKFS_MASK;
- regval |= ((divisor >> 8) << SDHCI_SYSCTL_SDCLKFSUP_SHIFT) & SDHCI_SYSCTL_SDCLKFSUP_MASK;
+ regval |= (divisor << SDHCI_SYSCTL_SDCLKFS_SHIFT) &
+ SDHCI_SYSCTL_SDCLKFS_MASK;
+ regval |= ((divisor >> 8) << SDHCI_SYSCTL_SDCLKFSUP_SHIFT) &
+ SDHCI_SYSCTL_SDCLKFSUP_MASK;
putreg32(regval, CXD56_SDHCI_SYSCTL);
}
-static void cxd56_sdio_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
+static void cxd56_sdio_clock(FAR struct sdio_dev_s *dev,
+ enum sdio_clock_e rate)
{
uint32_t regval;
uint32_t frequency = 0;
@@ -1574,7 +1599,8 @@ static void cxd56_sdio_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
mcinfo("SYSCTRL: %08x\n", getreg32(CXD56_SDHCI_SYSCTL));
/* sel_ttclk bit[16] */
- if (cxd56_get_sdio_baseclock() < 48*1000*1000)
+
+ if (cxd56_get_sdio_baseclock() < 48 * 1000 * 1000)
{
putreg32(getreg32(CXD56_SDHCI_USERDEF2CTL) | (0x1 << 16),
CXD56_SDHCI_USERDEF2CTL);
@@ -1586,13 +1612,17 @@ static void cxd56_sdio_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
}
/* HS_SYNC_RISE bit[16] */
+
putreg32(0x01010100, CXD56_SDHCI_OTHERIOLL);
/* sdclk_dly_sel */
+
if (rate <= CLOCK_SD_TRANSFER_4BIT)
- putreg32((getreg32(CXD56_SDHCI_USERDEF2CTL) & ~(0x7))| 0x1, CXD56_SDHCI_USERDEF2CTL);
+ putreg32((getreg32(CXD56_SDHCI_USERDEF2CTL) & ~(0x7)) | 0x1,
+ CXD56_SDHCI_USERDEF2CTL);
else
- putreg32((getreg32(CXD56_SDHCI_USERDEF2CTL) & ~(0x7))| 0x0, CXD56_SDHCI_USERDEF2CTL);
+ putreg32((getreg32(CXD56_SDHCI_USERDEF2CTL) & ~(0x7)) | 0x0,
+ CXD56_SDHCI_USERDEF2CTL);
/* Select the new prescaler and divisor values based on the requested mode
* and the settings from the board.h file.
@@ -1637,8 +1667,9 @@ static void cxd56_sdio_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
cxd56_sdio_frequency(frequency);
- putreg32(getreg32(CXD56_SDHCI_SYSCTL) | SDHCI_SYSCTL_ICLKEN, CXD56_SDHCI_SYSCTL);
- for (i=0;i<20;i++)
+ putreg32(getreg32(CXD56_SDHCI_SYSCTL) | SDHCI_SYSCTL_ICLKEN,
+ CXD56_SDHCI_SYSCTL);
+ for (i = 0; i < 20; i++)
{
up_mdelay(50);
regval = getreg32(CXD56_SDHCI_SYSCTL);
@@ -1651,7 +1682,7 @@ static void cxd56_sdio_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
{
putreg32(regval | SDHCI_SYSCTL_SDCLKEN, CXD56_SDHCI_SYSCTL);
}
- while((getreg32(CXD56_SDHCI_SYSCTL) & SDHCI_SYSCTL_SDCLKEN) == 0);
+ while ((getreg32(CXD56_SDHCI_SYSCTL) & SDHCI_SYSCTL_SDCLKEN) == 0);
mcinfo("SYSCTRL: %08x\n", getreg32(CXD56_SDHCI_SYSCTL));
}
@@ -1674,6 +1705,7 @@ static int cxd56_sdio_attach(FAR struct sdio_dev_s *dev)
int ret;
/* Attach the SDIO interrupt handler */
+
ret = irq_attach(CXD56_IRQ_SDIO, cxd56_interrupt, NULL);
if (ret == OK)
{
@@ -1716,7 +1748,8 @@ static int cxd56_sdio_attach(FAR struct sdio_dev_s *dev)
*
****************************************************************************/
-static int cxd56_sdio_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
+static int cxd56_sdio_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t arg)
{
#ifdef CONFIG_SDIO_DMA
struct cxd56_sdiodev_s *priv = (struct cxd56_sdiodev_s *)dev;
@@ -1816,7 +1849,9 @@ static int cxd56_sdio_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
/* Enable DMA */
#ifdef CONFIG_SDIO_DMA
+
/* Internal DMA is used */
+
priv->dmasend_prepare = false;
priv->dmasend_cmd = 0;
priv->dmasend_regcmd = 0;
@@ -1873,9 +1908,11 @@ static int cxd56_sdio_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
}
/* Set the SDHC Argument value */
+
putreg32(arg, CXD56_SDHCI_CMDARG);
/* Clear interrupt status and write the SDHC CMD */
+
putreg32(SDHCI_RESPDONE_INTS, CXD56_SDHCI_IRQSTAT);
#ifdef CONFIG_SDIO_DMA
priv->dma_cmd = cmd;
@@ -1908,8 +1945,8 @@ static int cxd56_sdio_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
*
****************************************************************************/
-static void cxd56_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
- unsigned int nblocks)
+static void cxd56_blocksetup(FAR struct sdio_dev_s *dev,
+ unsigned int blocklen, unsigned int nblocks)
{
struct cxd56_sdiodev_s *priv = (struct cxd56_sdiodev_s *)dev;
uint32_t regval;
@@ -1947,8 +1984,8 @@ static void cxd56_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
*
****************************************************************************/
-static int cxd56_sdio_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
- size_t nbytes)
+static int cxd56_sdio_recvsetup(FAR struct sdio_dev_s *dev,
+ FAR uint8_t *buffer, size_t nbytes)
{
struct cxd56_sdiodev_s *priv = (struct cxd56_sdiodev_s *)dev;
@@ -1985,10 +2022,11 @@ static int cxd56_sdio_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
* Name: cxd56_sdio_sendsetup
*
* Description:
- * Setup hardware in preparation for data transfer from the card. This method
- * will do whatever controller setup is necessary. This would be called
- * for SD memory just AFTER sending CMD24 (WRITE_BLOCK), CMD25
- * (WRITE_MULTIPLE_BLOCK), ... and before SDIO_SENDDATA is called.
+ * Setup hardware in preparation for data transfer from the card.
+ * This method will do whatever controller setup is necessary.
+ * This would be called for SD memory just AFTER sending
+ * CMD24 (WRITE_BLOCK), CMD25 (WRITE_MULTIPLE_BLOCK), ...
+ * and before SDIO_SENDDATA is called.
*
* Input Parameters:
* dev - An instance of the SDIO device interface
@@ -2000,8 +2038,8 @@ static int cxd56_sdio_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
*
****************************************************************************/
-static int cxd56_sdio_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer,
- size_t nbytes)
+static int cxd56_sdio_sendsetup(FAR struct sdio_dev_s *dev,
+ FAR const uint8_t *buffer, size_t nbytes)
{
struct cxd56_sdiodev_s *priv = (struct cxd56_sdiodev_s *)dev;
@@ -2058,6 +2096,7 @@ static int cxd56_sdio_cancel(FAR struct sdio_dev_s *dev)
#ifdef CONFIG_SDIO_DMA
/* Release allocated buffer */
+
if (priv->aligned_buffer)
{
/* Free aligned buffer */
@@ -2111,6 +2150,7 @@ static int cxd56_sdio_cancel(FAR struct sdio_dev_s *dev)
while ((getreg32(CXD56_SDHCI_SYSCTL) & SDHCI_SYSCTL_RSTD) != 0);
/* Mark no transfer in progress */
+
priv->remaining = 0;
return OK;
@@ -2188,7 +2228,7 @@ static int cxd56_sdio_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
{
mcerr("ERROR: Timeout cmd: %08x IRQSTAT: %08x\n",
cmd, getreg32(CXD56_SDHCI_IRQSTAT));
- putreg32(0,CXD56_SDHCI_IRQSIGEN);
+ putreg32(0, CXD56_SDHCI_IRQSIGEN);
return -ETIMEDOUT;
}
@@ -2204,10 +2244,11 @@ static int cxd56_sdio_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
}
/* Clear the response wait status bits */
+
if ((cmd & MMCSD_DATAXFR_MASK) == MMCSD_NODATAXFR)
{
- putreg32((SDHCI_INT_TC & getreg32(CXD56_SDHCI_IRQSTAT))| SDHCI_RESPDONE_INTS,
- CXD56_SDHCI_IRQSTAT);
+ putreg32((SDHCI_INT_TC & getreg32(CXD56_SDHCI_IRQSTAT)) |
+ SDHCI_RESPDONE_INTS, CXD56_SDHCI_IRQSTAT);
}
else
{
@@ -2325,7 +2366,8 @@ static int cxd56_sdio_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd,
return ret;
}
-static int cxd56_sdio_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t rlong[4])
+static int cxd56_sdio_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t rlong[4])
{
uint32_t regval;
int ret = OK;
@@ -2383,15 +2425,19 @@ static int cxd56_sdio_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_
}
if (1)
{
- rlong[0] = ((rlong[0] << 8) & 0xffffff00) | ((rlong[1] >> 24) & 0x000000FF);
- rlong[1] = ((rlong[1] << 8) & 0xffffff00) | ((rlong[2] >> 24) & 0x000000FF);
- rlong[2] = ((rlong[2] << 8) & 0xffffff00) | ((rlong[3] >> 24) & 0x000000FF);
+ rlong[0] = ((rlong[0] << 8) & 0xffffff00) |
+ ((rlong[1] >> 24) & 0x000000ff);
+ rlong[1] = ((rlong[1] << 8) & 0xffffff00) |
+ ((rlong[2] >> 24) & 0x000000ff);
+ rlong[2] = ((rlong[2] << 8) & 0xffffff00) |
+ ((rlong[3] >> 24) & 0x000000ff);
rlong[3] = (rlong[3] << 8) & 0xffffff00;
}
return ret;
}
-static int cxd56_sdio_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort)
+static int cxd56_sdio_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t *rshort)
{
uint32_t regval;
int ret = OK;
@@ -2409,7 +2455,8 @@ static int cxd56_sdio_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32
* 47 0 Start bit
* 46 0 Direction bit(0=card to host)
* 45:40 bit5 - bit0 Reserved
- * 39 1 Set to 1 if Card is ready to operate after initialization
+ * 39 1 Set to 1 if Card is
+ * ready to operate after initialization
* 38:36 bit2 - bit0 Number of I/O functions
* 35 1 Memory Present
* 34:32 bit2 - bit0 Stuff Bits
@@ -2433,7 +2480,9 @@ static int cxd56_sdio_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32
{
*rshort = 0;
}
+
/* Check that this is the correct response to this command */
+
#ifdef CONFIG_DEBUG_FEATURES
if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R3_RESPONSE &&
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R4_RESPONSE &&
@@ -2592,22 +2641,25 @@ static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev,
for (; ; )
{
- /* Wait for an event in event set to occur. If this the event has already
- * occurred, then the semaphore will already have been incremented and
+ /* Wait for an event in event set to occur.
+ * If this the event has already occurred,
+ * then the semaphore will already have been incremented and
* there will be no wait.
*/
cxd56_takesem(priv);
wkupevent = priv->wkupevent;
- /* Check if the event has occurred. When the event has occurred, then
- * evenset will be set to 0 and wkupevent will be set to a non-zero value.
+ /* Check if the event has occurred
+ * When the event has occurred, then evenset will be set to 0 and
+ * wkupevent will be set to a non-zero value.
*/
if (wkupevent != 0)
{
/* Yes... break out of the loop with wkupevent non-zero */
- if (wkupevent & ( SDIOWAIT_RESPONSEDONE | SDIOWAIT_TRANSFERDONE))
+
+ if (wkupevent & (SDIOWAIT_RESPONSEDONE | SDIOWAIT_TRANSFERDONE))
{
if (priv->remaining > 0)
{
@@ -2622,7 +2674,6 @@ static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev,
}
}
-
/* Disable event-related interrupts */
cxd56_configwaitints(priv, 0, 0, 0);
@@ -2634,7 +2685,8 @@ static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev,
{
/* Copy receive buffer from aligned address */
- memcpy(priv->receive_buffer, priv->aligned_buffer, priv->receive_size);
+ memcpy(priv->receive_buffer, priv->aligned_buffer,
+ priv->receive_size);
}
/* Free aligned buffer */
@@ -2743,32 +2795,35 @@ static int cxd56_sdio_admasetup(FAR const uint8_t *buffer, size_t buflen)
{
uint32_t dscr_top = (uint32_t)cxd56_sdhci_adma_dscr;
uint32_t dscr_l;
- uint32_t i, remaining, len;
+ uint32_t i;
+ uint32_t remaining;
+ uint32_t len;
uint32_t data_addr = (uint32_t)buffer;
remaining = buflen;
putreg32(0x0, CXD56_SDHCI_ADSADDR_H);
putreg32(dscr_top, CXD56_SDHCI_ADSADDR);
- for (i=0;i