This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 24e45d071e Pinephone Pro port just nsh
24e45d071e is described below

commit 24e45d071e6c56611ba866620a47af59b1e604e7
Author: Anner J. Bonilla <[email protected]>
AuthorDate: Fri Aug 11 09:12:26 2023 -0400

    Pinephone Pro port just nsh
    
    Pinephone Pro port just nsh
    
    Status:
    booting till GICD / IRQ issue
    
    style cleanups
    
    start to fix style checks
    
    revert offset
    
    whitespaces
    
    revert a64 bringup file
    
    prob last cleanup
    
    more cleanups
    
    remove dts
    
    move changes from a64 hardware specific folders to rk3399
    
    undo common changes (except head.s)
    
    revert gitignore
    
    missing irq.h and rk3399_serial.c need to finish cleaning them up
    
    WIP
    
    add source for load address
    
    make debug print hex again add board include
    
    Pinephone Pro port just nsh
    
    Status:
    booting till GICD / IRQ issue
    
    style cleanups
    
    start to fix style checks
    
    revert offset
    
    whitespaces
    
    revert a64 bringup file
    
    prob last cleanup
    
    more cleanups
    
    remove dts
    
    move changes from a64 hardware specific folders to rk3399
    
    undo common changes (except head.s)
    
    revert gitignore
    
    missing irq.h and rk3399_serial.c need to finish cleaning them up
    
    WIP
    
    add source for load address
    
    remove ccache, add board memory map
    
    remove board reset
---
 arch/arm64/Kconfig                                 |   15 +
 arch/arm64/include/rk3399/chip.h                   |   71 +
 arch/arm64/include/rk3399/irq.h                    |  168 +++
 arch/arm64/src/common/arm64_mmu.c                  |    2 +-
 arch/arm64/src/rk3399/Kconfig                      |   52 +
 arch/arm64/src/rk3399/Make.defs                    |   28 +
 arch/arm64/src/rk3399/chip.h                       |   42 +
 arch/arm64/src/rk3399/hardware/rk3399_memorymap.h  |   61 +
 arch/arm64/src/rk3399/rk3399_boot.c                |  130 ++
 arch/arm64/src/rk3399/rk3399_boot.h                |   77 ++
 arch/arm64/src/rk3399/rk3399_lowputc.S             |   90 ++
 arch/arm64/src/rk3399/rk3399_serial.c              | 1446 ++++++++++++++++++++
 arch/arm64/src/rk3399/rk3399_serial.h              |   69 +
 boards/Kconfig                                     |   12 +
 boards/arm64/rk3399/pinephonepro/Kconfig           |    7 +
 .../rk3399/pinephonepro/configs/nsh/defconfig      |   69 +
 boards/arm64/rk3399/pinephonepro/include/board.h   |   71 +
 .../rk3399/pinephonepro/include/board_memorymap.h  |   59 +
 boards/arm64/rk3399/pinephonepro/scripts/Make.defs |   48 +
 .../arm64/rk3399/pinephonepro/scripts/dramboot.ld  |  128 ++
 boards/arm64/rk3399/pinephonepro/src/Makefile      |   29 +
 .../arm64/rk3399/pinephonepro/src/pinephonepro.h   |   49 +
 .../rk3399/pinephonepro/src/pinephonepro_appinit.c |   73 +
 .../pinephonepro/src/pinephonepro_boardinit.c      |  106 ++
 .../rk3399/pinephonepro/src/pinephonepro_bringup.c |   63 +
 25 files changed, 2964 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 2321f7420f..6f0ce5711c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -36,6 +36,16 @@ config ARCH_CHIP_A64
        ---help---
                Allwinner A64 SoC
 
+config ARCH_CHIP_RK3399
+       bool "Rockchip RK3399"
+       select ARCH_CORTEX_A53
+       select ARCH_HAVE_ADDRENV
+       select ARCH_HAVE_RESET
+       select ARCH_HAVE_PSCI
+       select ARCH_NEED_ADDRENV_MAPPING
+       ---help---
+               Rockchip RK3399 SoC
+
 config ARCH_CHIP_QEMU
        bool "QEMU virt platform (ARMv8a)"
        select ARCH_HAVE_ADDRENV
@@ -190,6 +200,7 @@ config ARCH_FAMILY
 config ARCH_CHIP
        string
        default "a64"       if ARCH_CHIP_A64
+       default "rk3399"    if ARCH_CHIP_RK3399
        default "qemu"      if ARCH_CHIP_QEMU
        default "fvp-v8r"   if ARCH_CHIP_FVP_ARMV8R
        default "imx8"      if ARCH_CHIP_IMX8
@@ -251,6 +262,10 @@ if ARCH_CHIP_A64
 source "arch/arm64/src/a64/Kconfig"
 endif
 
+if ARCH_CHIP_RK3399
+source "arch/arm64/src/rk3399/Kconfig"
+endif
+
 if ARCH_CHIP_QEMU
 source "arch/arm64/src/qemu/Kconfig"
 endif
diff --git a/arch/arm64/include/rk3399/chip.h b/arch/arm64/include/rk3399/chip.h
new file mode 100644
index 0000000000..76ae29ce9a
--- /dev/null
+++ b/arch/arm64/include/rk3399/chip.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * arch/arm64/include/rk3399/chip.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM64_INCLUDE_RK3399_CHIP_H
+#define __ARCH_ARM64_INCLUDE_RK3399_CHIP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Number of bytes in @p x kibibytes/mebibytes/gibibytes */
+
+#define KB(x)           ((x) << 10)
+#define MB(x)           (KB(x) << 10)
+#define GB(x)           (MB(UINT64_C(x)) << 10)
+
+/* Rockchip A64 Generic Interrupt Controller v2: Distributor and Redist */
+
+#define CONFIG_GICD_BASE          0xfee00000
+#define CONFIG_GICR_BASE          0xfef00000 
+#define CONFIG_GICR_OFFSET        0x20000
+
+/* Rockchip RK3399 Memory Map: RAM and Device I/O */
+
+#define CONFIG_RAMBANK1_ADDR      0x02000000
+#define CONFIG_RAMBANK1_SIZE      MB(512)
+#define CONFIG_DEVICEIO_BASEADDR  0xF8000000
+#define CONFIG_DEVICEIO_SIZE      MB(128)
+
+/* U-Boot loads NuttX at this address (kernel_addr_r) */
+
+#define CONFIG_LOAD_BASE          0x02080000
+
+#define MPID_TO_CLUSTER_ID(mpid)  ((mpid) & ~0xff)
+/****************************************************************************
+ * Assembly Macros
+ ****************************************************************************/
+
+#ifdef __ASSEMBLY__
+
+.macro  get_cpu_id xreg0
+  mrs    \xreg0, mpidr_el1
+  ubfx   \xreg0, \xreg0, #0, #8
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM64_INCLUDE_RK3399_CHIP_H */
diff --git a/arch/arm64/include/rk3399/irq.h b/arch/arm64/include/rk3399/irq.h
new file mode 100644
index 0000000000..5022aa0593
--- /dev/null
+++ b/arch/arm64/include/rk3399/irq.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+ * arch/arm64/include/rk3399/irq.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directly but, rather,
+ * only indirectly through nuttx/irq.h
+ */
+
+#ifndef __ARCH_ARM64_INCLUDE_RK3399_IRQ_H
+#define __ARCH_ARM64_INCLUDE_RK3399_IRQ_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Rockchip RK3399 Interrupts */
+
+#define NR_IRQS                 181   /* Total number of interrupts */
+
+#define A64_IRQ_SGI0            (0)   /* 0x0000 SGI 0 interrupt */
+#define A64_IRQ_SGI1            (1)   /* 0x0004 SGI 1 interrupt */
+#define A64_IRQ_SGI2            (2)   /* 0x0008 SGI 2 interrupt */
+#define A64_IRQ_SGI3            (3)   /* 0x000C SGI 3 interrupt */
+#define A64_IRQ_SGI4            (4)   /* 0x0010 SGI 4 interrupt */
+#define A64_IRQ_SGI5            (5)   /* 0x0014 SGI 5 interrupt */
+#define A64_IRQ_SGI6            (6)   /* 0x0018 SGI 6 interrupt */
+#define A64_IRQ_SGI7            (7)   /* 0x001C SGI 7 interrupt */
+#define A64_IRQ_SGI8            (8)   /* 0x0020 SGI 8 interrupt */
+#define A64_IRQ_SGI9            (9)   /* 0x0024 SGI 9 interrupt */
+#define A64_IRQ_SGI10           (10)  /* 0x0028 SGI 10 interrupt */
+#define A64_IRQ_SGI11           (11)  /* 0x002C SGI 11 interrupt */
+#define A64_IRQ_SGI12           (12)  /* 0x0030 SGI 12 interrupt */
+#define A64_IRQ_SGI13           (13)  /* 0x0034 SGI 13 interrupt */
+#define A64_IRQ_SGI14           (14)  /* 0x0038 SGI 14 interrupt */
+#define A64_IRQ_SGI15           (15)  /* 0x003C SGI 15 interrupt */
+
+#define A64_IRQ_PPI0            (16)  /* 0x0040 PPI 0 interrupt */
+#define A64_IRQ_PPI1            (17)  /* 0x0044 PPI 1 interrupt */
+#define A64_IRQ_PPI2            (18)  /* 0x0048 PPI 2 interrupt */
+#define A64_IRQ_PPI3            (19)  /* 0x004C PPI 3 interrupt */
+#define A64_IRQ_PPI4            (20)  /* 0x0050 PPI 4 interrupt */
+#define A64_IRQ_PPI5            (21)  /* 0x0054 PPI 5 interrupt */
+#define A64_IRQ_PPI6            (22)  /* 0x0058 PPI 6 interrupt from ncommirq 
*/
+#define A64_IRQ_PPI7            (23)  /* 0x005C PPI 7 interrupt from npmuirq*/
+#define A64_IRQ_PPI8            (24)  /* 0x0060 PPI 8 interrupt from 
nctiirqack*/
+#define A64_IRQ_PPI9            (25)  /* 0x0064 PPI 9 interrupt from 
nvcpumntirq*/
+#define A64_IRQ_PPI10           (26)  /* 0x0068 PPI 10 interrupt from 
ncnthpirq*/
+#define A64_IRQ_PPI11           (27)  /* 0x006C PPI 11 interrupt from 
ncntvirq*/
+#define A64_IRQ_PPI12           (28)  /* 0x0070 PPI 12 interrupt */
+#define A64_IRQ_PPI13           (29)  /* 0x0074 PPI 13 interrupt from 
ncntpsirq*/
+#define A64_IRQ_PPI14           (30)  /* 0x0078 PPI 14 interrupt from 
ncntpnsirq */
+#define A64_IRQ_PPI15           (31)  /* 0x007C PPI 15 interrupt */
+
+#define A64_IRQ_TWI0            (38)  /* 0x0098 TWI 0 interrupt */
+#define A64_IRQ_TWI1            (39)  /* 0x009C TWI 1 interrupt */
+#define A64_IRQ_TWI2            (40)  /* 0x00A0 TWI 2 interrupt */
+
+#define A64_IRQ_PB_EINT         (43)  /* 0x00AC PB_EINT interrupt */
+#define A64_IRQ_OWA             (44)  /* 0x00B0 OWA interrupt */
+#define A64_IRQ_I2S_PCM0        (45)  /* 0x00B4 I2S/PCM-0 interrupt */
+#define A64_IRQ_I2S_PCM1        (46)  /* 0x00B8 I2S/PCM-1 interrupt */
+#define A64_IRQ_I2S_PCM2        (47)  /* 0x00BC I2S/PCM-2 interrupt */
+
+#define A64_IRQ_PG_EINT         (49)  /* 0x00C4 PG_EINT interrupt */
+#define A64_IRQ_TIMER0          (50)  /* 0x00C8 Timer 0 interrupt */
+#define A64_IRQ_TIMER1          (51)  /* 0x00CC Timer 1 interrupt */
+
+#define A64_IRQ_PH_EINT         (53)  /* 0x00C4 PH_EINT interrupt */
+
+#define A64_IRQ_AC_DET          (60)  /* 0x00F0 Audio Codec earphone detect 
interrupt */
+#define A64_IRQ_AUDIO_CODEC     (61)  /* 0x00F4 Audio Codec interrupt */
+#define A64_IRQ_KEYADC          (62)  /* 0x00F8 KEYADC interrupt */
+#define A64_IRQ_THERMAL_SENSOR  (63)  /* 0x00FC Thermal Sensor interrupt */
+#define A64_IRQ_EXTERNAL_NMI    (64)  /* 0x100 External Non-Mask Interrupt */
+#define A64_IRQ_R_TIMER0        (65)  /* 0x104 R_timer 0 interrupt */
+#define A64_IRQ_R_TIMER1        (66)  /* 0x108 R_timer 1 interrupt */
+
+#define A64_IRQ_R_WATCHDOG      (68)  /* 0x0110 R_watchdog interrupt */
+#define A64_IRQ_R_CIR_RX        (69)  /* 0x00E8 R_CIR_RX interrupt */
+#define A64_IRQ_R_UART          (70)  /* 0x0118 R_UART interrupt */
+#define A64_IRQ_R_RSB           (71)  /* 0x011C R_RSB interrupt */
+#define A64_IRQ_R_ALARM0        (72)  /* 0x0120 R_Alarm 0 interrupt */
+#define A64_IRQ_R_ALARM1        (73)  /* 0x0124 R_Alarm 1 interrupt */
+#define A64_IRQ_R_TIMER2        (74)  /* 0x0128 R_timer 2 interrupt */
+#define A64_IRQ_R_TIMER3        (75)  /* 0x012C R_timer 3 interrupt */
+#define A64_IRQ_R_TWI           (76)  /* 0x0130 R_TWI interrupt */
+#define A64_IRQ_R_PL_EINT       (77)  /* 0x0134 R_PL_EINT interrupt */
+#define A64_IRQ_R_TWD           (78)  /* 0x0138 R_TWD interrupt */
+
+#define A64_IRQ_MSGBOX          (81)  /* 0x0144 MSGBOX interrupt */
+#define A64_IRQ_DMA             (82)  /* 0x0148 DMA channel interrupt */
+#define A64_IRQ_HS_TIMER        (83)  /* 0x014C HS Timer interrupt */
+
+#define A64_IRQ_SD_MMC0         (92)  /* 0x0170 SD/MMC Host Controller 0 
interrupt */
+#define A64_IRQ_SD_MMC1         (93)  /* 0x0174 SD/MMC Host Controller 1 
interrupt */
+#define A64_IRQ_SD_MMC2         (94)  /* 0x0178 SD/MMC Host Controller 2 
interrupt */
+
+#define A64_IRQ_SPI0            (97)  /* 0x0184 SPI 0 interrupt */
+#define A64_IRQ_SPI1            (98)  /* 0x0188 SPI 1 interrupt */
+
+#define A64_IRQ_DRAM_MDFS       (101) /* 0x0194 DRAM MDFS interrupt */
+#define A64_IRQ_NAND            (102) /* 0x0198 NAND Flash Controller 
interrupt */
+#define A64_IRQ_USB_OTG         (103) /* 0x019C USB-OTG interrupt */
+#define A64_IRQ_USB_OTG_EHCI    (104) /* 0x01A0 USB-OTG-EHCI interrupt */
+#define A64_IRQ_USB_OTG_OHCI    (105) /* 0x01A4 USB-OTG-OHCI interrupt */
+#define A64_IRQ_USB_EHCI0       (106) /* 0x01A8 USB-EHCI0 interrupt */
+#define A64_IRQ_USB_OHCI0       (107) /* 0x01AC USB-OHCI0 interrupt */
+
+#define A64_IRQ_CE0             (112) /* 0x01C0 CE interrupt */
+#define A64_IRQ_TS              (113) /* 0x01C4 TS interrupt */
+#define A64_IRQ_EMAC            (114) /* 0x01C8 EMAC interrupt */
+#define A64_IRQ_SCR             (115) /* 0x01CC SCR interrupt */
+#define A64_IRQ_CSI             (116) /* 0x01D0 CSI interrupt */
+#define A64_IRQ_CSI_CCI         (117) /* 0x01D4 CSI_CCI interrupt */
+#define A64_IRQ_TCON0           (118) /* 0x01D8 TCON0 interrupt */
+#define A64_IRQ_TCON1           (119) /* 0x01DC TCON1 interrupt */
+#define A64_IRQ_HDMI            (120) /* 0x01E0 HDMI interrupt */
+#define A64_IRQ_MIPI_DSI        (121) /* 0x01E4 MIPI DSI interrupt */
+
+#define A64_IRQ_DIT             (125) /* 0x01F4 De-interlace interrupt */
+#define A64_IRQ_CE1             (126) /* 0x01F8 CE1 interrupt */
+#define A64_IRQ_DE              (127) /* 0x01FC DE interrupt */
+#define A64_IRQ_ROT             (128) /* 0x0200 DE_RORATE interrupt */
+#define A64_IRQ_GPU_GP          (129) /* 0x0204 GPU-GP interrupt */
+
+#define A64_IRQ_UART1           (130)  /* 0x0084 UART 1 interrupt */
+#define A64_IRQ_UART0           (131)  /* 0x0080 UART 0 interrupt */
+#define A64_IRQ_UART2           (132)  /* 0x0088 UART 2 interrupt */
+#define A64_IRQ_UART3           (133)  /* 0x008C UART 3 interrupt */
+#define A64_IRQ_UART4           (134)  /* 0x0090 UART 4 interrupt */
+
+#define A64_IRQ_GPU_PPMMU1      (135) /* 0x021C GPU-PPMMU1 interrupt */
+
+#define A64_IRQ_CTI0            (140) /* 0x0230 CTI0 interrupt */
+#define A64_IRQ_CTI1            (141) /* 0x0234 CTI1 interrupt */
+#define A64_IRQ_CTI2            (142) /* 0x0238 CTI2 interrupt */
+#define A64_IRQ_CTI3            (143) /* 0x023C CTI3 interrupt */
+#define A64_IRQ_COMMTX0         (144) /* 0x0240 COMMTX0 interrupt */
+#define A64_IRQ_COMMTX1         (145) /* 0x0244 COMMTX1 interrupt */
+#define A64_IRQ_COMMTX2         (146) /* 0x0248 COMMTX2 interrupt */
+#define A64_IRQ_COMMTX3         (147) /* 0x024C COMMTX3 interrupt */
+#define A64_IRQ_COMMRX0         (148) /* 0x0250 COMMRX0 interrupt */
+#define A64_IRQ_COMMRX1         (149) /* 0x0254 COMMRX1 interrupt */
+#define A64_IRQ_COMMRX2         (150) /* 0x0258 COMMRX2 interrupt */
+#define A64_IRQ_COMMRX3         (151) /* 0x025C COMMRX3 interrupt */
+#define A64_IRQ_PMU0            (152) /* 0x0260 PMU0 interrupt */
+#define A64_IRQ_PMU1            (153) /* 0x0264 PMU1 interrupt */
+#define A64_IRQ_PMU2            (154) /* 0x0268 PMU2 interrupt */
+#define A64_IRQ_PMU3            (155) /* 0x026C PMU3 interrupt */
+#define A64_IRQ_AXI_ERROR       (156) /* 0x0270 AXI_ERROR interrupt */
+
+#endif /* __ARCH_ARM64_INCLUDE_RK3399_IRQ_H */
diff --git a/arch/arm64/src/common/arm64_mmu.c 
b/arch/arm64/src/common/arm64_mmu.c
index 8121dcc5e1..18476049fe 100644
--- a/arch/arm64/src/common/arm64_mmu.c
+++ b/arch/arm64/src/common/arm64_mmu.c
@@ -426,7 +426,7 @@ static void init_xlat_tables(const struct arm_mmu_region 
*region)
   uint64_t level_size;
 
 #ifdef CONFIG_MMU_DEBUG
-  sinfo("mmap: virt %llx phys %llx size %llx\n", virt, phys, size);
+  sinfo("mmap: virt %lux phys %lux size %lux\n", virt, phys, size);
 #endif
 
   /* check minimum alignment requirement for given mmap region */
diff --git a/arch/arm64/src/rk3399/Kconfig b/arch/arm64/src/rk3399/Kconfig
new file mode 100644
index 0000000000..fcf218cf8b
--- /dev/null
+++ b/arch/arm64/src/rk3399/Kconfig
@@ -0,0 +1,52 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+if ARCH_CHIP_RK3399
+
+menu "Rockchip RK3399 Peripheral Selection"
+
+config RK3399_UART
+       bool "UART 0"
+       default n
+       select UART0_SERIALDRIVER
+       select ARCH_HAVE_SERIAL_TERMIOS
+       ---help---
+               Select to enable support for UART0.
+
+config RK3399_UART1
+       bool "UART 1"
+       default n
+       select UART1_SERIALDRIVER
+       select ARCH_HAVE_SERIAL_TERMIOS
+       ---help---
+               Select to enable support for UART1.
+
+config RK3399_UART2
+       bool "UART 2"
+       default y
+       select UART2_SERIALDRIVER
+       select ARCH_HAVE_SERIAL_TERMIOS
+       ---help---
+               Select to enable support for UART2.
+
+config RK3399_UART3
+       bool "UART 3"
+       default n
+       select UART3_SERIALDRIVER
+       select ARCH_HAVE_SERIAL_TERMIOS
+       ---help---
+               Select to enable support for UART3.
+
+config RK3399_UART4
+       bool "UART 4"
+       default n
+       select UART4_SERIALDRIVER
+       select ARCH_HAVE_SERIAL_TERMIOS
+       ---help---
+               Select to enable support for UART4.
+
+endmenu # Rockchip RK3399 Peripheral Selection
+
+endif # ARCH_CHIP_RK3399
diff --git a/arch/arm64/src/rk3399/Make.defs b/arch/arm64/src/rk3399/Make.defs
new file mode 100644
index 0000000000..ceb41df155
--- /dev/null
+++ b/arch/arm64/src/rk3399/Make.defs
@@ -0,0 +1,28 @@
+############################################################################
+# arch/arm64/src/rk3399/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include common/Make.defs
+
+# Rockchip RK3399 specific C source files
+CHIP_CSRCS  = rk3399_boot.c rk3399_serial.c
+
+ifeq ($(CONFIG_ARCH_EARLY_PRINT),y)
+CHIP_ASRCS  = rk3399_lowputc.S
+endif
diff --git a/arch/arm64/src/rk3399/chip.h b/arch/arm64/src/rk3399/chip.h
new file mode 100644
index 0000000000..5e87cb8ca3
--- /dev/null
+++ b/arch/arm64/src/rk3399/chip.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ * arch/arm64/src/rk3399/chip.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM64_SRC_RK3399_CHIP_H
+#define __ARCH_ARM64_SRC_RK3399_CHIP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifndef __ASSEMBLY__
+#  include <nuttx/arch.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Macro Definitions
+ ****************************************************************************/
+
+#endif /* __ARCH_ARM64_SRC_RK3399_CHIP_H */
diff --git a/arch/arm64/src/rk3399/hardware/rk3399_memorymap.h 
b/arch/arm64/src/rk3399/hardware/rk3399_memorymap.h
new file mode 100644
index 0000000000..a147438552
--- /dev/null
+++ b/arch/arm64/src/rk3399/hardware/rk3399_memorymap.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+ * arch/arm64/src/rk3399/hardware/rk3399_memorymap.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM64_SRC_RK3399_HARDWARE_RK3399_MEMORYMAP_H
+#define __ARCH_ARM64_SRC_RK3399_HARDWARE_RK3399_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Peripheral Base Addresses */
+#define RK3399_GPIO0_ADDR        0xff720000
+#define RK3399_GPIO1_ADDR        0xff730000
+#define RK3399_GPIO2_ADDR        0xff780000
+#define RK3399_GPIO3_ADDR        0xff788000
+#define RK3399_GPIO4_ADDR        0xff790000
+
+#define RK3399_PIO_ADDR        RK3399_GPIO0_ADDR
+#define RK3399_PWM_ADDR        0xff430000
+#define RK3399_UART0_ADDR      0xff180000
+#define RK3399_UART1_ADDR      0xff190000
+#define RK3399_UART2_ADDR      0xff1a0000
+#define RK3399_UART3_ADDR      0xff1b0000
+#define RK3399_UART4_ADDR      0xff370000
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+#endif /* __ARCH_ARM64_SRC_RK3399_HARDWARE_RK3399_MEMORYMAP_H */
diff --git a/arch/arm64/src/rk3399/rk3399_boot.c 
b/arch/arm64/src/rk3399/rk3399_boot.c
new file mode 100644
index 0000000000..85cdb6f8ba
--- /dev/null
+++ b/arch/arm64/src/rk3399/rk3399_boot.c
@@ -0,0 +1,130 @@
+/****************************************************************************
+ * arch/arm64/src/rk3399/rk3399_boot.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/cache.h>
+#ifdef CONFIG_PAGING
+#  include <nuttx/page.h>
+#endif
+
+#include <arch/chip/chip.h>
+
+#ifdef CONFIG_SMP
+#include "arm64_smp.h"
+#endif
+
+#include "arm64_arch.h"
+#include "arm64_internal.h"
+#include "arm64_mmu.h"
+#include "rk3399_boot.h"
+#include "rk3399_serial.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct arm_mmu_region g_mmu_regions[] =
+{
+  MMU_REGION_FLAT_ENTRY("DEVICE_REGION",
+                        CONFIG_DEVICEIO_BASEADDR, CONFIG_DEVICEIO_SIZE,
+                        MT_DEVICE_NGNRNE | MT_RW | MT_SECURE),
+
+  MMU_REGION_FLAT_ENTRY("DRAM0_S0",
+                        CONFIG_RAMBANK1_ADDR, CONFIG_RAMBANK1_SIZE,
+                        MT_NORMAL | MT_RW | MT_SECURE),
+};
+
+const struct arm_mmu_config g_mmu_config =
+{
+  .num_regions = nitems(g_mmu_regions),
+  .mmu_regions = g_mmu_regions,
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: arm64_el_init
+ *
+ * Description:
+ *   The function called from arm64_head.S at very early stage for these
+ * platform, it's use to:
+ *   - Handling special hardware initialize routine which is need to
+ *     run at high ELs
+ *   - Initialize system software such as hypervisor or security firmware
+ *     which is need to run at high ELs
+ *
+ ****************************************************************************/
+
+void arm64_el_init(void)
+{
+  /* TODO: RK3399 set init sys clock */
+}
+
+/****************************************************************************
+ * Name: arm64_chip_boot
+ *
+ * Description:
+ *   Complete boot operations started in arm64_head.S
+ *
+ ****************************************************************************/
+
+void arm64_chip_boot(void)
+{
+  /* MAP IO and DRAM, enable MMU. */
+
+  arm64_mmu_init(true);
+
+#if defined(CONFIG_SMP) || defined(CONFIG_ARCH_HAVE_PSCI)
+  arm64_psci_init("smc");
+
+#endif
+
+  /* Perform board-specific device initialization. This would include
+   * configuration of board specific resources such as GPIOs, LEDs, etc.
+   */
+
+  rk3399_board_initialize();
+
+#ifdef USE_EARLYSERIALINIT
+  /* Perform early serial initialization if we are going to use the serial
+   * driver.
+   */
+
+  arm64_earlyserialinit();
+#endif
+}
+
+#if defined(CONFIG_NET) && !defined(CONFIG_NETDEV_LATEINIT)
+void arm64_netinitialize(void)
+{
+  /* TODO: Support net initialize */
+}
+#endif
diff --git a/arch/arm64/src/rk3399/rk3399_boot.h 
b/arch/arm64/src/rk3399/rk3399_boot.h
new file mode 100644
index 0000000000..56fd2f1b95
--- /dev/null
+++ b/arch/arm64/src/rk3399/rk3399_boot.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+ * arch/arm64/src/rk3399/rk3399_boot.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM64_SRC_RK3399_RK3399_BOOT_H
+#define __ARCH_ARM64_SRC_RK3399_RK3399_BOOT_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <arch/chip/chip.h>
+#include "arm64_internal.h"
+#include "arm64_arch.h"
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: rk3399_board_initialize
+ *
+ * Description:
+ *   All rk3399 architectures must provide the following entry point.  This
+ *   entry point is called in the initialization phase -- after
+ *   a64_memory_initialize and after all memory has been configured and
+ *   mapped but before any devices have been initialized.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void rk3399_board_initialize(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM64_SRC_RK3399_RK3399_BOOT_H */
diff --git a/arch/arm64/src/rk3399/rk3399_lowputc.S 
b/arch/arm64/src/rk3399/rk3399_lowputc.S
new file mode 100644
index 0000000000..07731122af
--- /dev/null
+++ b/arch/arm64/src/rk3399/rk3399_lowputc.S
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * arch/arm64/src/rk3399/rk3399_lowputc.S
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************
+ *
+ *    DESCRIPTION
+ *       Low-level console output for Rockchip RK3399
+ *
+ ***************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "arm64_macro.inc"
+
+/****************************************************************************
+ * Public Symbols
+ ****************************************************************************/
+
+    .file    "rk3399_lowputc.S"
+
+/****************************************************************************
+ * Assembly Macros
+ ****************************************************************************/
+
+ /* Rockchip RK3399 UART0 Base Address */
+#define UART2_BASE_ADDRESS 0xFF1A0000
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* Initialize A64 UART
+ * xb: Register that contains the UART Base Address
+ * c:  Scratch register number
+ */
+
+GTEXT(arm64_earlyprintinit)
+SECTION_FUNC(text, arm64_earlyprintinit)
+    ret  /* Do nothing because U-Boot has already initialized UART */
+
+/* Wait for RK3399 UART to be ready to transmit
+ * xb: Register that contains the UART Base Address
+ * wt: Scratch register number
+ */
+
+.macro early_uart_ready xb, wt
+1:
+    ldrh  \wt, [\xb, #0x14]      /* UART_LSR (Line Status Register) */
+    tst   \wt, #0x20             /* Check THRE (TX Holding Register Empty) */
+    b.eq  1b                     /* Wait for the UART to be ready (THRE=1) */
+.endm
+
+/* Transmit character to RK3399 UART
+ * xb: Register that contains the UART base address
+ * wt: Register that contains the character to transmit
+ */
+
+.macro early_uart_transmit xb, wt
+    strb  \wt, [\xb]             /* UART_THR (Transmit Holding Register) */
+.endm
+
+/* Print a character on the UART - this function is called by C
+ * x0: Character to print
+ */
+
+GTEXT(arm64_lowputc)
+SECTION_FUNC(text, arm64_lowputc)
+    ldr   x15, =UART2_BASE_ADDRESS
+    early_uart_ready x15, w2
+    early_uart_transmit x15, w0
+    ret
diff --git a/arch/arm64/src/rk3399/rk3399_serial.c 
b/arch/arm64/src/rk3399/rk3399_serial.c
new file mode 100644
index 0000000000..117c920f15
--- /dev/null
+++ b/arch/arm64/src/rk3399/rk3399_serial.c
@@ -0,0 +1,1446 @@
+/***************************************************************************
+ * arch/arm64/src/rk3399/rk3399_serial.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ***************************************************************************/
+
+/* Reference:
+ *
+ * "NuttX RTOS for PinePhone: UART Driver"
+ * https://lupyuen.github.io/articles/serial
+ *
+ * "A64 Page" refers to Allwinner A64 User Manual
+ * https://lupyuen.github.io/images/Allwinner_A64_User_Manual_V1.1.pdf
+ */
+
+/***************************************************************************
+ * Included Files
+ ***************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#ifdef CONFIG_SERIAL_TERMIOS
+#  include <termios.h>
+#endif
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/spinlock.h>
+#include <nuttx/init.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/serial/serial.h>
+
+#include "arm64_arch.h"
+#include "arm64_internal.h"
+#include "rk3399_serial.h"
+#include "arm64_arch_timer.h"
+#include "rk3399_boot.h"
+#include "arm64_gic.h"
+
+#ifdef USE_SERIALDRIVER
+
+/***************************************************************************
+ * Pre-processor Definitions
+ ***************************************************************************/
+
+/* UART0 Settings should be same as U-Boot Bootloader */
+
+#ifndef CONFIG_UART0_BAUD
+#  define CONFIG_UART0_BAUD 115200
+#endif
+
+#ifndef CONFIG_UART0_BITS
+#  define CONFIG_UART0_BITS 8
+#endif
+
+#ifndef CONFIG_UART0_PARITY
+#  define CONFIG_UART0_PARITY 0
+#endif
+
+#ifndef CONFIG_UART0_2STOP
+#  define CONFIG_UART0_2STOP 0
+#endif
+
+#ifndef CONFIG_UART0_RXBUFSIZE
+#  define CONFIG_UART0_RXBUFSIZE 256
+#endif
+
+#ifndef CONFIG_UART0_TXBUFSIZE
+#  define CONFIG_UART0_TXBUFSIZE 256
+#endif
+
+/* UART2 is console and ttys0, follows U-Boot Bootloader */
+
+#define CONSOLE_DEV     g_uart2port         /* UART2 is console */
+#define TTYS0_DEV       g_uart2port         /* UART2 is ttyS0 */
+#define UART0_ASSIGNED  1
+
+/* A64 UART SCLK is the UART Input Clock.  Through experimentation, it has
+ * been found that the serial clock is OSC24M
+ */
+
+#define UART_SCLK 24000000
+
+/* Timeout for UART Busy Wait, in milliseconds */
+
+#define UART_TIMEOUT_MS 100
+
+/* A64 UART I/O Pins *******************************************************/
+
+/* UART1: PG6 and PG7 (Peripheral 2) */
+
+#ifdef CONFIG_A64_UART1
+#  define PIO_UART1_TX (PIO_PERIPH2 | PIO_PORT_PIOG | PIO_PIN6)
+#  define PIO_UART1_RX (PIO_PERIPH2 | PIO_PORT_PIOG | PIO_PIN7)
+#endif
+
+/* UART2: PB0 and PB1 (Peripheral 2) */
+
+#ifdef CONFIG_A64_UART2
+#  define PIO_UART2_TX (PIO_PERIPH2 | PIO_PORT_PIOB | PIO_PIN0)
+#  define PIO_UART2_RX (PIO_PERIPH2 | PIO_PORT_PIOB | PIO_PIN1)
+#endif
+
+/* UART3: PD0 and PD1 (Peripheral 3) */
+
+#ifdef CONFIG_A64_UART3
+#  define PIO_UART3_TX (PIO_PERIPH3 | PIO_PORT_PIOD | PIO_PIN0)
+#  define PIO_UART3_RX (PIO_PERIPH3 | PIO_PORT_PIOD | PIO_PIN1)
+#endif
+
+/* UART4: PD2 and PD3 (Peripheral 3) */
+
+#ifdef CONFIG_A64_UART4
+#  define PIO_UART4_TX (PIO_PERIPH3 | PIO_PORT_PIOD | PIO_PIN2)
+#  define PIO_UART4_RX (PIO_PERIPH3 | PIO_PORT_PIOD | PIO_PIN3)
+#endif
+
+/* A64 UART Registers and Bit Definitions **********************************/
+
+/* A64 UART Registers (A64 Page 562) */
+
+#define UART_THR(uart_addr) (uart_addr + 0x00)  /* Tx Holding */
+#define UART_RBR(uart_addr) (uart_addr + 0x00)  /* Rx Buffer */
+#define UART_DLL(uart_addr) (uart_addr + 0x00)  /* Divisor Latch Low */
+#define UART_DLH(uart_addr) (uart_addr + 0x04)  /* Divisor Latch High */
+#define UART_IER(uart_addr) (uart_addr + 0x04)  /* Interrupt Enable */
+#define UART_IIR(uart_addr) (uart_addr + 0x08)  /* Interrupt Identity */
+#define UART_FCR(uart_addr) (uart_addr + 0x08)  /* FIFO Control */
+#define UART_LCR(uart_addr) (uart_addr + 0x0c)  /* Line Control */
+#define UART_LSR(uart_addr) (uart_addr + 0x14)  /* Line Status */
+#define UART_MSR(uart_addr) (uart_addr + 0x18)  /* Modem Status */
+#define UART_USR(uart_addr) (uart_addr + 0x7c)  /* UART Status */
+
+/* A64 UART Register Bit Definitions (A64 Page 565) */
+
+#define UART_IER_ERBFI (1 << 0)  /* Enable Rx Data Interrupt */
+#define UART_IER_ETBEI (1 << 1)  /* Enable Tx Empty Interrupt */
+#define UART_LSR_DR    (1 << 0)  /* Rx Data Ready */
+#define UART_LSR_THRE  (1 << 5)  /* Tx Empty */
+#define UART_USR_BUSY  (1 << 0)  /* UART Busy */
+
+/* A64 UART Interrupt Identity Register (A64 Page 565) */
+
+#define UART_IIR_IID_SHIFT        (0) /* Bits: 0-3: Interrupt ID */
+#define UART_IIR_IID_MASK         (15 << UART_IIR_IID_SHIFT)
+#  define UART_IIR_IID_MODEM      (0 << UART_IIR_IID_SHIFT)  /* Modem status */
+#  define UART_IIR_IID_NONE       (1 << UART_IIR_IID_SHIFT)  /* No interrupt 
pending */
+#  define UART_IIR_IID_TXEMPTY    (2 << UART_IIR_IID_SHIFT)  /* THR empty */
+#  define UART_IIR_IID_RECV       (4 << UART_IIR_IID_SHIFT)  /* Received data 
available */
+#  define UART_IIR_IID_LINESTATUS (6 << UART_IIR_IID_SHIFT)  /* Receiver line 
status */
+#  define UART_IIR_IID_BUSY       (7 << UART_IIR_IID_SHIFT)  /* Busy detect */
+#  define UART_IIR_IID_TIMEOUT    (12 << UART_IIR_IID_SHIFT) /* Character 
timeout */
+
+#define UART_IIR_FEFLAG_SHIFT     (6) /* Bits 6-7: FIFOs Enable Flag */
+#define UART_IIR_FEFLAG_MASK      (3 << UART_IIR_FEFLAG_SHIFT)
+#  define UART_IIR_FEFLAG_DISABLE (0 << UART_IIR_FEFLAG_SHIFT)
+#  define UART_IIR_FEFLAG_ENABLE  (3 << UART_IIR_FEFLAG_SHIFT)
+
+/* A64 UART FIFO Control Register (A64 Page 567) */
+
+#define UART_FCR_FIFOE            (1 << 0)  /* Bit 0:  Enable FIFOs */
+#define UART_FCR_RFIFOR           (1 << 1)  /* Bit 1:  RCVR FIFO Reset */
+#define UART_FCR_XFIFOR           (1 << 2)  /* Bit 2:  XMIT FIFO reset */
+#define UART_FCR_DMAM             (1 << 3)  /* Bit 3:  DMA mode */
+#define UART_FCR_TFT_SHIFT        (4)       /* Bits 4-5: TX Empty Trigger */
+#define UART_FCR_TFT_MASK         (3 << UART_FCR_TFT_SHIFT)
+#  define UART_FCR_TFT_EMPTY      (0 << UART_FCR_TFT_SHIFT) /* FIFO empty */
+#  define UART_FCR_TFT_TWO        (1 << UART_FCR_TFT_SHIFT) /* 2 characters in 
the FIFO */
+#  define UART_FCR_TFT_QUARTER    (2 << UART_FCR_TFT_SHIFT) /* FIFO 1/4 full */
+#  define UART_FCR_TFT_HALF       (3 << UART_FCR_TFT_SHIFT) /* FIFO 1/2 full */
+
+#define UART_FCR_RT_SHIFT         (6)       /* Bits 6-7: RCVR Trigger */
+#define UART_FCR_RT_MASK          (3 << UART_FCR_RT_SHIFT)
+#  define UART_FCR_RT_ONE         (0 << UART_FCR_RT_SHIFT) /* 1 character in 
the FIFO */
+#  define UART_FCR_RT_QUARTER     (1 << UART_FCR_RT_SHIFT) /* FIFO 1/4 full */
+#  define UART_FCR_RT_HALF        (2 << UART_FCR_RT_SHIFT) /* FIFO 1/2 full */
+#  define UART_FCR_RT_MINUS2      (3 << UART_FCR_RT_SHIFT) /* FIFO-2 less than 
full */
+
+/* A64 UART Line Control Register (A64 Page 568) */
+
+#define UART_LCR_DLS_SHIFT        (0)       /* Bits 0-1: Data Length Select */
+#define UART_LCR_DLS_MASK         (3 << UART_LCR_DLS_SHIFT)
+#  define UART_LCR_DLS_5BITS      (0 << UART_LCR_DLS_SHIFT) /* 5 bits */
+#  define UART_LCR_DLS_6BITS      (1 << UART_LCR_DLS_SHIFT) /* 6 bits */
+#  define UART_LCR_DLS_7BITS      (2 << UART_LCR_DLS_SHIFT) /* 7 bits */
+#  define UART_LCR_DLS_8BITS      (3 << UART_LCR_DLS_SHIFT) /* 8 bits */
+
+#define UART_LCR_STOP             (1 << 2)  /* Bit 2:  Number of stop bits */
+#define UART_LCR_PEN              (1 << 3)  /* Bit 3:  Parity Enable */
+#define UART_LCR_EPS              (1 << 4)  /* Bit 4:  Even Parity Select */
+#define UART_LCR_BC               (1 << 6)  /* Bit 6:  Break Control Bit */
+#define UART_LCR_DLAB             (1 << 7)  /* Bit 7:  Divisor Latch Access 
Bit */
+
+/* A64 CCU Registers and Bit Definitions ***********************************/
+
+/* Bus Clock Gating Register 3 (A64 Page 104) */
+
+#define BUS_CLK_GATING_REG3 (A64_CCU_ADDR + 0x006C)
+#define UART0_GATING        (1 << 16)
+#define UART1_GATING        (1 << 17)
+#define UART2_GATING        (1 << 18)
+#define UART3_GATING        (1 << 19)
+#define UART4_GATING        (1 << 20)
+
+/* Bus Software Reset Register 4 (A64 Page 142) */
+
+#define BUS_SOFT_RST_REG4 (A64_CCU_ADDR + 0x02D8)
+#define UART0_RST         (1 << 16)
+#define UART1_RST         (1 << 17)
+#define UART2_RST         (1 << 18)
+#define UART3_RST         (1 << 19)
+#define UART4_RST         (1 << 20)
+
+/***************************************************************************
+ * Private Types
+ ***************************************************************************/
+
+/* A64 UART Configuration */
+
+struct a64_uart_config
+{
+  unsigned long uart;  /* UART Base Address */
+};
+
+/* A64 UART Device Data */
+
+struct a64_uart_data
+{
+  uint32_t baud_rate;  /* UART Baud Rate */
+  uint32_t ier;        /* Saved IER value */
+  uint8_t  parity;     /* 0=none, 1=odd, 2=even */
+  uint8_t  bits;       /* Number of bits (7 or 8) */
+  bool     stopbits2;  /* true: Configure with 2 stop bits instead of 1 */
+};
+
+/* A64 UART Port */
+
+struct a64_uart_port_s
+{
+  struct a64_uart_data data;     /* UART Device Data */
+  struct a64_uart_config config; /* UART Configuration */
+  unsigned int irq_num;          /* UART IRQ Number */
+  bool is_console;               /* 1 if this UART is console */
+};
+
+/***************************************************************************
+ * Private Function Prototypes
+ ***************************************************************************/
+
+static void a64_uart_rxint(struct uart_dev_s *dev, bool enable);
+static void a64_uart_txint(struct uart_dev_s *dev, bool enable);
+
+/***************************************************************************
+ * Private Functions
+ ***************************************************************************/
+
+/***************************************************************************
+ * Name: a64_uart_divisor
+ *
+ * Description:
+ *   Select a divisor to produce the BAUD from the UART SCLK.
+ *
+ *     BAUD = SCLK / (16 * DL), or
+ *     DL   = SCLK / BAUD / 16
+ *
+ * Returned Value:
+ *   UART Divisor
+ *
+ ***************************************************************************/
+
+static uint32_t a64_uart_divisor(uint32_t baud)
+{
+  DEBUGASSERT(baud != 0);
+  return UART_SCLK / (baud << 4);
+}
+
+/***************************************************************************
+ * Name: a64_uart_irq_handler
+ *
+ * Description:
+ *   This is the common UART interrupt handler.  It should call
+ *   uart_xmitchars or uart_recvchars to perform the appropriate data
+ *   transfers.
+ *
+ * Input Parameters:
+ *   irq     - IRQ Number
+ *   context - Interrupt Context
+ *   arg     - UART Device
+ *
+ * Returned Value:
+ *   OK is always returned at present.
+ *
+ ***************************************************************************/
+
+static int a64_uart_irq_handler(int irq, void *context, void *arg)
+{
+  struct uart_dev_s *dev = (struct uart_dev_s *)arg;
+  const struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+  const struct a64_uart_config *config = &port->config;
+  uint32_t status;
+  int passes;
+
+  DEBUGASSERT(dev != NULL && dev->priv != NULL);
+
+  /* Loop until there are no characters to be transferred or,
+   * until we have been looping for a long time.
+   */
+
+  for (passes = 0; passes < 256; passes++)
+    {
+      /* Get the current UART status */
+
+      status = getreg32(UART_IIR(config->uart));
+
+      /* Handle the interrupt by its interrupt ID field */
+
+      switch (status & UART_IIR_IID_MASK)
+        {
+          /* Handle incoming, receive bytes (with or without timeout) */
+
+          case UART_IIR_IID_RECV:
+          case UART_IIR_IID_TIMEOUT:
+            {
+              uart_recvchars(dev);
+              break;
+            }
+
+          /* Handle outgoing, transmit bytes */
+
+          case UART_IIR_IID_TXEMPTY:
+            {
+              uart_xmitchars(dev);
+              break;
+            }
+
+          /* Just clear modem status interrupts (UART1 only) */
+
+          case UART_IIR_IID_MODEM:
+            {
+              /* Read the modem status register (MSR) to clear */
+
+              status = getreg32(UART_MSR(config->uart));
+              break;
+            }
+
+          /* Just clear any line status interrupts */
+
+          case UART_IIR_IID_LINESTATUS:
+            {
+              /* Read the line status register (LSR) to clear */
+
+              status = getreg32(UART_LSR(config->uart));
+              break;
+            }
+
+          /* Busy detect.
+           * Just ignore.
+           * Cleared by reading the status register
+           */
+
+          case UART_IIR_IID_BUSY:
+            {
+              /* Read from the UART status register
+               * to clear the BUSY condition
+               */
+
+              status = getreg32(UART_USR(config->uart));
+              break;
+            }
+
+          /* No further interrupts pending... return now */
+
+          case UART_IIR_IID_NONE:
+            {
+              return OK;
+            }
+
+            /* Otherwise we have received an interrupt
+             * that we cannot handle
+             */
+
+          default:
+            {
+              _err("ERROR: Unexpected IIR: %02" PRIx32 "\n", status);
+              break;
+            }
+        }
+    }
+
+  return OK;
+}
+
+/***************************************************************************
+ * Name: a64_uart_wait
+ *
+ * Description:
+ *   Wait for UART to be non-busy.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) on success; ERROR if timeout.
+ *
+ ***************************************************************************/
+
+static int a64_uart_wait(struct uart_dev_s *dev)
+{
+  struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+  const struct a64_uart_config *config = &port->config;
+  int i;
+
+  for (i = 0; i < UART_TIMEOUT_MS; i++)
+    {
+      uint32_t status = getreg32(UART_USR(config->uart));
+
+      if ((status & UART_USR_BUSY) == 0)
+        {
+          return OK;
+        }
+
+      up_mdelay(1);
+    }
+
+  _err("UART timeout\n");
+  return ERROR;
+}
+
+/***************************************************************************
+ * Name: a64_uart_setup
+ *
+ * Description:
+ *   Configure the UART baud, bits, parity, fifos, etc. This method is
+ *   called the first time that the serial port is opened.
+ *
+ * Input Parameters:
+ *   dev - UART Device
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value is returned on any failure.
+ *
+ ***************************************************************************/
+
+static int a64_uart_setup(struct uart_dev_s *dev)
+{
+#ifndef CONFIG_SUPPRESS_UART_CONFIG
+  struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+  const struct a64_uart_config *config = &port->config;
+  struct a64_uart_data *data = &port->data;
+  uint16_t dl;
+  uint32_t lcr;
+  int ret;
+
+  DEBUGASSERT(data != NULL);
+
+  /* Clear fifos */
+
+  putreg32(UART_FCR_RFIFOR | UART_FCR_XFIFOR, UART_FCR(config->uart));
+
+  /* Set trigger */
+
+  putreg32(UART_FCR_FIFOE | UART_FCR_RT_HALF, UART_FCR(config->uart));
+
+  /* Set up the IER */
+
+  data->ier = getreg32(UART_IER(config->uart));
+
+  /* Set up the LCR */
+
+  lcr = 0;
+
+  switch (data->bits)
+    {
+    case 5:
+      lcr |= UART_LCR_DLS_5BITS;
+      break;
+
+    case 6:
+      lcr |= UART_LCR_DLS_6BITS;
+      break;
+
+    case 7:
+      lcr |= UART_LCR_DLS_7BITS;
+      break;
+
+    case 8:
+    default:
+      lcr |= UART_LCR_DLS_8BITS;
+      break;
+    }
+
+  if (data->stopbits2)
+    {
+      lcr |= UART_LCR_STOP;
+    }
+
+  if (data->parity == 1)
+    {
+      lcr |= UART_LCR_PEN;
+    }
+  else if (data->parity == 2)
+    {
+      lcr |= (UART_LCR_PEN | UART_LCR_EPS);
+    }
+
+  /* Set DLAB when UART is not busy */
+
+  ret = a64_uart_wait(dev);
+
+  if (ret < 0)
+    {
+      _err("UART wait failed, ret=%d\n", ret);
+      return ret;
+    }
+
+  putreg32(lcr | UART_LCR_DLAB, UART_LCR(config->uart));
+
+  ret = a64_uart_wait(dev);
+
+  if (ret < 0)
+    {
+      _err("UART wait failed, ret=%d\n", ret);
+      return ret;
+    }
+
+  /* Set the BAUD divisor */
+
+  dl = a64_uart_divisor(data->baud_rate);
+  putreg8(dl >> 8,   UART_DLH(config->uart));
+  putreg8(dl & 0xff, UART_DLL(config->uart));
+
+  /* Check the BAUD divisor */
+
+  if (getreg8(UART_DLH(config->uart)) != (dl >> 8) ||
+      getreg8(UART_DLL(config->uart)) != (dl & 0xff))
+    {
+      _err("UART BAUD divisor failed\n");
+      return ERROR;
+    }
+
+  /* Clear DLAB */
+
+  putreg32(lcr, UART_LCR(config->uart));
+
+  /* Configure the FIFOs */
+
+  putreg32(UART_FCR_RT_HALF | UART_FCR_XFIFOR | UART_FCR_RFIFOR |
+           UART_FCR_FIFOE, UART_FCR(config->uart));
+
+  /* Enable Auto-Flow Control in the Modem Control Register */
+
+#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
+#  warning Missing logic
+#endif
+
+#endif /* CONFIG_SUPPRESS_UART_CONFIG */
+  return OK;
+}
+
+/***************************************************************************
+ * Name: a64_uart_shutdown
+ *
+ * Description:
+ *   Disable the UART Port.  This method is called when the serial
+ *   port is closed.
+ *
+ * Input Parameters:
+ *   dev - UART Device
+ *
+ * Returned Value:
+ *   None
+ *
+ ***************************************************************************/
+
+static void a64_uart_shutdown(struct uart_dev_s *dev)
+{
+  /* Disable the Receive and Transmit Interrupts */
+
+  a64_uart_rxint(dev, false);
+  a64_uart_txint(dev, false);
+}
+
+/***************************************************************************
+ * Name: a64_uart_attach
+ *
+ * Description:
+ *   Configure the UART to operation in interrupt driven mode.
+ *   This method is called when the serial port is opened.
+ *   Normally, this is just after the setup() method is called,
+ *   however, the serial console may operate in
+ *   a non-interrupt driven mode during the boot phase.
+ *
+ *   RX and TX interrupts are not enabled when by the attach method
+ *   (unless the hardware supports multiple levels of interrupt
+ *   enabling).  The RX and TX interrupts are not enabled until
+ *   the txint() and rxint() methods are called.
+ *
+ * Input Parameters:
+ *   dev - UART Device
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value is returned on any failure.
+ *
+ ***************************************************************************/
+
+static int a64_uart_attach(struct uart_dev_s *dev)
+{
+  int ret;
+  const struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+
+  DEBUGASSERT(port != NULL);
+
+  /* Attach UART Interrupt Handler */
+
+  ret = irq_attach(port->irq_num, a64_uart_irq_handler, dev);
+
+  /* Set Interrupt Priority in Generic Interrupt Controller v2 */
+
+  arm64_gic_irq_set_priority(port->irq_num, 0, IRQ_TYPE_LEVEL);
+
+  /* Enable UART Interrupt */
+
+  if (ret == OK)
+    {
+      up_enable_irq(port->irq_num);
+    }
+  else
+    {
+      _err("IRQ attach failed, ret=%d\n", ret);
+    }
+
+  return ret;
+}
+
+/***************************************************************************
+ * Name: a64_uart_detach
+ *
+ * Description:
+ *   Detach UART interrupts.  This method is called when the serial port is
+ *   closed normally just before the shutdown method is called.  The
+ *   exception is the serial console which is never shutdown.
+ *
+ * Input Parameters:
+ *   dev - UART Device
+ *
+ * Returned Value:
+ *   None
+ *
+ ***************************************************************************/
+
+static void a64_uart_detach(struct uart_dev_s *dev)
+{
+  const struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+
+  DEBUGASSERT(port != NULL);
+
+  /* Disable UART Interrupt */
+
+  up_disable_irq(port->irq_num);
+
+  /* Detach UART Interrupt Handler */
+
+  irq_detach(port->irq_num);
+}
+
+/***************************************************************************
+ * Name: a64_uart_ioctl
+ *
+ * Description:
+ *   All ioctl calls will be routed through this method.
+ *
+ * Input Parameters:
+ *   filep - File Struct
+ *   cmd   - ioctl Command
+ *   arg   - ioctl Argument
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value is returned on any failure.
+ *
+ ***************************************************************************/
+
+static int a64_uart_ioctl(struct file *filep, int cmd, unsigned long arg)
+{
+  int ret = OK;
+
+  UNUSED(filep);
+  UNUSED(arg);
+
+  switch (cmd)
+    {
+      case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
+      case TIOCCBRK:  /* BSD compatibility: Turn break off, unconditionally */
+      default:
+        {
+          ret = -ENOTTY;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+/***************************************************************************
+ * Name: a64_uart_receive
+ *
+ * Description:
+ *   Called (usually) from the interrupt level to receive one
+ *   character from the UART.  Error bits associated with the
+ *   receipt are provided in the return 'status'.
+ *
+ * Input Parameters:
+ *   dev    - UART Device
+ *   status - Return status, zero on success
+ *
+ * Returned Value:
+ *   Received character
+ *
+ ***************************************************************************/
+
+static int a64_uart_receive(struct uart_dev_s *dev, unsigned int *status)
+{
+  struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+  const struct a64_uart_config *config = &port->config;
+  uint32_t rbr;
+
+  *status = getreg8(UART_LSR(config->uart));
+  rbr     = getreg8(UART_RBR(config->uart));
+  return rbr;
+}
+
+/***************************************************************************
+ * Name: a64_uart_rxint
+ *
+ * Description:
+ *   Call to enable or disable RX interrupts
+ *
+ * Input Parameters:
+ *   dev    - UART Device
+ *   enable - True to enable RX interrupts; false to disable
+ *
+ * Returned Value:
+ *   None
+ *
+ ***************************************************************************/
+
+static void a64_uart_rxint(struct uart_dev_s *dev, bool enable)
+{
+  const struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+  const struct a64_uart_config *config = &port->config;
+
+  /* Write to Interrupt Enable Register (UART_IER) */
+
+  if (enable)
+    {
+      /* Set ERBFI bit (Enable Rx Data Available Interrupt) */
+
+      modreg8(UART_IER_ERBFI, UART_IER_ERBFI, UART_IER(config->uart));
+    }
+  else
+    {
+      /* Clear ERBFI bit (Disable Rx Data Available Interrupt) */
+
+      modreg8(0, UART_IER_ERBFI, UART_IER(config->uart));
+    }
+}
+
+/***************************************************************************
+ * Name: a64_uart_rxavailable
+ *
+ * Description:
+ *   Return true if the Receive FIFO is not empty
+ *
+ * Input Parameters:
+ *   dev - UART Device
+ *
+ * Returned Value:
+ *   True if the Receive FIFO is not empty; false otherwise
+ *
+ ***************************************************************************/
+
+static bool a64_uart_rxavailable(struct uart_dev_s *dev)
+{
+  const struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+  const struct a64_uart_config *config = &port->config;
+
+  /* Data Ready Bit (Line Status Register) is 1 if Rx Data is ready */
+
+  return getreg8(UART_LSR(config->uart)) & UART_LSR_DR;
+}
+
+/***************************************************************************
+ * Name: a64_uart_send
+ *
+ * Description:
+ *   This method will send one byte on the UART
+ *
+ * Input Parameters:
+ *   dev - UART Device
+ *   ch  - Character to be sent
+ *
+ * Returned Value:
+ *   None
+ *
+ ***************************************************************************/
+
+static void a64_uart_send(struct uart_dev_s *dev, int ch)
+{
+  const struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+  const struct a64_uart_config *config = &port->config;
+
+  /* Write char to Transmit Holding Register (UART_THR) */
+
+  putreg8(ch, UART_THR(config->uart));
+}
+
+/***************************************************************************
+ * Name: a64_uart_txint
+ *
+ * Description:
+ *   Call to enable or disable TX interrupts
+ *
+ * Input Parameters:
+ *   dev    - UART Device
+ *   enable - True to enable TX interrupts; false to disable
+ *
+ * Returned Value:
+ *   None
+ *
+ ***************************************************************************/
+
+static void a64_uart_txint(struct uart_dev_s *dev, bool enable)
+{
+  const struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+  const struct a64_uart_config *config = &port->config;
+
+  /* Write to Interrupt Enable Register (UART_IER) */
+
+  if (enable)
+    {
+      /* Set ETBEI bit (Enable Tx Holding Register Empty Interrupt) */
+
+      modreg8(UART_IER_ETBEI, UART_IER_ETBEI, UART_IER(config->uart));
+    }
+  else
+    {
+      /* Clear ETBEI bit (Disable Tx Holding Register Empty Interrupt) */
+
+      modreg8(0, UART_IER_ETBEI, UART_IER(config->uart));
+    }
+}
+
+/***************************************************************************
+ * Name: a64_uart_txready
+ *
+ * Description:
+ *   Return true if the Transmit FIFO is not full
+ *
+ * Input Parameters:
+ *   dev - UART Device
+ *
+ * Returned Value:
+ *   True if the Transmit FIFO is not full; false otherwise
+ *
+ ***************************************************************************/
+
+static bool a64_uart_txready(struct uart_dev_s *dev)
+{
+  const struct a64_uart_port_s *port = (struct a64_uart_port_s *)dev->priv;
+  const struct a64_uart_config *config = &port->config;
+
+  /* Tx FIFO is ready if THRE Bit is 1 (Tx Holding Register Empty) */
+
+  return (getreg8(UART_LSR(config->uart)) & UART_LSR_THRE) != 0;
+}
+
+/***************************************************************************
+ * Name: a64_uart_txempty
+ *
+ * Description:
+ *   Return true if the Transmit FIFO is empty
+ *
+ * Input Parameters:
+ *   dev - UART Device
+ *
+ * Returned Value:
+ *   True if the Transmit FIFO is empty; false otherwise
+ *
+ ***************************************************************************/
+
+static bool a64_uart_txempty(struct uart_dev_s *dev)
+{
+  /* Tx FIFO is empty if Tx FIFO is not full (for now) */
+
+  return a64_uart_txready(dev);
+}
+
+/***************************************************************************
+ * Name: a64_uart_wait_send
+ *
+ * Description:
+ *   Wait for Transmit FIFO until it is not full, then transmit the
+ *   character over UART.
+ *
+ * Input Parameters:
+ *   dev - UART Device
+ *   ch  - Character to be sent
+ *
+ * Returned Value:
+ *   None
+ *
+ ***************************************************************************/
+
+static void a64_uart_wait_send(struct uart_dev_s *dev, int ch)
+{
+  DEBUGASSERT(dev != NULL);
+  while (!a64_uart_txready(dev));
+  a64_uart_send(dev, ch);
+}
+
+/***************************************************************************
+ * Private Data
+ ***************************************************************************/
+
+/* UART Operations for Serial Driver */
+
+static const struct uart_ops_s g_uart_ops =
+{
+  .setup    = a64_uart_setup,
+  .shutdown = a64_uart_shutdown,
+  .attach   = a64_uart_attach,
+  .detach   = a64_uart_detach,
+  .ioctl    = a64_uart_ioctl,
+  .receive  = a64_uart_receive,
+  .rxint    = a64_uart_rxint,
+  .rxavailable = a64_uart_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol    = NULL,
+#endif
+  .send     = a64_uart_send,
+  .txint    = a64_uart_txint,
+  .txready  = a64_uart_txready,
+  .txempty  = a64_uart_txempty,
+};
+
+/* UART0 Port State (Console) */
+
+#ifdef CONFIG_RK3399_UART
+static struct a64_uart_port_s g_uart0priv =
+{
+  .data   =
+    {
+      .baud_rate  = CONFIG_UART0_BAUD,
+      .parity     = CONFIG_UART0_PARITY,
+      .bits       = CONFIG_UART0_BITS,
+      .stopbits2  = CONFIG_UART0_2STOP
+    },
+
+  .config =
+    {
+      .uart       = RK3399_UART2_ADDR
+    },
+
+    .irq_num      = RK3399_UART2_IRQ,
+    .is_console   = 1
+};
+
+/* UART0 I/O Buffers (Console) */
+
+static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE];
+static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE];
+
+/* UART0 Port Definition (Console) */
+
+static struct uart_dev_s g_uart0port =
+{
+  .recv  =
+    {
+      .size   = CONFIG_UART0_RXBUFSIZE,
+      .buffer = g_uart0rxbuffer,
+    },
+
+  .xmit  =
+    {
+      .size   = CONFIG_UART0_TXBUFSIZE,
+      .buffer = g_uart0txbuffer,
+    },
+
+  .ops   = &g_uart_ops,
+  .priv  = &g_uart0priv,
+};
+
+#endif /* CONFIG_A64_UART */
+
+#ifdef CONFIG_RK3399_UART1
+
+/* UART1 Port State */
+
+static struct a64_uart_port_s g_uart1priv =
+{
+  .data   =
+    {
+      .baud_rate  = CONFIG_UART1_BAUD,
+      .parity     = CONFIG_UART1_PARITY,
+      .bits       = CONFIG_UART1_BITS,
+      .stopbits2  = CONFIG_UART1_2STOP
+    },
+
+  .config =
+    {
+      .uart       = A64_UART1_ADDR
+    },
+
+    .irq_num      = RK3399_UART1_IRQ,
+    .is_console   = 0
+};
+
+/* UART1 I/O Buffers */
+
+static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE];
+
+/* UART1 Port Definition */
+
+static struct uart_dev_s g_uart1port =
+{
+  .recv  =
+    {
+      .size   = CONFIG_UART1_RXBUFSIZE,
+      .buffer = g_uart1rxbuffer,
+    },
+
+  .xmit  =
+    {
+      .size   = CONFIG_UART1_TXBUFSIZE,
+      .buffer = g_uart1txbuffer,
+    },
+
+  .ops   = &g_uart_ops,
+  .priv  = &g_uart1priv,
+};
+
+#endif /* CONFIG_A64_UART1 */
+
+#ifdef CONFIG_RK3399_UART2
+
+/* UART2 Port State */
+
+static struct a64_uart_port_s g_uart2priv =
+{
+  .data   =
+    {
+      .baud_rate  = CONFIG_UART2_BAUD,
+      .parity     = CONFIG_UART2_PARITY,
+      .bits       = CONFIG_UART2_BITS,
+      .stopbits2  = CONFIG_UART2_2STOP
+    },
+
+  .config =
+    {
+      .uart       = RK3399_UART2_ADDR
+    },
+
+    .irq_num      = RK3399_UART2_IRQ,
+    .is_console   = 0
+};
+
+/* UART2 I/O Buffers */
+
+static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE];
+static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE];
+
+/* UART2 Port Definition */
+
+static struct uart_dev_s g_uart2port =
+{
+  .recv  =
+    {
+      .size   = CONFIG_UART2_RXBUFSIZE,
+      .buffer = g_uart2rxbuffer,
+    },
+
+  .xmit  =
+    {
+      .size   = CONFIG_UART2_TXBUFSIZE,
+      .buffer = g_uart2txbuffer,
+    },
+
+  .ops   = &g_uart_ops,
+  .priv  = &g_uart2priv,
+};
+
+#endif /* CONFIG_A64_UART2 */
+
+#ifdef CONFIG_RK3399_UART3
+
+/* UART3 Port State */
+
+static struct a64_uart_port_s g_uart3priv =
+{
+  .data   =
+    {
+      .baud_rate  = CONFIG_UART3_BAUD,
+      .parity     = CONFIG_UART3_PARITY,
+      .bits       = CONFIG_UART3_BITS,
+      .stopbits2  = CONFIG_UART3_2STOP
+    },
+
+  .config =
+    {
+      .uart       = A64_UART3_ADDR
+    },
+
+    .irq_num      = A64_UART3_IRQ,
+    .is_console   = 0
+};
+
+/* UART3 I/O Buffers */
+
+static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE];
+
+/* UART3 Port Definition */
+
+static struct uart_dev_s g_uart3port =
+{
+  .recv  =
+    {
+      .size   = CONFIG_UART3_RXBUFSIZE,
+      .buffer = g_uart3rxbuffer,
+    },
+
+  .xmit  =
+    {
+      .size   = CONFIG_UART3_TXBUFSIZE,
+      .buffer = g_uart3txbuffer,
+    },
+
+  .ops   = &g_uart_ops,
+  .priv  = &g_uart3priv,
+};
+
+#endif /* CONFIG_A64_UART3 */
+
+#ifdef CONFIG_RK3399_UART4
+
+/* UART4 Port State */
+
+static struct a64_uart_port_s g_uart4priv =
+{
+  .data   =
+    {
+      .baud_rate  = CONFIG_UART4_BAUD,
+      .parity     = CONFIG_UART4_PARITY,
+      .bits       = CONFIG_UART4_BITS,
+      .stopbits2  = CONFIG_UART4_2STOP
+    },
+
+  .config =
+    {
+      .uart       = A64_UART4_ADDR
+    },
+
+    .irq_num      = A64_UART4_IRQ,
+    .is_console   = 0
+};
+
+/* UART4 I/O Buffers */
+
+static char g_uart4rxbuffer[CONFIG_UART4_RXBUFSIZE];
+static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE];
+
+/* UART4 Port Definition */
+
+static struct uart_dev_s g_uart4port =
+{
+  .recv  =
+    {
+      .size   = CONFIG_UART4_RXBUFSIZE,
+      .buffer = g_uart4rxbuffer,
+    },
+
+  .xmit  =
+    {
+      .size   = CONFIG_UART4_TXBUFSIZE,
+      .buffer = g_uart4txbuffer,
+    },
+
+  .ops   = &g_uart_ops,
+  .priv  = &g_uart4priv,
+};
+
+#endif /* CONFIG_A64_UART4 */
+
+/* Pick ttys1.  This could be any of UART1-4. */
+
+#if defined(CONFIG_RK3399_UART1) && !defined(UART1_ASSIGNED)
+#  define TTYS1_DEV           g_uart1port /* UART1 is ttyS1 */
+#  define UART1_ASSIGNED      1
+#elif defined(CONFIG_RK3399_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS1_DEV           g_uart2port /* UART2 is ttyS1 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_RK3399_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS1_DEV           g_uart3port /* UART3 is ttyS1 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_RK3399_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS1_DEV           g_uart4port /* UART4 is ttyS1 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys2.  This could be one of UART2-4. */
+
+#if defined(CONFIG_RK3399_UART2) && !defined(UART2_ASSIGNED)
+#  define TTYS2_DEV           g_uart2port /* UART2 is ttyS2 */
+#  define UART2_ASSIGNED      1
+#elif defined(CONFIG_RK3399_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS2_DEV           g_uart3port /* UART3 is ttyS2 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_RK3399_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS2_DEV           g_uart4port /* UART4 is ttyS2 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys3.  This could be one of UART3-4. */
+
+#if defined(CONFIG_RK3399_UART3) && !defined(UART3_ASSIGNED)
+#  define TTYS3_DEV           g_uart3port /* UART3 is ttyS3 */
+#  define UART3_ASSIGNED      1
+#elif defined(CONFIG_RK3399_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS3_DEV           g_uart4port /* UART4 is ttyS3 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/* Pick ttys4.  This could only be UART4. */
+
+#if defined(CONFIG_RK3399_UART4) && !defined(UART4_ASSIGNED)
+#  define TTYS4_DEV           g_uart4port /* UART4 is ttyS4 */
+#  define UART4_ASSIGNED      1
+#endif
+
+/***************************************************************************
+ * Public Functions
+ ***************************************************************************/
+
+/***************************************************************************
+ * Name: arm64_earlyserialinit
+ *
+ * Description:
+ *   Performs the low level UART initialization early in
+ *   debug so that the serial console will be available
+ *   during bootup.  This must be called before arm64_serialinit.
+ *
+ * Returned Value:
+ *   None
+ *
+ ***************************************************************************/
+
+void arm64_earlyserialinit(void)
+{
+  int ret;
+
+  /* NOTE: This function assumes that UART0 low level hardware configuration
+   * -- including all clocking and pin configuration -- was performed
+   * earlier by U-Boot Bootloader.
+   */
+
+#ifdef CONFIG_A64_UART1
+  /* Configure UART1 */
+
+  ret = a64_uart_init(UART1_GATING, UART1_RST, PIO_UART1_TX, PIO_UART1_RX);
+
+  if (ret < 0)
+    {
+      _err("UART1 config failed, ret=%d\n", ret);
+    }
+#endif /* CONFIG_A64_UART1 */
+
+#ifdef CONFIG_A64_UART2
+  /* Configure UART2 */
+
+  ret = a64_uart_init(UART2_GATING, UART2_RST, PIO_UART2_TX, PIO_UART2_RX);
+
+  if (ret < 0)
+    {
+      _err("UART2 config failed, ret=%d\n", ret);
+    }
+#endif /* CONFIG_A64_UART2 */
+
+#ifdef CONFIG_A64_UART3
+  /* Configure UART3 */
+
+  ret = a64_uart_init(UART3_GATING, UART3_RST, PIO_UART3_TX, PIO_UART3_RX);
+
+  if (ret < 0)
+    {
+      _err("UART3 config failed, ret=%d\n", ret);
+    }
+#endif /* CONFIG_A64_UART3 */
+
+#ifdef CONFIG_A64_UART4
+  /* Configure UART4 */
+
+  ret = a64_uart_init(UART4_GATING, UART4_RST, PIO_UART4_TX, PIO_UART4_RX);
+
+  if (ret < 0)
+    {
+      _err("UART4 config failed, ret=%d\n", ret);
+    }
+#endif /* CONFIG_A64_UART4 */
+
+#ifdef CONSOLE_DEV
+  /* Enable the console at UART0 */
+
+  CONSOLE_DEV.isconsole = true;
+  a64_uart_setup(&CONSOLE_DEV);
+#endif
+
+  UNUSED(ret);
+}
+
+/***************************************************************************
+ * Name: up_putc
+ *
+ * Description:
+ *   Provide priority, low-level access to support OS debug
+ *   writes
+ *
+ * Input Parameters:
+ *   ch - Character to be transmitted over UART
+ *
+ * Returned Value:
+ *   Character that was transmitted
+ *
+ ***************************************************************************/
+
+int up_putc(int ch)
+{
+#ifdef CONSOLE_DEV
+  struct uart_dev_s *dev = &CONSOLE_DEV;
+
+  /* Check for LF */
+
+  if (ch == '\n')
+    {
+      /* Add CR */
+
+      a64_uart_wait_send(dev, '\r');
+    }
+
+  a64_uart_wait_send(dev, ch);
+#endif
+  return ch;
+}
+
+/***************************************************************************
+ * Name: arm64_serialinit
+ *
+ * Description:
+ *   Register serial console and serial ports.  This assumes
+ *   that a64_earlyserialinit was called previously.
+ *
+ * Returned Value:
+ *   None
+ *
+ ***************************************************************************/
+
+void arm64_serialinit(void)
+{
+#ifdef CONSOLE_DEV
+  int ret;
+
+  ret = uart_register("/dev/console", &CONSOLE_DEV);
+  if (ret < 0)
+    {
+      _err("Register /dev/console failed, ret=%d\n", ret);
+    }
+
+  ret = uart_register("/dev/ttyS0", &TTYS0_DEV);
+
+  if (ret < 0)
+    {
+      _err("Register /dev/ttyS0 failed, ret=%d\n", ret);
+    }
+
+#ifdef TTYS1_DEV
+  ret = uart_register("/dev/ttyS1", &TTYS1_DEV);
+
+  if (ret < 0)
+    {
+      _err("Register /dev/ttyS1 failed, ret=%d\n", ret);
+    }
+#endif /* TTYS1_DEV */
+
+#ifdef TTYS2_DEV
+  ret = uart_register("/dev/ttyS2", &TTYS2_DEV);
+
+  if (ret < 0)
+    {
+      _err("Register /dev/ttyS2 failed, ret=%d\n", ret);
+    }
+#endif /* TTYS2_DEV */
+
+#ifdef TTYS3_DEV
+  ret = uart_register("/dev/ttyS3", &TTYS3_DEV);
+
+  if (ret < 0)
+    {
+      _err("Register /dev/ttyS3 failed, ret=%d\n", ret);
+    }
+#endif /* TTYS3_DEV */
+
+#ifdef TTYS4_DEV
+  ret = uart_register("/dev/ttyS4", &TTYS4_DEV);
+
+  if (ret < 0)
+    {
+      _err("Register /dev/ttyS4 failed, ret=%d\n", ret);
+    }
+#endif /* TTYS4_DEV */
+
+#endif
+}
+
+#endif /* USE_SERIALDRIVER */
diff --git a/arch/arm64/src/rk3399/rk3399_serial.h 
b/arch/arm64/src/rk3399/rk3399_serial.h
new file mode 100644
index 0000000000..02809fabfe
--- /dev/null
+++ b/arch/arm64/src/rk3399/rk3399_serial.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+ * arch/arm64/src/rk3399/rk3399_serial.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM64_SRC_RK3399_RK3399_SERIAL_H
+#define __ARCH_ARM64_SRC_RK3399_RK3399_SERIAL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "arm64_internal.h"
+#include "arm64_gic.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_CHIP_RK3399
+
+/* IRQ for RK3399 UART Rockchip_RK3399TRM_V1.4_Part1-20170408 page 17 */
+
+#define RK3399_UART2_ADDR      0xff1a0000
+#define RK3399_UART0_IRQ       131         /* RK3399 UART0 IRQ */
+#define RK3399_UART1_IRQ       130         /* RK3399 UART1 IRQ */
+#define RK3399_UART2_IRQ       132         /* RK3399 UART2 IRQ */
+#define RK3399_UART3_IRQ       133         /* RK3399 UART3 IRQ */
+#define RK3399_UART4_IRQ       134         /* RK3399 UART4 IRQ */
+
+#endif /* CONFIG_ARCH_CHIP_RK3399 */
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM64_SRC_RK3399_RK3399_SERIAL_H */
diff --git a/boards/Kconfig b/boards/Kconfig
index fcd3ae3048..c839947bab 100644
--- a/boards/Kconfig
+++ b/boards/Kconfig
@@ -1943,6 +1943,14 @@ config ARCH_BOARD_PINEPHONE
                This options selects support for NuttX on PINE64 PinePhone based
                on Allwinner A64 SoC with ARM Cortex-A53.
 
+config ARCH_BOARD_PINEPHONE_PRO
+       bool "PINE64 PinePhonePro"
+       depends on ARCH_CHIP_RK3399
+       select ARCH_HAVE_LEDS
+       select ARCH_HAVE_IRQBUTTONS
+       ---help---
+               This options selects support for NuttX on PINE64 PinePhone based
+               on Rockchip RK3399 SoC with ARM Cortex-A53
 config ARCH_BOARD_FVP_ARMV8R
        bool "FVP ARM-v8r CPUs board"
        depends on ARCH_CHIP_FVP_ARMV8R
@@ -3100,6 +3108,7 @@ config ARCH_BOARD
        default "qemu-armv7a"               if ARCH_BOARD_QEMU_ARMV7A
        default "qemu-armv8a"               if ARCH_BOARD_QEMU_ARMV8A
        default "pinephone"                 if ARCH_BOARD_PINEPHONE
+       default "pinephonepro"              if ARCH_BOARD_PINEPHONE_PRO
        default "fvp-armv8r"                if ARCH_BOARD_FVP_ARMV8R
        default "fvp-armv8r-aarch32"        if ARCH_BOARD_FVP_ARMV8R_AARCH32
        default "imx8qm-mek"                if ARCH_BOARD_IMX8QM_MEK
@@ -3302,6 +3311,9 @@ endif
 if ARCH_BOARD_PINEPHONE
 source "boards/arm64/a64/pinephone/Kconfig"
 endif
+if ARCH_BOARD_PINEPHONE_PRO
+source "boards/arm64/rk3399/pinephonepro/Kconfig"
+endif
 if ARCH_BOARD_FVP_ARMV8R
 source "boards/arm64/fvp-v8r/fvp-armv8r/Kconfig"
 endif
diff --git a/boards/arm64/rk3399/pinephonepro/Kconfig 
b/boards/arm64/rk3399/pinephonepro/Kconfig
new file mode 100644
index 0000000000..25e8c268d2
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/Kconfig
@@ -0,0 +1,7 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+if ARCH_BOARD_PINEPHONE_PRO
+endif # ARCH_BOARD_PINEPHONE_PRO
diff --git a/boards/arm64/rk3399/pinephonepro/configs/nsh/defconfig 
b/boards/arm64/rk3399/pinephonepro/configs/nsh/defconfig
new file mode 100644
index 0000000000..272f196939
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/configs/nsh/defconfig
@@ -0,0 +1,69 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed 
.config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that 
includes your
+# modifications.
+#
+CONFIG_ARCH="arm64"
+CONFIG_ARCH_ARM64=y
+CONFIG_ARCH_BOARD="pinephonepro"
+CONFIG_ARCH_BOARD_PINEPHONE_PRO=y
+CONFIG_ARCH_CHIP="rk3399"
+CONFIG_ARCH_CHIP_RK3399=y
+CONFIG_ARCH_EARLY_PRINT=y
+CONFIG_ARCH_INTERRUPTSTACK=4096
+CONFIG_BOARD_LOOPSPERMSEC=116524
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_ASSERTIONS=y
+CONFIG_DEBUG_ERROR=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_IRQ=y
+CONFIG_DEBUG_IRQ_INFO=y
+CONFIG_DEBUG_SCHED=y
+CONFIG_DEBUG_SCHED_ERROR=y
+CONFIG_DEBUG_SCHED_WARN=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEBUG_WARN=y
+CONFIG_DEFAULT_TASK_STACKSIZE=8192
+CONFIG_DEV_ZERO=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_EXAMPLES_LEDS=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_FRAME_POINTER=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_ROMFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=8192
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_ROMFSETC=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PTHREAD_STACK_MIN=8192
+CONFIG_RAMLOG=y
+CONFIG_RAM_SIZE=134217728
+CONFIG_RAM_START=0x02080000
+CONFIG_RAW_BINARY=y
+CONFIG_READLINE_CMD_HISTORY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_BACKTRACE=y
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_HPWORKPRIORITY=192
+CONFIG_SPINLOCK=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_MONTH=11
+CONFIG_START_YEAR=2022
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_SYSTEM=y
+CONFIG_SYSTEM_TIME64=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_USEC_PER_TICK=1000
+CONFIG_USERLED=y
diff --git a/boards/arm64/rk3399/pinephonepro/include/board.h 
b/boards/arm64/rk3399/pinephonepro/include/board.h
new file mode 100644
index 0000000000..204c5bc2ec
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/include/board.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * boards/arm64/rk3399/pinephonepro/include/board.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM64_RK3399_PINEPHONE_PRO_INCLUDE_BOARD_H
+#define __BOARDS_ARM64_RK3399_PINEPHONE_PRO_INCLUDE_BOARD_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* LED definitions **********************************************************/
+
+/* LED index values for use with board_userled() */
+
+typedef enum
+{
+    BOARD_LED1 = 0,  /* Green LED */
+    BOARD_LED2 = 1,  /* Red LED */
+    BOARD_LED3 = 2,  /* Blue LED */
+    BOARD_LEDS       /* Number of LEDs */
+} led_typedef_enum;
+
+/* LED bits for use with board_userled_all() */
+
+#define BOARD_LED1_BIT    (1 << BOARD_LED1)
+#define BOARD_LED2_BIT    (1 << BOARD_LED2)
+#define BOARD_LED3_BIT    (1 << BOARD_LED3)
+
+/* If CONFIG_ARCH_LEDS is defined, the usage by the board port is defined in
+ * include/board.h and src/pinephone_autoleds.c. The LEDs are used to encode
+ * OS-related events as follows:
+ *
+ *   SYMBOL                     Meaning                      LED state
+ *                                                        LED1  LED2  LED3
+ *   ----------------------  --------------------------  ------ ------ ---
+ */
+
+#define LED_STARTED        0 /* NuttX has been started   OFF    OFF   OFF  */
+#define LED_HEAPALLOCATE   1 /* Heap has been allocated  ON     OFF   OFF  */
+#define LED_IRQSENABLED    2 /* Interrupts enabled       OFF    ON    OFF  */
+#define LED_STACKCREATED   3 /* Idle stack created       OFF    OFF   ON   */
+#define LED_INIRQ          4 /* In an interrupt          ON     ON    OFF  */
+#define LED_SIGNAL         5 /* In a signal handler      ON     OFF   ON   */
+#define LED_ASSERTION      6 /* An assertion failed      OFF    ON    ON   */
+#define LED_PANIC          7 /* The system has crashed   FLASH  ON    ON   */
+#define LED_IDLE           8 /* MCU is is sleep mode     OFF    FLASH OFF  */
+
+#endif /* __BOARDS_ARM64_RK3399_PINEPHONE_PRO_INCLUDE_BOARD_H */
diff --git a/boards/arm64/rk3399/pinephonepro/include/board_memorymap.h 
b/boards/arm64/rk3399/pinephonepro/include/board_memorymap.h
new file mode 100644
index 0000000000..7640a97a9a
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/include/board_memorymap.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * boards/arm64/rk3399/pinephonepro/include/board_memorymap.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM64_RK3399_PINEPHONE_PRO_INCLUDE_BOARD_MEMORYMAP_H
+#define __BOARDS_ARM64_RK3399_PINEPHONE_PRO_INCLUDE_BOARD_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM64_RK3399_PINEPHONE_PRO_INCLUDE_BOARD_MEMORYMAP_H */
diff --git a/boards/arm64/rk3399/pinephonepro/scripts/Make.defs 
b/boards/arm64/rk3399/pinephonepro/scripts/Make.defs
new file mode 100644
index 0000000000..47cb13de0d
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/scripts/Make.defs
@@ -0,0 +1,48 @@
+############################################################################
+# boards/arm64/rk3399/pinephonepro/scripts/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(TOPDIR)/.config
+include $(TOPDIR)/tools/Config.mk
+include $(TOPDIR)/arch/arm64/src/Toolchain.defs
+
+LDSCRIPT = dramboot.ld
+
+ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)
+
+CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) 
$(ARCHDEFINES) $(EXTRAFLAGS) -pipe
+CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS)
+CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) 
$(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe
+CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS)
+CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS)
+AFLAGS := $(CFLAGS) -D__ASSEMBLY__
+
+# NXFLAT module definitions
+
+NXFLATLDFLAGS1 = -r -d -warn-common
+NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) 
-T$(TOPDIR)$(DELIM)binfmt$(DELIM)libnxflat$(DELIM)gnu-nxflat-pcrel.ld 
-no-check-sections
+LDNXFLATFLAGS = -e main -s 2048
+
+# ELF module definitions
+
+CELFFLAGS = $(CFLAGS) -mlong-calls # --target1-abs
+CXXELFFLAGS = $(CXXFLAGS) -mlong-calls # --target1-abs
+
+LDELFFLAGS = -r -e main
+LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld)
diff --git a/boards/arm64/rk3399/pinephonepro/scripts/dramboot.ld 
b/boards/arm64/rk3399/pinephonepro/scripts/dramboot.ld
new file mode 100644
index 0000000000..b6b314a09f
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/scripts/dramboot.ld
@@ -0,0 +1,128 @@
+/****************************************************************************
+ * boards/arm64/rk3399/pinephone/scripts/dramboot.ld
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+OUTPUT_ARCH(aarch64)
+
+ENTRY(__start)
+
+PHDRS
+{
+  text PT_LOAD ;
+}
+
+SECTIONS
+{
+   // this comes from u-boot  
https://github.com/u-boot/u-boot/blob/a5899cc69a99379f01e8e2f9f98e0e09b24f1656/include/configs/rk3399_common.h#L41
+  . = 0x02080000;  /* U-Boot loads NuttX at this address (kernel_addr_r) */
+  _start = .;
+  .text : {
+        _stext = .;            /* Text section */
+       *(.text)
+       *(.text.cold)
+       *(.text.unlikely)
+       *(.fixup)
+       *(.gnu.warning)
+  } :text = 0x9090
+
+  . = ALIGN(4096);
+
+  .init_section : {
+        _sinit = ABSOLUTE(.);
+        KEEP(*(.init_array .init_array.*))
+        _einit = ABSOLUTE(.);
+  }
+
+  . = ALIGN(4096);
+
+  .vector : {
+        _vector_start = .;
+        KEEP(*(.exc_vector_table))
+        KEEP(*(".exc_vector_table.*"))
+        KEEP(*(.vectors))
+       _vector_end = .;
+  } :text
+  . = ALIGN(4096);
+  _etext = .; /* End_1 of .text */
+  _sztext = _etext - _stext;
+
+  . = ALIGN(4096);
+  .rodata : {
+        _srodata = .;          /* Read-only data */
+       *(.rodata)
+       *(.rodata.*)
+       *(.data.rel.ro)
+       *(.data.rel.ro.*)
+  } :text
+  . = ALIGN(4096);
+  _erodata = .;                /* End of read-only data */
+  _szrodata = _erodata - _srodata;
+  _eronly = .;  /* End of read-only data */
+
+  . = ALIGN(4096);
+  .data : {                    /* Data */
+        _sdata = .;
+       *(.data.page_aligned)
+       *(.data)
+       . = ALIGN(8);
+       *(.data.rel)
+       *(.data.rel.*)
+       CONSTRUCTORS
+  } :text
+  _edata = .; /* End+1 of .data */
+
+  .bss : {                     /* BSS */
+       . = ALIGN(8);
+       _sbss = .;
+       *(.bss)
+       . = ALIGN(8);
+  } :text
+  . = ALIGN(4096);
+  _ebss = .;
+  _szbss = _ebss - _sbss;
+
+  .initstack : {             /* INIT STACK */
+       _s_initstack = .;
+       *(.initstack)
+       . = ALIGN(16);
+  } :text
+  . = ALIGN(4096);
+  _e_initstack = . ;
+  g_idle_topstack = . ;
+
+  _szdata = _e_initstack - _sdata;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+       *(.exit.text)
+       *(.exit.data)
+       *(.exitcall.exit)
+       *(.eh_frame)
+  }
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
+
diff --git a/boards/arm64/rk3399/pinephonepro/src/Makefile 
b/boards/arm64/rk3399/pinephonepro/src/Makefile
new file mode 100644
index 0000000000..e7c3d94397
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/src/Makefile
@@ -0,0 +1,29 @@
+############################################################################
+# boards/arm64/a64/pinephone/src/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(TOPDIR)/Make.defs
+
+CSRCS = pinephonepro_boardinit.c pinephonepro_bringup.c
+
+ifeq ($(CONFIG_BOARDCTL),y)
+CSRCS += pinephonepro_appinit.c
+endif
+
+include $(TOPDIR)/boards/Board.mk
diff --git a/boards/arm64/rk3399/pinephonepro/src/pinephonepro.h 
b/boards/arm64/rk3399/pinephonepro/src/pinephonepro.h
new file mode 100644
index 0000000000..5eba9bdb17
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/src/pinephonepro.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * boards/arm64/rk3399/pinephonepro/src/pinephonepro.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM64_RK3399_PINEPHONE_SRC_PINEPHONEPRO_H
+#define __BOARDS_ARM64_RK3399_PINEPHONE_SRC_PINEPHONEPRO_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Functions Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pinephone_bringup
+ *
+ * Description:
+ *   Bring up board features
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_BOARDCTL) || defined(CONFIG_BOARD_LATE_INITIALIZE)
+int pinephone_bringup(void);
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM64_RK3399_PINEPHONE_SRC_PINEPHONEPRO_H */
diff --git a/boards/arm64/rk3399/pinephonepro/src/pinephonepro_appinit.c 
b/boards/arm64/rk3399/pinephonepro/src/pinephonepro_appinit.c
new file mode 100644
index 0000000000..27f1c599c6
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/src/pinephonepro_appinit.c
@@ -0,0 +1,73 @@
+/****************************************************************************
+ * boards/arm64/rk3399/pinephonepro/src/pinephonepro_appinit.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <nuttx/board.h>
+#include "pinephonepro.h"
+
+#ifdef CONFIG_BOARDCTL
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_app_initialize
+ *
+ * Description:
+ *   Perform application specific initialization.  This function is never
+ *   called directly from application code, but only indirectly via the
+ *   (non-standard) boardctl() interface using the command BOARDIOC_INIT.
+ *
+ * Input Parameters:
+ *   arg - The boardctl() argument is passed to the board_app_initialize()
+ *         implementation without modification.  The argument has no
+ *         meaning to NuttX; the meaning of the argument is a contract
+ *         between the board-specific initialization logic and the
+ *         matching application logic.  The value could be such things as a
+ *         mode enumeration value, a set of DIP switch switch settings, a
+ *         pointer to configuration data read from a file or serial FLASH,
+ *         or whatever you would like to do with it.  Every implementation
+ *         should accept zero/NULL as a default configuration.
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success; a negated errno value is returned on
+ *   any failure to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+int board_app_initialize(uintptr_t arg)
+{
+  UNUSED(arg);
+#ifndef CONFIG_BOARD_LATE_INITIALIZE
+  /* Perform board initialization */
+
+  return pinephone_bringup();
+#else
+  return OK;
+#endif
+}
+
+#endif /* CONFIG_BOARDCTL */
diff --git a/boards/arm64/rk3399/pinephonepro/src/pinephonepro_boardinit.c 
b/boards/arm64/rk3399/pinephonepro/src/pinephonepro_boardinit.c
new file mode 100644
index 0000000000..185206181f
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/src/pinephonepro_boardinit.c
@@ -0,0 +1,106 @@
+/****************************************************************************
+ * boards/arm64/rk3399/pinephonepro/src/pinephonepro_boardinit.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+#include <nuttx/board.h>
+#include "pinephonepro.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rk3399_memory_initialize
+ *
+ * Description:
+ *   All RK3399 architectures must provide the following entry point.  This
+ *   entry point is called early in the initialization before memory has
+ *   been configured.  This board-specific function is responsible for
+ *   configuring any on-board memories.
+ *
+ *   Logic in rk3399_memory_initialize must be careful to avoid using any
+ *   global variables because those will be uninitialized at the time this
+ *   function is called.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void rk3399_memory_initialize(void)
+{
+  /* SDRAM was already init by bootloader in supported configuration */
+}
+
+/****************************************************************************
+ * Name: rk3399_board_initialize
+ *
+ * Description:
+ *   All RK3399 architectures must provide the following entry point.  This
+ *   entry point is called in the initialization phase -- after
+ *   rk3399_memory_initialize and after all memory has been configured and
+ *   mapped but before any devices have been initialized.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void rk3399_board_initialize(void)
+{
+#ifdef CONFIG_ARCH_LEDS
+  /* Configure on-board LEDs if LED support has been selected. */
+
+  /* board_autoled_initialize(); */
+#endif
+}
+
+/****************************************************************************
+ * Name: board_late_initialize
+ *
+ * Description:
+ *   If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional
+ *   initialization call will be performed in the boot-up sequence to a
+ *   function called board_late_initialize(). board_late_initialize() will be
+ *   called immediately after up_initialize() is called and just before the
+ *   initial application is started.  This additional initialization phase
+ *   may be used, for example, to initialize board-specific device drivers.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BOARD_LATE_INITIALIZE
+void board_late_initialize(void)
+{
+  /* Perform board initialization */
+
+  pinephone_bringup();
+}
+#endif /* CONFIG_BOARD_LATE_INITIALIZE */
diff --git a/boards/arm64/rk3399/pinephonepro/src/pinephonepro_bringup.c 
b/boards/arm64/rk3399/pinephonepro/src/pinephonepro_bringup.c
new file mode 100644
index 0000000000..874c267cdc
--- /dev/null
+++ b/boards/arm64/rk3399/pinephonepro/src/pinephonepro_bringup.c
@@ -0,0 +1,63 @@
+/****************************************************************************
+ * boards/arm64/rk3399/pinephonepro/src/pinephonepro_bringup.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/kmalloc.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include "pinephonepro.h"
+
+#ifdef CONFIG_FS_PROCFS
+#  include <nuttx/fs/fs.h>
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pinephone_bringup
+ *
+ * Description:
+ *   Bring up board features
+ *
+ ****************************************************************************/
+
+int pinephone_bringup(void)
+{
+  int ret = OK;
+
+#ifdef CONFIG_FS_PROCFS
+  /* Mount the procfs file system */
+
+  ret = nx_mount(NULL, "/proc", "procfs", 0, NULL);
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to mount procfs at /proc: %d\n", ret);
+    }
+#endif
+
+  UNUSED(ret);
+  return OK;
+}

Reply via email to