Platform: Debug Access Port (DAP) driver (psoc64)

As specified by the default security policy, CM4 core debug port
is disabled during the boot, but allowed to be enabled later after CM4
is up. Add an API to control DAP and enable CM4 debugging.

Signed-off-by: Andrei Narkevitch <ainh@cypress.com>
Change-Id: Ib9ee449bb21c8a26c75ac51c80be112608914ed8
diff --git a/platform/ext/psoc64.cmake b/platform/ext/psoc64.cmake
index baa1065..a98ea51 100644
--- a/platform/ext/psoc64.cmake
+++ b/platform/ext/psoc64.cmake
@@ -215,6 +215,7 @@
 elseif(BUILD_CMSIS_DRIVERS)
   list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/cypress/psoc64/driver_smpu.c")
   list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/cypress/psoc64/driver_ppu.c")
+  list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/cypress/psoc64/driver_dap.c")
   list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/cypress/psoc64/CMSIS_Driver/Driver_USART.c")
   embedded_include_directories(PATH "${PLATFORM_DIR}/target/cypress/psoc64/CMSIS_Driver" ABSOLUTE)
   embedded_include_directories(PATH "${PLATFORM_DIR}/driver" ABSOLUTE)
diff --git a/platform/ext/target/cypress/psoc64/driver_dap.c b/platform/ext/target/cypress/psoc64/driver_dap.c
new file mode 100644
index 0000000..3b20a7a
--- /dev/null
+++ b/platform/ext/target/cypress/psoc64/driver_dap.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2020, Cypress Semiconductor Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+
+#include "driver_dap.h"
+
+#include "cycfg.h"
+#include "cy_device.h"
+#include "cy_device_headers.h"
+#include "cy_ipc_drv.h"
+#include "cy_prot.h"
+#include "cy_sysint.h"
+#include "driver_dap.h"
+#include "pc_config.h"
+
+/* DAPControl SysCall opcode */
+#define DAPCONTROL_SYSCALL_OPCODE       (0x3AUL << 24UL)
+
+/* FlashBoot SysCall success return code */
+#define CY_FB_SYSCALL_SUCCESS           (0xA0000000UL)
+
+/* SysCall timeout value */
+#define CY_DAP_SYSCALL_WAIT_MAX_TRIES   (15000UL)
+
+
+int cy_access_port_control(enum cy_ap_name ap, enum cy_ap_control en)
+{
+    int rc = -1;
+    uint32_t syscallCmd, result;
+    uint32_t timeout = 0U;
+
+    syscallCmd  = DAPCONTROL_SYSCALL_OPCODE;
+    syscallCmd |= (uint8_t)en << 16;
+    syscallCmd |= (uint8_t)ap << 8;
+    syscallCmd |= 1;
+
+    /* Get IPC base register address */
+    IPC_STRUCT_Type * ipcStruct = Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL);
+
+    while ((CY_IPC_DRV_SUCCESS != Cy_IPC_Drv_LockAcquire(ipcStruct)) &&
+            (timeout < CY_DAP_SYSCALL_WAIT_MAX_TRIES)) {
+        ++timeout;
+    }
+
+    if (timeout < CY_DAP_SYSCALL_WAIT_MAX_TRIES) {
+        timeout = 0U;
+
+        Cy_IPC_Drv_WriteDataValue(ipcStruct, syscallCmd);
+        Cy_IPC_Drv_AcquireNotify(ipcStruct, (1<<CY_IPC_CHAN_SYSCALL));
+
+        while ((Cy_IPC_Drv_IsLockAcquired(ipcStruct))&&
+                (timeout < CY_DAP_SYSCALL_WAIT_MAX_TRIES)) {
+            ++timeout;
+        }
+
+        if (timeout < CY_DAP_SYSCALL_WAIT_MAX_TRIES) {
+            result = Cy_IPC_Drv_ReadDataValue(ipcStruct);
+            if (result != CY_FB_SYSCALL_SUCCESS) {
+                rc = result;
+            }
+            else {
+                rc = 0;
+            }
+        }
+    }
+    return rc;
+}
diff --git a/platform/ext/target/cypress/psoc64/driver_dap.h b/platform/ext/target/cypress/psoc64/driver_dap.h
new file mode 100644
index 0000000..4ad1e65
--- /dev/null
+++ b/platform/ext/target/cypress/psoc64/driver_dap.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2020, Cypress Semiconductor Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DRIVER_DAP_H__
+#define __DRIVER_DAP_H__
+
+/** DAPControl SysCall parameter: access port state */
+enum cy_ap_control {
+    CY_AP_DIS = 0,
+    CY_AP_EN = 1
+};
+
+/** DAPControl SysCall parameter: access port name */
+enum cy_ap_name {
+    CY_CM0_AP = 0,
+    CY_CM4_AP = 1,
+    CY_SYS_AP = 2
+};
+
+/* API functions */
+int cy_access_port_control(enum cy_ap_name ap, enum cy_ap_control en);
+
+#endif /* __DRIVER_DAP_H__ */
diff --git a/platform/ext/target/cypress/psoc64/spm_hal.c b/platform/ext/target/cypress/psoc64/spm_hal.c
index 350845a..23eb655 100644
--- a/platform/ext/target/cypress/psoc64/spm_hal.c
+++ b/platform/ext/target/cypress/psoc64/spm_hal.c
@@ -28,6 +28,7 @@
 #include "cy_ipc_drv.h"
 #include "cy_prot.h"
 #include "pc_config.h"
+#include "driver_dap.h"
 
 /* Get address of memory regions to configure MPU */
 extern const struct memory_region_limits memory_regions;
@@ -215,6 +216,14 @@
 void tfm_spm_hal_boot_ns_cpu(uintptr_t start_addr)
 {
     smpu_print_config();
+
+    if (cy_access_port_control(CY_CM4_AP, CY_AP_EN) == 0) {
+        /* The delay is required after Access port was enabled for
+        * debugger/programmer to connect and set TEST BIT */
+        Cy_SysLib_Delay(100);
+        printf("Enabled CM4_AP DAP control\n");
+    }
+
     printf("Starting Cortex-M4 at 0x%x\r\n", start_addr);
     Cy_SysEnableCM4(start_addr);
 }