Platform: Enable whole QSPI access on Musca-A1

- Add the QSPI driver to the Musca-A1 platform files so it can be used
by the flash driver to remap the base address
- Make temporary modifications to the Musca flash driver using the QSPI
driver to enable the whole of the flash area to be accessed, so that
the newest image can be selected and copied directly to SRAM by the
bootloader

Signed-off-by: Oliver Swede <oli.swede@arm.com>
Change-Id: I33e6fb5cb5f1f1aa0902388c78d3c1c60d9cc05d
diff --git a/platform/ext/musca_a.cmake b/platform/ext/musca_a.cmake
index 7eafeca..dec8fe8 100755
--- a/platform/ext/musca_a.cmake
+++ b/platform/ext/musca_a.cmake
@@ -80,6 +80,7 @@
 elseif(BUILD_NATIVE_DRIVERS)
   list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/Native_Driver/uart_pl011_drv.c")
   list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/Native_Driver/musca_a1_scc_drv.c")
+  list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/Native_Driver/qspi_ip6514e_drv.c")
 
   list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_a/Native_Driver/mpc_sie200_drv.c"
               "${PLATFORM_DIR}/target/musca_a/Native_Driver/ppc_sse200_drv.c")
diff --git a/platform/ext/target/musca_a/CMSIS_Driver/Driver_Flash.c b/platform/ext/target/musca_a/CMSIS_Driver/Driver_Flash.c
index 807702a..b21167f 100755
--- a/platform/ext/target/musca_a/CMSIS_Driver/Driver_Flash.c
+++ b/platform/ext/target/musca_a/CMSIS_Driver/Driver_Flash.c
@@ -24,6 +24,9 @@
 #include "flash_layout.h"
 #include "region_defs.h"
 
+#include <assert.h>
+#include "qspi_ip6514e_drv.h"
+
 #ifndef ARG_UNUSED
 #define ARG_UNUSED(arg)  ((void)arg)
 #endif
@@ -207,10 +210,22 @@
     if(addr >= SST_FLASH_AREA_ADDR &&
        addr <= SST_FLASH_AREA_ADDR + FLASH_SST_AREA_SIZE) {
         start_addr = S_CODE_SRAM_ALIAS_BASE + addr;
+        memcpy(data, (void *)start_addr, cnt);
+    } else {
+        uint32_t window_off = start_addr % SPI_FLASH_ACCESS_LENGTH;
+        uint32_t window_base = start_addr - window_off;
+        /* Might need to handle this case */
+        assert ((window_off + cnt) <= SPI_FLASH_ACCESS_LENGTH);
+        qspi_remap_base(window_base - mem_base);
+        if (cnt % 4 != 0) { /* Some read sizes are smaller than 4 bytes */
+            memcpy(data, (void *)(mem_base + window_off), cnt);
+        } else {
+            /* Need to use memcpy4 instead of memcpy as it's possible that
+             * this method is being used to copy image from Flash to SRAM */
+            memcpy4(data, (void *)(mem_base + window_off), cnt);
+        }
     }
 
-    /* Flash interface just emulated over SRAM, use memcpy */
-    memcpy(data, (void *)start_addr, cnt);
     return ARM_DRIVER_OK;
 }
 
@@ -241,8 +256,14 @@
         }
     } else {
         /* Flash interface just emulated over SRAM, use memcpy */
-        memcpy((void *)start_addr, data, cnt);
+        uint32_t window_off = start_addr % SPI_FLASH_ACCESS_LENGTH;
+        uint32_t window_base = start_addr - window_off;
+        /* Might need to handle this case */
+        assert ((window_off + cnt) <= SPI_FLASH_ACCESS_LENGTH);
+        qspi_remap_base(window_base - mem_base);
+        memcpy((void *)(mem_base + window_off), data, cnt);
     }
+
     return ARM_DRIVER_OK;
 }
 
@@ -269,13 +290,18 @@
         if (rc != ARM_DRIVER_OK) {
             return ARM_DRIVER_ERROR_PARAMETER;
         }
-
     } else {
-        /* Flash interface just emulated over SRAM, use memset */
-        memset((void *)mem_base + addr,
+        uint32_t start_addr = S_CODE_SRAM_ALIAS_BASE + addr;
+        uint32_t window_off = start_addr % SPI_FLASH_ACCESS_LENGTH;
+        uint32_t window_base = start_addr - window_off;
+        assert ((window_off + FLASH0_DEV->data->sector_size)
+                <= SPI_FLASH_ACCESS_LENGTH);
+        qspi_remap_base(window_base - mem_base);
+        memset((void *)(mem_base + window_off),
                FLASH0_DEV->data->erased_value,
                FLASH0_DEV->data->sector_size);
     }
+
     return ARM_DRIVER_OK;
 }
 
diff --git a/platform/ext/target/musca_a/Device/Include/platform_retarget.h b/platform/ext/target/musca_a/Device/Include/platform_retarget.h
index 6dd2172..1e4b2d8 100755
--- a/platform/ext/target/musca_a/Device/Include/platform_retarget.h
+++ b/platform/ext/target/musca_a/Device/Include/platform_retarget.h
@@ -66,4 +66,6 @@
 #define FLASH0_PAGE_SIZE              (0x00001000)  /* 4 kB */
 #define FLASH0_PROGRAM_UNIT           (0x4)         /* Minimum write size */
 
+#define QSPI_CONTROLLER_ADDRESS       (0x5010A000)
+
 #endif  /* __ARM_LTD_MUSCA_RETARGET_H__ */
diff --git a/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.c b/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.c
new file mode 100644
index 0000000..5ce569c
--- /dev/null
+++ b/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include "qspi_ip6514e_drv.h"
+
+struct _qspi_ip6514e_reg_t {
+    volatile uint32_t qspi_cfg;                           /*!< 0x00 (R/W) */
+    volatile uint32_t hidden1[8];
+    volatile uint32_t remap_addr;                         /*!< 0x24 (R/W) */
+};
+
+#define  QSPI_CONTROLLER ((volatile struct _qspi_ip6514e_reg_t *) \
+         QSPI_CONTROLLER_ADDRESS)
+
+void qspi_remap_base(uint32_t new_addr)
+{
+    __DSB();
+    __ISB();
+    QSPI_CONTROLLER->qspi_cfg &= ~1U;
+    QSPI_CONTROLLER->remap_addr = new_addr;
+    QSPI_CONTROLLER->qspi_cfg |= (1U << 16);
+    QSPI_CONTROLLER->qspi_cfg |= 1U;
+    __DSB();
+    __ISB();
+}
\ No newline at end of file
diff --git a/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.h b/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.h
new file mode 100644
index 0000000..fb60ece
--- /dev/null
+++ b/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __QSPI_IP6514E_DRV_H__
+#define __QSPI_IP6514E_DRV_H__
+
+#include "platform_retarget.h"
+
+#define SPI_FLASH_ACCESS_LENGTH       (0x40000)
+
+void qspi_remap_base(uint32_t new_addr);
+
+#endif /* __QSPI_IP6514E_DRV_H__ */
\ No newline at end of file