From 29309f101a4828842c377ff11a3a59908aab05f2 Mon Sep 17 00:00:00 2001
From: edolomb <none@example.com>
Date: Thu, 17 Jan 2019 15:19:20 +0000
Subject: Updated SAMA drivers (still incomplete)

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12543 110e8d01-0319-4d1e-a829-52ad28d1bb01
---
 os/common/ports/ARM/compilers/GCC/chtypes.h        |  18 +
 os/common/ports/ARMCAx-TZ/chtssi.c                 | 188 +++-
 os/common/ports/ARMCAx-TZ/chtssi.h                 |  92 +-
 os/common/ports/ARMCAx-TZ/compilers/GCC/monitor.S  |   5 +-
 .../startup/ARM/compilers/GCC/ld/SAMA5D2bvddr.ld   |  46 -
 .../startup/ARM/compilers/GCC/ld/SAMA5D2ddr.ld     |  39 +-
 os/common/startup/ARM/devices/SAMA5D2/mmu.c        |  27 +-
 os/common/startup/ARMCAx-TZ/compilers/GCC/crt0.S   |  42 +
 .../ARMCAx-TZ/compilers/GCC/ld/SAMA5D2ddr.ld       |  37 +-
 os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.c  |  25 +-
 os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.h  |   2 +-
 .../startup/ARMCAx-TZ/devices/SAMA5D2/sama5d2x.h   |   2 +
 os/hal/boards/ATSAMA5D27_SOM1/board.c              | 289 +++++++
 os/hal/boards/ATSAMA5D27_SOM1/board.h              | 238 +++++
 os/hal/boards/ATSAMA5D27_SOM1/board.mk             |   9 +
 os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.c         | 165 ++++
 os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.h         | 232 +++++
 os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.mk        |   9 +
 os/hal/boards/ATSAMA5D27_SOM1_SEC/board.c          | 229 +++++
 os/hal/boards/ATSAMA5D27_SOM1_SEC/board.h          | 236 +++++
 os/hal/boards/ATSAMA5D27_SOM1_SEC/board.mk         |   9 +
 os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c      |  20 +
 os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c   |   7 +-
 os/hal/ports/SAMA/LLD/CRYPTOv1/sama_gcm_lld.c      |  19 +
 os/hal/ports/SAMA/LLD/CRYPTOv1/sama_sha_lld.c      |  16 +-
 os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c     |  21 +
 os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.c           |  26 +-
 os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.h           |  12 +-
 os/hal/ports/SAMA/LLD/I2Cv1/driver.mk              |  21 +
 os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.c          | 963 +++++++++++++++++++++
 os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.h          | 277 ++++++
 os/hal/ports/SAMA/LLD/MACv1/hal_mac_lld.c          |  25 +-
 os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.c          | 301 +++++++
 os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.h          |  49 +-
 os/hal/ports/SAMA/LLD/RNGv1/driver.mk              |   9 +
 os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.c         | 175 ++++
 os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.h         | 113 +++
 os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.c          |  31 +-
 os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.h          |  55 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c           |   2 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h           |   2 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c      |   4 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c    |  60 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_macros.h    |  11 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c       |   2 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h   |  18 +
 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c        |   2 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sdio.c      |   2 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk            |  10 +
 os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c     |   4 +-
 os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h     |   8 +-
 os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c          | 205 ++++-
 os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.h          | 300 ++++---
 os/hal/ports/SAMA/LLD/USARTv1/hal_serial_lld.h     |   2 +-
 os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.c       |  66 +-
 os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.h       |  20 +
 os/hal/ports/SAMA/LLD/xWDGv1/driver.mk             |   9 +
 os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.c         | 165 ++++
 os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.h         | 141 +++
 os/hal/ports/SAMA/SAMA5D2x/aic.c                   | 310 -------
 os/hal/ports/SAMA/SAMA5D2x/aic.h                   | 114 ---
 os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c        |  12 +-
 os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.h        |  20 +-
 os/hal/ports/SAMA/SAMA5D2x/hal_lld.c               |  10 +-
 os/hal/ports/SAMA/SAMA5D2x/hal_lld.h               |  30 +-
 os/hal/ports/SAMA/SAMA5D2x/platform.mk             |  12 +-
 os/hal/ports/SAMA/SAMA5D2x/sama_aic.c              | 310 +++++++
 os/hal/ports/SAMA/SAMA5D2x/sama_aic.h              | 114 +++
 os/hal/ports/SAMA/SAMA5D2x/sama_cache.c            |  34 +-
 os/hal/ports/SAMA/SAMA5D2x/sama_cache.h            |   5 +
 os/hal/ports/SAMA/SAMA5D2x/sama_classd.c           | 526 +++++++++++
 os/hal/ports/SAMA/SAMA5D2x/sama_classd.h           | 301 +++++++
 os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.c             | 955 ++++++++++++++++++++
 os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.h             | 280 ++++++
 os/hal/ports/SAMA/SAMA5D2x/sama_onewire.c          | 548 ++++++++++++
 os/hal/ports/SAMA/SAMA5D2x/sama_onewire.h          | 127 +++
 os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h              | 480 ++++++++++
 os/hal/ports/SAMA/SAMA5D2x/sama_rstc.h             | 179 ++++
 os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c          |   6 +-
 os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h          |  11 +-
 os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.c           | 575 ++++++++++++
 os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.h           | 364 ++++++++
 os/hal/ports/SAMA/SAMA5D2x/sama_trng.c             | 190 ----
 os/hal/ports/SAMA/SAMA5D2x/sama_trng.h             | 106 ---
 84 files changed, 9617 insertions(+), 1114 deletions(-)
 delete mode 100755 os/common/startup/ARM/compilers/GCC/ld/SAMA5D2bvddr.ld
 create mode 100644 os/hal/boards/ATSAMA5D27_SOM1/board.c
 create mode 100644 os/hal/boards/ATSAMA5D27_SOM1/board.h
 create mode 100644 os/hal/boards/ATSAMA5D27_SOM1/board.mk
 create mode 100644 os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.c
 create mode 100644 os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.h
 create mode 100644 os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.mk
 create mode 100644 os/hal/boards/ATSAMA5D27_SOM1_SEC/board.c
 create mode 100644 os/hal/boards/ATSAMA5D27_SOM1_SEC/board.h
 create mode 100644 os/hal/boards/ATSAMA5D27_SOM1_SEC/board.mk
 create mode 100644 os/hal/ports/SAMA/LLD/I2Cv1/driver.mk
 create mode 100644 os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.c
 create mode 100644 os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.h
 create mode 100644 os/hal/ports/SAMA/LLD/RNGv1/driver.mk
 create mode 100644 os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.c
 create mode 100644 os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.h
 create mode 100644 os/hal/ports/SAMA/LLD/xWDGv1/driver.mk
 create mode 100644 os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.c
 create mode 100644 os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.h
 delete mode 100644 os/hal/ports/SAMA/SAMA5D2x/aic.c
 delete mode 100644 os/hal/ports/SAMA/SAMA5D2x/aic.h
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_aic.c
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_aic.h
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_classd.c
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_classd.h
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.c
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.h
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_onewire.c
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_onewire.h
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_rstc.h
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.c
 create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.h
 delete mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_trng.c
 delete mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_trng.h

diff --git a/os/common/ports/ARM/compilers/GCC/chtypes.h b/os/common/ports/ARM/compilers/GCC/chtypes.h
index 23c3b8e7b..048101666 100644
--- a/os/common/ports/ARM/compilers/GCC/chtypes.h
+++ b/os/common/ports/ARM/compilers/GCC/chtypes.h
@@ -32,6 +32,24 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+/**
+ * @name    Common constants
+ */
+/**
+ * @brief   Generic 'false' boolean constant.
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE               0
+#endif
+
+/**
+ * @brief   Generic 'true' boolean constant.
+ */
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE                1
+#endif
+/** @} */
+
 /**
  * @name    Kernel types
  * @{
diff --git a/os/common/ports/ARMCAx-TZ/chtssi.c b/os/common/ports/ARMCAx-TZ/chtssi.c
index 4e37c7be5..9948aa75b 100644
--- a/os/common/ports/ARMCAx-TZ/chtssi.c
+++ b/os/common/ports/ARMCAx-TZ/chtssi.c
@@ -1,5 +1,5 @@
 /*
-    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+    ChibiOS - Copyright (C) 2006..2018 Isidoro Orabona
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -37,8 +37,18 @@
 /*===========================================================================*/
 /* Module local definitions.                                                 */
 /*===========================================================================*/
+/* Granted timeslices to trusted service. DO NOT modify those values.
+   They have non secure world counterparts.*/
+typedef enum {
+  TS_TIMEINT_1000_US  = 1000,
+  TS_TIMEINT_10000_US = 10000
+} ts_timeint_t;
 
 #define LOWORD(in64) ((int64_t)in64 & 0x0FFFFFFFF)
+#define TS_TIME2I(tmo)                                                      \
+   (tmo == TS_TIMEINT_10000_US ? TIME_US2I(TS_TIMEINT_10000_US) :           \
+                                 TIME_US2I(TS_TIMEINT_1000_US))
+#define FDT_MAGIC 0xd00dfeed
 
 /*===========================================================================*/
 /* Module exported variables.                                                */
@@ -47,6 +57,8 @@
 /* If a services file is missing in the user application.*/
 CC_WEAK ts_state_t ts_state[TS_MAX_SVCS];
 CC_WEAK const thread_descriptor_t ts_configs[TS_MAX_SVCS];
+CC_WEAK const fc_descriptor_t ts_fc_configs[1];
+uint32_t ts_fc_configs_n;
 
 /* The reference to the suspended NSEC main thread.*/
 thread_reference_t _ns_thread = NULL;
@@ -54,10 +66,31 @@ thread_reference_t _ns_thread = NULL;
 /* The services may broadcast and listen event flags via this object.*/
 EVENTSOURCE_DECL(tsEventSource);
 
+extern uint32_t __ram0_start__;
+
 /*===========================================================================*/
 /* Module local types.                                                       */
 /*===========================================================================*/
 
+struct fdt_header {
+  uint32_t magic;           /* magic word FDT_MAGIC */
+  uint32_t totalsize;       /* total size of DT block */
+  uint32_t off_dt_struct;   /* offset to structure */
+  uint32_t off_dt_strings;  /* offset to strings */
+  uint32_t off_mem_rsvmap;  /* offset to memory reserve map */
+  uint32_t version;         /* format version */
+  uint32_t last_comp_version;   /* last compatible version */
+
+  /* version 2 fields below */
+  uint32_t boot_cpuid_phys; /* Which physical CPU id we're
+                               booting on */
+  /* version 3 fields below */
+  uint32_t size_dt_strings; /* size of the strings block */
+
+  /* version 17 fields below */
+  uint32_t size_dt_struct;  /* size of the structure block */
+};
+
 /*===========================================================================*/
 /* Module local variables.                                                   */
 /*===========================================================================*/
@@ -69,6 +102,14 @@ static event_listener_t tsEventListener;
 /* Module local functions.                                                   */
 /*===========================================================================*/
 
+static inline uint32_t uswap32(uint32_t v)
+{
+  uint32_t result;
+
+  __asm volatile ("rev %0, %1" : "=r" (result) : "r" (v));
+  return result;
+}
+
 static bool isAddrSpaceValid(uint8_t *addr, size_t size)
 {
   if (size == 0)
@@ -134,12 +175,13 @@ static ts_state_t *findSvcsEntry(const char *name)
  * @notapi
  */
 int64_t smcEntry(ts_state_t *svc_handle, ts_params_area_t svc_data,
-               size_t svc_datalen, sysinterval_t svc_timeout) {
+               size_t svc_datalen, ts_timeint_t svc_timeout) {
   ts_state_t *tssp = NULL;
   msg_t r;
 
-  /* Internal query service.*/
   if (svc_handle == TS_HND_STQRY) {
+
+    /* Internal query status service.*/
     ts_state_t *tsqryd;
 
     /* svc_data is the handle of the service to whom 'query' the state.*/
@@ -159,7 +201,19 @@ int64_t smcEntry(ts_state_t *svc_handle, ts_params_area_t svc_data,
     if (!isAddrSpaceValid(svc_data, svc_datalen))
       return LOWORD(SMC_SVC_INVALID);
 
-    if (svc_handle == TS_HND_VERSION) {
+    uint32_t i = (uint32_t)svc_handle;
+
+    if ((i & TS_FASTCALL_MASK) == TS_FASTCALL_MASK) {
+
+      /* Fast call user service.*/
+      i &= ~TS_FASTCALL_MASK;
+
+      if (i >= ts_fc_configs_n)
+        return LOWORD(SMC_SVC_BADH);
+
+      return TS_FC_CONF_TABLE(i)->funcp(svc_data, svc_datalen);
+    }
+    else if (svc_handle == TS_HND_VERSION) {
 
       /* Internal get version service.*/
       return LOWORD(TSSI_VERSION);
@@ -181,13 +235,13 @@ int64_t smcEntry(ts_state_t *svc_handle, ts_params_area_t svc_data,
       if (!isHndlValid(svc_handle))
         return LOWORD(SMC_SVC_BADH);
       tssp = svc_handle;
-    }
 
-    /* If the service is not waiting requests, it's busy.*/
-    if (tssp->ts_thdp == NULL)
-      return LOWORD(SMC_SVC_BUSY);
-    tssp->ts_datap = svc_data;
-    tssp->ts_datalen = svc_datalen;
+      /* If the service is not waiting requests, it's busy.*/
+      if (tssp->ts_thdp == NULL)
+        return LOWORD(SMC_SVC_BUSY);
+      tssp->ts_datap = svc_data;
+      tssp->ts_datalen = svc_datalen;
+    }
   }
 
 #if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
@@ -200,7 +254,11 @@ int64_t smcEntry(ts_state_t *svc_handle, ts_params_area_t svc_data,
 
   if (tssp)
     chThdResumeS(&tssp->ts_thdp, MSG_OK);
-  r = chThdSuspendTimeoutS(&_ns_thread, TIME_US2I(svc_timeout));
+  r = chThdSuspendTimeoutS(&_ns_thread, TS_TIME2I(svc_timeout));
+
+  /* Map MSG_TIMEOUT to SMC_SVC_INTR.*/
+  if (r == MSG_TIMEOUT)
+    r = SMC_SVC_INTR;
 
   /* Get and clear any pending event flags.*/
   eventflags_t f = chEvtGetAndClearFlagsI(&tsEventListener);
@@ -233,7 +291,7 @@ msg_t tssiWaitRequest(ts_state_t *svcp)
   chSysLock();
   if (_ns_thread) {
     /* Ack a previous service invocation. Not schedule.*/
-    chThdResumeI(&_ns_thread, svcp->ts_status);
+    chThdResumeI(&_ns_thread, SMC_SVC_INTR);
   }
   r = chThdSuspendS(&svcp->ts_thdp);
   chSysUnlock();
@@ -266,26 +324,36 @@ CC_NO_RETURN void tssiInit(void)
   int32_t i;
   uint32_t d;
   uint32_t *tt;
+  struct fdt_header *pfdt = (struct fdt_header *)NSEC_MEMORY_START_ADDR;
+  void *moveto = NULL;
 
   /*
    * The main DDR memory, PORT0, is divided in 4 region, each 32MB large.
    * The last region is split in two areas, each 16MB large.
    * The first 3 region and the lower area of this last region is non secure.
    * All the rest of the regions space is secured.
-   * The same applies to AESB view of the DDR, PORT1
+   * The same applies to AESB view of the DDR, PORT1, and LCDC view.
    *
    * Those settings depend on the designed memory mapping.
    */
   mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT0, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
   mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT1, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
+  mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT2, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
+  mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT3, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
 
   mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT0, MATRIX_AREA_SIZE_32M,
       REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
   mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT1, MATRIX_AREA_SIZE_32M,
       REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
+  mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT2, MATRIX_AREA_SIZE_32M,
+      REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
+  mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT3, MATRIX_AREA_SIZE_32M,
+      REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
 
   mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT0, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
   mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT1, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
+  mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT2, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
+  mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT3, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
 
   mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_DDR_PORT0,
       mtxRegionLansech(REGION_0, UPPER_AREA_SECURABLE) |
@@ -311,7 +379,31 @@ CC_NO_RETURN void tssiInit(void)
       mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
       mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
 
-#if !HAL_USE_SDMMC
+  mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_DDR_PORT2,
+      mtxRegionLansech(REGION_0, UPPER_AREA_SECURABLE) |
+      mtxRegionLansech(REGION_1, UPPER_AREA_SECURABLE) |
+      mtxRegionLansech(REGION_2, UPPER_AREA_SECURABLE) |
+      mtxRegionLansech(REGION_3, UPPER_AREA_SECURABLE),
+      mtxRegionRdnsech(REGION_0, NOT_SECURE_READ) |
+      mtxRegionRdnsech(REGION_1, NOT_SECURE_READ) |
+      mtxRegionRdnsech(REGION_2, NOT_SECURE_READ),
+      mtxRegionWrnsech(REGION_0, NOT_SECURE_WRITE) |
+      mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
+      mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
+
+  mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_DDR_PORT3,
+      mtxRegionLansech(REGION_0, UPPER_AREA_SECURABLE) |
+      mtxRegionLansech(REGION_1, UPPER_AREA_SECURABLE) |
+      mtxRegionLansech(REGION_2, UPPER_AREA_SECURABLE) |
+      mtxRegionLansech(REGION_3, UPPER_AREA_SECURABLE),
+      mtxRegionRdnsech(REGION_0, NOT_SECURE_READ) |
+      mtxRegionRdnsech(REGION_1, NOT_SECURE_READ) |
+      mtxRegionRdnsech(REGION_2, NOT_SECURE_READ),
+      mtxRegionWrnsech(REGION_0, NOT_SECURE_WRITE) |
+      mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
+      mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
+
+#if !SAMA_USE_SDMMC
 
   /* Configure the SDMMCx regions as non secure.*/
   mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_SDMMC, MATRIX_AREA_SIZE_128M, REGION_1_MSK|REGION_2_MSK);
@@ -324,15 +416,31 @@ CC_NO_RETURN void tssiInit(void)
       mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
 #endif
 
-  /* Mark the whole non secure memory region as non executable
-     by the secure side.*/
+  /* Mark the whole non secure memory region non executable
+     by the secure side, and set the Non-Secure access bit, so that
+     any access to this region is in the non-secure physical
+     space. This ensures the coherence of the cache between
+     secure and non secure accesses.*/
   tt = (uint32_t *)(__get_TTBR0() & 0xFFFFC000);
   for (d = ((uint32_t)NSEC_MEMORY_START_ADDR >> 20);
        d < ((uint32_t)NSEC_MEMORY_END_ADDR >> 20); d += 1) {
+    MMU_SecureSection(tt + d, NON_SECURE);
+    MMU_XNSection(tt + d, NON_EXECUTE);
+  }
+
+  /* The same, but for the AESB view of the DDR memory region.*/
+  for (d = ((uint32_t)(NSEC_MEMORY_START_ADDR + 0x20000000) >> 20);
+       d < ((uint32_t)(NSEC_MEMORY_END_ADDR + 0x20000000) >> 20); d += 1) {
+    MMU_SecureSection(tt + d, NON_SECURE);
     MMU_XNSection(tt + d, NON_EXECUTE);
   }
   MMU_InvalidateTLB();
 
+  /* Flush the modified MMU table.*/
+  cacheCleanRegion(tt, d * sizeof (uint32_t));
+  __DSB();
+  __ISB();
+
   /* Make sure that prio is NORMALPRIO.*/
   chThdSetPriority(NORMALPRIO);
 
@@ -342,12 +450,12 @@ CC_NO_RETURN void tssiInit(void)
       continue;
 
     /* Check that the initialization of the TS_TABLE against TS_STATE_TABLE
-       was set right.*/
+       has been set right.*/
     if (TS_CONF_TABLE(i)->arg != TS_STATE(i)) {
       chSysHalt("Bad TS_STATE setting in the services configuration table.");
     }
 
-    /* Check that the service priority was set right.*/
+    /* Check that the service priority has been set right.*/
     if ((TS_CONF_TABLE(i)->prio <= NORMALPRIO) ||
         (TS_CONF_TABLE(i)->prio >= HIGHPRIO)) {
       chSysHalt("Bad prio setting in the services configuration table.");
@@ -357,25 +465,55 @@ CC_NO_RETURN void tssiInit(void)
     chThdCreate(TS_CONF_TABLE(i));
   }
 
+  /* Fast call services.*/
+  for (i = 0; TS_FC_CONF_TABLE(i)->name; ++i) {
+
+    /* Check that the 'code' field of the
+       fast call table has been set right.*/
+    if ((TS_FC_CONF_TABLE(i)->code &~ TS_FASTCALL_MASK) != (uint32_t)i) {
+      chSysHalt("Bad 'code' setting in the fast call configuration table.");
+    }
+  }
+  ts_fc_configs_n = i;
+
   /* Register to the daemon services events. All flags.*/
   chEvtRegister(&tsEventSource, &tsEventListener, EVT_DAEMON_REQ_ATN);
 
-  /* Now set the priority to the max.*/
+  /* Now set the priority at the max.*/
   chThdSetPriority(HIGHPRIO);
 
-  /* Remove write protection on PMC registers.*/
-  pmcDisableWP();
-
   /* Allow non secure access to CP10 and CP11.*/
   asm volatile (
-    "MRC p15, 0, r0, c1, c1, 2    \n"
-    "ORR r0, r0, #0b11<<10        \n"
-    "MCR p15, 0, r0, c1, c1, 2    \n"
+    "mrc p15, 0, r0, c1, c1, 2    \n"
+    "orr r0, r0, #0b11<<10        \n"
+    "mcr p15, 0, r0, c1, c1, 2    \n"
   );
 
+  /* Check if a fdt image exists at the start
+     of the non secure memory region.*/
+  if (uswap32(pfdt->magic) == FDT_MAGIC) {
+    uint32_t fdtsize;
+
+    /* Detected a fdt structure.
+       Move it to the end of non secure area.*/
+    fdtsize = uswap32(pfdt->totalsize);
+    fdtsize = (fdtsize + 4095) &~ 4095;
+    moveto = (void *)(SEC_MEMORY_START_ADDR - fdtsize);
+    memmove(moveto, pfdt, fdtsize);
+
+    /* Invalidate the original fdt image.*/
+    pfdt->magic = 0;
+  }
+
   /* Jump in the NON SECURE world.
      This thread becomes the non secure environment as view by
      the secure world.*/
+
+  /* r2 address of the moved fdt, if any.*/
+  asm volatile (
+    "mov r2, %0 \n" :: "r" (moveto)
+  );
+
   _ns_trampoline(NSEC_MEMORY_START_ADDR + NSEC_MEMORY_EXE_OFFSET);
 
   /* It never goes here.*/
diff --git a/os/common/ports/ARMCAx-TZ/chtssi.h b/os/common/ports/ARMCAx-TZ/chtssi.h
index ae9cec7af..ca3d7aa5f 100644
--- a/os/common/ports/ARMCAx-TZ/chtssi.h
+++ b/os/common/ports/ARMCAx-TZ/chtssi.h
@@ -1,5 +1,5 @@
 /*
-    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+    ChibiOS - Copyright (C) 2006..2018 Isidoro Orabona.
 
     This file is part of ChibiOS.
 
@@ -40,15 +40,16 @@
 #define TSSI_VERSION          0x01000000    /* 00 major, 000 minor, 000 build.*/
 
 /* Service registry errors as returned by smc.*/
-#define SMC_SVC_OK            MSG_OK        /* No error.*/
-#define SMC_SVC_INTR          (msg_t)-1     /* Service interrupted ( == MSG_TIMEOUT).*/
-#define SMC_SVC_NOENT         (msg_t)-2     /* No existent service.*/
-#define SMC_SVC_INVALID       (msg_t)-3     /* Invalid service parameter(s).*/
-#define SMC_SVC_BADH          (msg_t)-4     /* Invalid service handle.*/
-#define SMC_SVC_EXIST         (msg_t)-5     /* Service already exists.*/
-#define SMC_SVC_NHND          (msg_t)-6     /* No more services or
-                                               service resources.*/
-#define SMC_SVC_BUSY          (msg_t)-7     /* Service busy.*/
+#define SMC_SVC_OK            (int32_t)0      /* No error.*/
+#define SMC_SVC_INTR          (int32_t)-4     /* Service interrupted.*/
+#define SMC_SVC_NOENT         (int32_t)-2     /* No existent service.*/
+#define SMC_SVC_INVALID       (int32_t)-22    /* Invalid service
+                                                 parameter(s).*/
+#define SMC_SVC_BADH          (int32_t)-9     /* Invalid service handle.*/
+#define SMC_SVC_EXIST         (int32_t)-17    /* Service already exists.*/
+#define SMC_SVC_NHND          (int32_t)-23    /* No more services or
+                                                 service resources.*/
+#define SMC_SVC_BUSY          (int32_t)-16    /* Service busy.*/
 
 /* Special trusted service handles.*/
 #define TS_HND_TRAMP          ((ts_state_t *)0)  /* Trampoline service handle.*/
@@ -57,6 +58,11 @@
 #define TS_HND_IDLE           ((ts_state_t *)3)  /* Idle service handle.*/
 #define TS_HND_VERSION        ((ts_state_t *)4)  /* Get version service handle.*/
 
+/* Fast call service bitmask.
+   Service handles that contain this mask access to
+   the fast call table.*/
+#define TS_FASTCALL_MASK      0xFFFF0000
+
 /* Services events event mask.*/
 #define EVT_DAEMON_REQ_ATN    EVENT_MASK(0)
 
@@ -116,6 +122,30 @@ typedef struct tssi_service_state {
   uint32_t            ts_datalen;
 } ts_state_t;
 
+/**
+ * @brief   Fast call function.
+ */
+typedef msg_t (*fcfunc_t)(ts_params_area_t ts_datap, uint32_t ts_datalen);
+
+/**
+ * @brief   Type of a fast call descriptor.
+ */
+typedef struct {
+  /**
+   * @brief   Fast call service name.
+   */
+  const char  *name;
+
+  /* The code identifying the service.
+     Used for checking purpose, it must correspond to the
+     order that the service lists in the descriptor table.*/
+  uint32_t    code;
+  /**
+   * @brief   Fast call function pointer.
+   */
+  fcfunc_t    funcp;
+} fc_descriptor_t;
+
 /*===========================================================================*/
 /* Module macros.                                                            */
 /*===========================================================================*/
@@ -190,6 +220,48 @@ typedef struct tssi_service_state {
 
 /** @} */
 
+/**
+ * @name    Fast call table definition macros.
+ * @note    Fast call services run at max priority level, so it is
+ *          mandatory that they last less time as possible.
+ * @note    Fast call services should be invoked using
+ *          the tsInvoke0 function in order to optimize the
+ *          performances.
+ * @note    Fast call services don't have a runtime state, so
+ *          the response management is in charge to the higher levels.
+ * @{
+ */
+
+/**
+ * @brief   Start of user fast call service table.
+ */
+#define TS_FC_CONF_TABLE_BEGIN                                 \
+  const fc_descriptor_t ts_fc_configs[] = {
+
+/**
+ * @brief   Entry of user fast call services table.
+ */
+#define TS_FC_CONF_TABLE_ENTRY(name, code, funcp)               \
+  {name, code, funcp},
+
+/**
+ * @brief   End of user fast call services table.
+ */
+#define TS_FC_CONF_TABLE_END                                    \
+};
+
+/**
+ * @brief   Accessor to the fast call service table entry i.
+ */
+#define TS_FC_CONF_TABLE(i) (&ts_fc_configs[i])
+
+/**
+ * @brief   Number of entries in the fast call service table.
+ */
+#define TS_FC_CONF_TABLE_N (sizeof ts_fc_configs / sizeof ts_fc_configs[0])
+
+/** @} */
+
 /*===========================================================================*/
 /* External declarations.                                                    */
 /*===========================================================================*/
diff --git a/os/common/ports/ARMCAx-TZ/compilers/GCC/monitor.S b/os/common/ports/ARMCAx-TZ/compilers/GCC/monitor.S
index 647966b72..9a3faec34 100644
--- a/os/common/ports/ARMCAx-TZ/compilers/GCC/monitor.S
+++ b/os/common/ports/ARMCAx-TZ/compilers/GCC/monitor.S
@@ -66,7 +66,7 @@
                 .set    MON_S_SCR,      (SCR_IRQ)           // (SCR_EA|SCR_IRQ)
                 .set    MON_NS_SCR,     (SCR_FIQ|SCR_NS)
 
-                .set    SMC_SVC_INTR,   -1
+                .set    SMC_SVC_INTR,   -4
 
                 .comm   sm_secctx, 20*4, 4
                 .comm   sm_nsecctx, 20*4, 4
@@ -126,6 +126,7 @@
  * Monitor vectors
  */
 				.global _monitor_vectors
+				.balign 32
 _monitor_vectors:
                 b   .           // Reset vector, not used
                 b   .           // Undefined instruction, not used
@@ -281,7 +282,7 @@ _ns_trampoline:
                 cps     #MODE_SYS
 
                 ldr     r0, =#0
-                mov     r2, r0
+/*              mov     r2, r0  */              // r2 could contain the address of the fdt
                 mov     r3, r0
                 mov     r4, r0
                 mov     r5, r0
diff --git a/os/common/startup/ARM/compilers/GCC/ld/SAMA5D2bvddr.ld b/os/common/startup/ARM/compilers/GCC/ld/SAMA5D2bvddr.ld
deleted file mode 100755
index efa2f63d9..000000000
--- a/os/common/startup/ARM/compilers/GCC/ld/SAMA5D2bvddr.ld
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
-
-    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.
-*/
-
-/*
- * SAMA5D2 memory setup in non trusted mode.
- */
-MEMORY
-{
-    flash : org = 0x21000000, len = 16M
-    ram0  : org = 0x22000000, len = 96M
-    ram1  : org = 0x00000000, len = 0
-    ram2  : org = 0x00000000, len = 0
-    ram3  : org = 0x00000000, len = 0
-    ram4  : org = 0x00000000, len = 0
-    ram5  : org = 0x00000000, len = 0
-    ram6  : org = 0x00000000, len = 0
-    ram7  : org = 0x00000000, len = 0
-}
-
-/* RAM region to be used for stacks. This stack accommodates the processing
-   of all exceptions and interrupts*/
-REGION_ALIAS("STACKS_RAM", ram0);
-
-/* RAM region to be used for data segment.*/
-REGION_ALIAS("DATA_RAM", ram0);
-
-/* RAM region to be used for BSS segment.*/
-REGION_ALIAS("BSS_RAM", ram0);
-
-INCLUDE rules.ld
-
-ENTRY(Boot_Handler);
-
diff --git a/os/common/startup/ARM/compilers/GCC/ld/SAMA5D2ddr.ld b/os/common/startup/ARM/compilers/GCC/ld/SAMA5D2ddr.ld
index e2bcb004a..087234cbf 100755
--- a/os/common/startup/ARM/compilers/GCC/ld/SAMA5D2ddr.ld
+++ b/os/common/startup/ARM/compilers/GCC/ld/SAMA5D2ddr.ld
@@ -19,10 +19,10 @@
  */
 MEMORY
 {
-    flash : org = 0x20000000, len = 16M
-    ram0  : org = 0x21000000, len = 96M
-    ram1  : org = 0x00000000, len = 0
-    ram2  : org = 0x00000000, len = 0
+    flash : org = 0x21000000, len = 16M
+    ram0  : org = 0x22000000, len = 78M
+    ram1  : org = 0x26E00000, len = 1M
+    ram2  : org = 0x26F00000, len = 1M
     ram3  : org = 0x00000000, len = 0
     ram4  : org = 0x00000000, len = 0
     ram5  : org = 0x00000000, len = 0
@@ -40,6 +40,37 @@ REGION_ALIAS("DATA_RAM", ram0);
 /* RAM region to be used for BSS segment.*/
 REGION_ALIAS("BSS_RAM", ram0);
 
+/* RAM region to be used for lcd frame buffer. */
+REGION_ALIAS("FB_RAM", ram1);
+
+/* RAM region to be used for no cache area. */
+REGION_ALIAS("NO_CACHE", ram2);
+
+SECTIONS
+{
+    /* Special section for frame buffer area.*/
+    .fbram (NOLOAD) : ALIGN(4)
+    {
+        __fbram_base__ = .;
+        *(.fbram)
+        *(.fbram.*)
+        *(.bss.__fbram_*)
+        . = ALIGN(4);
+        __fbram_end__ = .;
+    } > FB_RAM
+    
+    /* Special section for no cache area.*/
+    .nocache (NOLOAD) : ALIGN(4)
+    {
+        __nocache_base__ = .;
+        *(.nocache)
+        *(.nocache.*)
+        *(.bss.__nocache_*)
+        . = ALIGN(4);
+        __nocache_end__ = .;
+    } > NO_CACHE
+}
+
 INCLUDE rules.ld
 
 ENTRY(Boot_Handler);
diff --git a/os/common/startup/ARM/devices/SAMA5D2/mmu.c b/os/common/startup/ARM/devices/SAMA5D2/mmu.c
index a4f3b0ea0..449019526 100644
--- a/os/common/startup/ARM/devices/SAMA5D2/mmu.c
+++ b/os/common/startup/ARM/devices/SAMA5D2/mmu.c
@@ -48,9 +48,17 @@
 #define SAMA_L2CC_ENABLE 0
 #endif
 
+#if (SAMA_L2CC_ASSUME_ENABLED && SAMA_L2CC_ENABLE)
+#error "These macros are mutually exclusive"
+#endif
+
 /*===========================================================================*/
 /* Module local definitions.                                                 */
 /*===========================================================================*/
+/*
+ * @brief    No cacheable memory start address.
+ */
+#define NO_CACHE_MEMORY_START_ADDR      ((uint8_t *) 0x26F00000)
 
 /*===========================================================================*/
 /* Module exported variables.                                                */
@@ -77,7 +85,7 @@
  * +---------+--+-+--+-+-----+--------+-------+-+------+--+-+-+-+---+
  * | section |NS|0|nG|S|AP[2]|TEX[2:0]|AP[1:0]| |domain|XN|C|B|1|PXN|
  * +---------+--+-+--+-+-----+--------+-------+-+------+--+-+-+-+---+
- * |         |0 |0|0 |1|0    |111     |11     |0|0000  |0 |1|1|1|0  | == normal, cacheable
+ * |         |X |0|0 |0|0    |111     |11     |0|0000  |0 |1|1|1|0  | == normal, cacheable, write back, no write allocate
  * |         |0 |0|0 |1|0    |100     |11     |0|0000  |0 |0|0|1|0  | == normal, no-cacheable
  * |         |0 |0|0 |1|0    |000     |11     |0|0000  |0 |0|1|1|0  | == device
  * |         |0 |0|0 |1|0    |000     |11     |0|0000  |0 |0|0|1|0  | == strongly-ordered
@@ -121,8 +129,8 @@ void __core_init(void) {
      Invalidate a disabled L1 D Cache.*/
   pm = __get_SCTLR();
   if ((pm & SCTLR_C_Msk)) {
-    L1C_CleanInvalidateCache(DCISW_CLEAN);
     L1C_DisableCaches();
+    L1C_CleanInvalidateCache(DCISW_CLEAN);
   }
 
   /* Disable the MMU and invalidate TLB.*/
@@ -164,7 +172,7 @@ void __core_init(void) {
                   TTE_SECT_MEM_CACHEABLE |
                   TTE_SECT_RW_ACCESS |
                   TTE_SECT_DOM(0x00) |
-                  TTE_SECT_S | TTE_TYPE_SECT;
+                  TTE_TYPE_SECT;
   /*
    * UDPHS RAM region
    *
@@ -264,7 +272,7 @@ void __core_init(void) {
                     TTE_SECT_MEM_CACHEABLE |
                     TTE_SECT_RW_ACCESS |
                     TTE_SECT_DOM(0x00) |
-                    TTE_SECT_S | TTE_TYPE_SECT;
+                    TTE_TYPE_SECT;
   /*
    * DDR AESB regions
    *
@@ -275,7 +283,7 @@ void __core_init(void) {
                     TTE_SECT_MEM_CACHEABLE |
                     TTE_SECT_RW_ACCESS |
                     TTE_SECT_DOM(0x00) |
-                    TTE_SECT_S | TTE_TYPE_SECT;
+                    TTE_TYPE_SECT;
   /*
    * EBI 1, 2 and 3 regions
    *
@@ -360,6 +368,9 @@ void __core_init(void) {
                   TTE_SECT_EXE_NEVER |
                   TTE_SECT_S | TTE_TYPE_SECT;
 
+  /* Make a NO CACHE AREA */
+  MMU_MemorySection((mmuTable + ((uint32_t)NO_CACHE_MEMORY_START_ADDR >> 20)), NORMAL, NON_CACHEABLE, NON_CACHEABLE);
+
   /* Invalidate TLB and L1 I cache
      Enable caches and MMU.*/
   MMU_InvalidateTLB();
@@ -395,11 +406,17 @@ void __core_init(void) {
 
     /* Invalidate and enable L2 cache.*/
     L2C_InvAllByWay();
+    L2C_310->AUX_CNT = L2CC_ACR_DPEN | L2CC_ACR_IPEN;
+
+    /* Prefetch control register. Double linefeed, instr and data enabled.*/
+    *((uint32_t *)((char *)L2C_310+0x0F60)) = 0x75800001;
     L2C_Enable();
     __DSB();
     __ISB();
   }
 #endif
+
+
 #endif
 }
 
diff --git a/os/common/startup/ARMCAx-TZ/compilers/GCC/crt0.S b/os/common/startup/ARMCAx-TZ/compilers/GCC/crt0.S
index 4810ea0f6..016e23c58 100644
--- a/os/common/startup/ARMCAx-TZ/compilers/GCC/crt0.S
+++ b/os/common/startup/ARMCAx-TZ/compilers/GCC/crt0.S
@@ -22,6 +22,20 @@
  * @{
  */
 
+/**
+ * @brief   Constructors invocation switch.
+ */
+#if !defined(CRT0_CALL_CONSTRUCTORS) || defined(__DOXYGEN__)
+#define CRT0_CALL_CONSTRUCTORS              TRUE
+#endif
+
+/**
+ * @brief   Destructors invocation switch.
+ */
+#if !defined(CRT0_CALL_DESTRUCTORS) || defined(__DOXYGEN__)
+#define CRT0_CALL_DESTRUCTORS               TRUE
+#endif
+
 #if !defined(__DOXYGEN__)
 
                 .set    MODE_USR, 0x10
@@ -117,10 +131,38 @@ bssloop:
                  */
                 bl      __core_init
                 bl      __late_init
+#if 0 /* Constructors initialized after halInit() */
+#if CRT0_CALL_CONSTRUCTORS == TRUE
+                /* Constructors invocation.*/
+                ldr     r4, =__init_array_start
+                ldr     r5, =__init_array_end
+initloop:
+                cmp     r4, r5
+                bge     endinitloop
+                ldr     r1, [r4], #4
+                blx     r1
+                b       initloop
+endinitloop:
+#endif /* CRT0_CALL_CONSTRUCTORS */
+#endif /* if 0 */
                 /*
                  * Main program invocation.
                  */
                 bl      main
+
+#if CRT0_CALL_DESTRUCTORS == TRUE
+                /* Destructors invocation.*/
+                ldr     r4, =__fini_array_start
+                ldr     r5, =__fini_array_end
+finiloop:
+                cmp     r4, r5
+                bge     endfiniloop
+                ldr     r1, [r4], #4
+                blx     r1
+                b       finiloop
+endfiniloop:
+#endif
+
                 b       __default_exit
 
 #endif /* !defined(__DOXYGEN__) */
diff --git a/os/common/startup/ARMCAx-TZ/compilers/GCC/ld/SAMA5D2ddr.ld b/os/common/startup/ARMCAx-TZ/compilers/GCC/ld/SAMA5D2ddr.ld
index 225f64d74..cb016edc0 100644
--- a/os/common/startup/ARMCAx-TZ/compilers/GCC/ld/SAMA5D2ddr.ld
+++ b/os/common/startup/ARMCAx-TZ/compilers/GCC/ld/SAMA5D2ddr.ld
@@ -20,9 +20,9 @@
 MEMORY
 {
     flash : org = 0x27000000, len = 1M
-    ram0  : org = 0x27100000, len = 15M
-    ram1  : org = 0x00000000, len = 0
-    ram2  : org = 0x00000000, len = 0
+    ram0  : org = 0x27100000, len = 13M
+    ram1  : org = 0x27E00000, len = 1M
+    ram2  : org = 0x27F00000, len = 1M
     ram3  : org = 0x00000000, len = 0
     ram4  : org = 0x00000000, len = 0
     ram5  : org = 0x00000000, len = 0
@@ -40,6 +40,37 @@ REGION_ALIAS("DATA_RAM", ram0);
 /* RAM region to be used for BSS segment.*/
 REGION_ALIAS("BSS_RAM", ram0);
 
+/* RAM region to be used for lcd frame buffer. */
+REGION_ALIAS("FB_RAM", ram1);
+
+/* RAM region to be used for no cache area. */
+REGION_ALIAS("NO_CACHE", ram2);
+
+SECTIONS
+{
+    /* Special section for frame buffer area.*/
+    .fbram (NOLOAD) : ALIGN(4)
+    {
+        __fbram_base__ = .;
+        *(.fbram)
+        *(.fbram.*)
+        *(.bss.__fbram_*)
+        . = ALIGN(4);
+        __fbram_end__ = .;
+    } > FB_RAM
+    
+    /* Special section for no cache area.*/
+    .nocache (NOLOAD) : ALIGN(4)
+    {
+        __nocache_base__ = .;
+        *(.nocache)
+        *(.nocache.*)
+        *(.bss.__nocache_*)
+        . = ALIGN(4);
+        __nocache_end__ = .;
+    } > NO_CACHE
+}
+
 INCLUDE rules.ld
 
 ENTRY(Boot_Handler);
diff --git a/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.c b/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.c
index ab063dcfc..b4af836c0 100644
--- a/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.c
+++ b/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.c
@@ -48,9 +48,17 @@
 #define SAMA_L2CC_ENABLE 0
 #endif
 
+#if (SAMA_L2CC_ASSUME_ENABLED && SAMA_L2CC_ENABLE)
+#error "These macros are mutually exclusive"
+#endif
+
 /*===========================================================================*/
 /* Module local definitions.                                                 */
 /*===========================================================================*/
+/*
+ * @brief    No cacheable memory start address.
+ */
+#define NO_CACHE_MEMORY_START_ADDR      ((uint8_t *) 0x27F00000)
 
 /*===========================================================================*/
 /* Module exported variables.                                                */
@@ -77,7 +85,7 @@
  * +---------+--+-+--+-+-----+--------+-------+-+------+--+-+-+-+---+
  * | section |NS|0|nG|S|AP[2]|TEX[2:0]|AP[1:0]| |domain|XN|C|B|1|PXN|
  * +---------+--+-+--+-+-----+--------+-------+-+------+--+-+-+-+---+
- * |         |0 |0|0 |1|0    |111     |11     |0|0000  |0 |1|1|1|0  | == normal, cacheable
+ * |         |0 |0|0 |0|0    |111     |11     |0|0000  |0 |1|1|1|0  | == normal, cacheable, write back, no write allocate
  * |         |0 |0|0 |1|0    |100     |11     |0|0000  |0 |0|0|1|0  | == normal, no-cacheable
  * |         |0 |0|0 |1|0    |000     |11     |0|0000  |0 |0|1|1|0  | == device
  * |         |0 |0|0 |1|0    |000     |11     |0|0000  |0 |0|0|1|0  | == strongly-ordered
@@ -164,7 +172,7 @@ void __core_init(void) {
                   TTE_SECT_MEM_CACHEABLE |
                   TTE_SECT_RW_ACCESS |
                   TTE_SECT_DOM(0x00) |
-                  TTE_SECT_S | TTE_TYPE_SECT;
+                  TTE_TYPE_SECT;
   /*
    * UDPHS RAM region
    *
@@ -264,7 +272,7 @@ void __core_init(void) {
                     TTE_SECT_MEM_CACHEABLE |
                     TTE_SECT_RW_ACCESS |
                     TTE_SECT_DOM(0x00) |
-                    TTE_SECT_S | TTE_TYPE_SECT;
+                    TTE_TYPE_SECT;
   /*
    * DDR AESB regions
    *
@@ -275,7 +283,7 @@ void __core_init(void) {
                     TTE_SECT_MEM_CACHEABLE |
                     TTE_SECT_RW_ACCESS |
                     TTE_SECT_DOM(0x00) |
-                    TTE_SECT_S | TTE_TYPE_SECT;
+                    TTE_TYPE_SECT;
   /*
    * EBI 1, 2 and 3 regions
    *
@@ -360,6 +368,9 @@ void __core_init(void) {
                   TTE_SECT_EXE_NEVER |
                   TTE_SECT_S | TTE_TYPE_SECT;
 
+  /* Make a NO CACHE AREA */
+  MMU_MemorySection((mmuTable + ((uint32_t)NO_CACHE_MEMORY_START_ADDR >> 20)), NORMAL, NON_CACHEABLE, NON_CACHEABLE);
+
   /* Invalidate TLB and L1 I cache
      Enable caches and MMU.*/
   MMU_InvalidateTLB();
@@ -395,11 +406,17 @@ void __core_init(void) {
 
     /* Invalidate and enable L2 cache.*/
     L2C_InvAllByWay();
+    L2C_310->AUX_CNT = L2CC_ACR_DPEN | L2CC_ACR_IPEN;
+
+    /* Prefetch control register. Double linefeed, instr and data enabled.*/
+    *((uint32_t *)((char *)L2C_310+0x0F60)) = 0x75800001;
     L2C_Enable();
     __DSB();
     __ISB();
   }
 #endif
+
+
 #endif
 }
 
diff --git a/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.h b/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.h
index 95ef15854..4392fe222 100644
--- a/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.h
+++ b/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/mmu.h
@@ -31,7 +31,6 @@
 /*===========================================================================*/
 /* Module constants.                                                         */
 /*===========================================================================*/
-
 #define DCISW_INVALIDATE    0
 #define DCISW_CLEAN         1
 #define DCISW_CLEAN_AND_INV 2
@@ -44,6 +43,7 @@
 /* Derived constants and error checks.                                       */
 /*===========================================================================*/
 
+
 /*===========================================================================*/
 /* Module data structures and types.                                         */
 /*===========================================================================*/
diff --git a/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/sama5d2x.h b/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/sama5d2x.h
index 6aad3e035..1d711bf0b 100644
--- a/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/sama5d2x.h
+++ b/os/common/startup/ARMCAx-TZ/devices/SAMA5D2/sama5d2x.h
@@ -64,8 +64,10 @@
 
 /**@} */
 
+#ifndef GBC_DISABLE_AES_REFERENCE
 /* TODO: to delete */
 #define Aes wc_Aes
+#endif
 
 /**
   * @brief SAMA5D2 Family
diff --git a/os/hal/boards/ATSAMA5D27_SOM1/board.c b/os/hal/boards/ATSAMA5D27_SOM1/board.c
new file mode 100644
index 000000000..76c87ed9d
--- /dev/null
+++ b/os/hal/boards/ATSAMA5D27_SOM1/board.c
@@ -0,0 +1,289 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    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 "hal.h"
+
+#define _PIOA                       ((Pio*)0xFC038000U)
+/*
+ * SAMA PIO CFGR masks.
+ */
+#define SAMA_PIO_FUNC_GPIO          0U
+#define SAMA_PIO_FUNC_PERIPH_A      1U
+#define SAMA_PIO_FUNC_PERIPH_B      2U
+#define SAMA_PIO_FUNC_PERIPH_C      3U
+#define SAMA_PIO_FUNC_PERIPH_D      4U
+#define SAMA_PIO_FUNC_PERIPH_E      5U
+#define SAMA_PIO_FUNC_PERIPH_F      6U
+#define SAMA_PIO_FUNC_PERIPH_G      7U
+#define SAMA_PIO_FUNC(n)            (n)
+#define SAMA_PIO_DIR_INPUT          (0U)
+#define SAMA_PIO_DIR_OUTPUT         (1U << 8U)
+#define SAMA_PIO_PUEN               (1U << 9U)
+#define SAMA_PIO_PDEN               (1U << 10U)
+#define SAMA_PIO_IFEN               (1U << 12U)
+#define SAMA_PIO_IFSCEN             (1U << 13U)
+#define SAMA_PIO_OPD                (1U << 14U)
+#define SAMA_PIO_SCHMITT            (1U << 15U)
+#define SAMA_PIO_DRVSTR_LO          (0U << 16U)
+#define SAMA_PIO_DRVSTR_ME          (2U << 16U)
+#define SAMA_PIO_DRVSTR_HI          (3U << 16U)
+
+#define SAMA_PIO_LOW                0U
+#define SAMA_PIO_HIGH               1U
+/*
+ * SAMA PIO default SIOSR, MSKR and CFGR values.
+ */
+#define SAMA_DEFAULT_SIOSR          0x00000000U
+#define SAMA_DEFAULT_SIONR          0xFFFFFFFFU
+#define SAMA_DEFAULT_MSKR           0xFFFFFFFFU
+#define SAMA_DEFAULT_CFGR           SAMA_PIO_FUNC_GPIO | SAMA_PIO_PUEN |    \
+                                    SAMA_PIO_DIR_INPUT | SAMA_PIO_SCHMITT
+
+/*
+ * This macro converts a pin identifier to a bitmask.
+ */
+#define SAMA_PIN_N(n)               (1U << n)
+
+/**
+ * @brief   SIU/SIUL register initializer type.
+ */
+typedef struct {
+  int32_t pio_id;
+  uint32_t pio_msk;
+  uint32_t pio_cfg;
+  uint32_t pio_ods;
+} sama_pio_init_t;
+
+/*
+ * @brief   Initial setup of all defined pads.
+ * @note    All pads are secured when SAMA_HAL_IS_SECURE is set as @p TRUE.
+ * @note    The list is terminated by a {-1, 0, 0, 0}
+ */
+static const sama_pio_init_t sama_inits[] = {
+  /* RGB Led Red and Led Blue */
+  {SAMA_PIOA,
+   SAMA_PIN_N(PIOA_LED_BLUE) | SAMA_PIN_N(PIOA_LED_RED),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_OUTPUT | SAMA_PIO_DRVSTR_HI,
+   SAMA_PIO_LOW},
+  /* RGB Led Green */
+  {SAMA_PIOB,
+   SAMA_PIN_N(PIOB_LED_GREEN),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_OUTPUT | SAMA_PIO_DRVSTR_HI,
+   SAMA_PIO_LOW},
+  /* User Button */
+  {SAMA_PIOA,
+   SAMA_PIN_N(PIOA_USER_PB),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_INPUT | SAMA_PIO_PUEN | SAMA_PIO_SCHMITT,
+   SAMA_PIO_LOW},
+  /* QSPI1 */
+  {SAMA_PIOB,
+   SAMA_PIN_N(PIOB_QSPI1_SCK) | SAMA_PIN_N(PIOB_QSPI1_CS) |
+   SAMA_PIN_N(PIOB_QSPI1_IO0) | SAMA_PIN_N(PIOB_QSPI1_IO1) |
+   SAMA_PIN_N(PIOB_QSPI1_IO2) | SAMA_PIN_N(PIOB_QSPI1_IO3),
+   SAMA_PIO_FUNC_PERIPH_D | SAMA_PIO_PUEN,
+   SAMA_PIO_HIGH},
+  /* UART1 */
+  {SAMA_PIOD,
+   SAMA_PIN_N(PIOD_URXD1) | SAMA_PIN_N(PIOD_UTXD1),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  /* UART2 */
+  {SAMA_PIOD,
+   SAMA_PIN_N(PIOD_URXD2) | SAMA_PIN_N(PIOD_UTXD2),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  /* UART4 */
+  {SAMA_PIOB,
+   SAMA_PIN_N(PIOB_URXD4) | SAMA_PIN_N(PIOB_UTXD4),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  /* FLEXSPI4 */
+  {SAMA_PIOC,
+   SAMA_PIN_N(PIOC_SPI_FLEXCOM4_IO0) |
+   SAMA_PIN_N(PIOC_SPI_FLEXCOM4_IO1) |
+   SAMA_PIN_N(PIOC_SPI_FLEXCOM4_IO2) |
+   SAMA_PIN_N(PIOC_SPI_FLEXCOM4_IO3),
+   SAMA_PIO_FUNC_PERIPH_B,
+   SAMA_PIO_HIGH},
+  {SAMA_PIOD,
+   SAMA_PIN_N(PIOD_SPI_FLEXCOM4_IO4),
+   SAMA_PIO_FUNC_PERIPH_B,
+   SAMA_PIO_HIGH},
+  /* IRQ9 */
+  {SAMA_PIOC,
+   SAMA_PIN_N(PIOC_IRQ9),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_INPUT | SAMA_PIO_PDEN,
+   SAMA_PIO_LOW},
+  /* PIOD_IRQ1 Touch */
+  {SAMA_PIOD,
+   SAMA_PIN_N(PIOD_IRQ1),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_INPUT | SAMA_PIO_PUEN | SAMA_PIO_SCHMITT,
+   SAMA_PIO_HIGH},
+  /* LCDC */
+  {SAMA_PIOB,
+   SAMA_PIN_N(PIOB_LCDDAT0) | SAMA_PIN_N(PIOB_LCDDAT1) |
+   SAMA_PIN_N(PIOB_LCDDAT2) | SAMA_PIN_N(PIOB_LCDDAT3) |
+   SAMA_PIN_N(PIOB_LCDDAT4) | SAMA_PIN_N(PIOB_LCDDAT5) |
+   SAMA_PIN_N(PIOB_LCDDAT6) | SAMA_PIN_N(PIOB_LCDDAT7) |
+   SAMA_PIN_N(PIOB_LCDDAT8) | SAMA_PIN_N(PIOB_LCDDAT9) |
+   SAMA_PIN_N(PIOB_LCDDAT10) | SAMA_PIN_N(PIOB_LCDDAT11) |
+   SAMA_PIN_N(PIOB_LCDDAT12) | SAMA_PIN_N(PIOB_LCDDAT13) |
+   SAMA_PIN_N(PIOB_LCDDAT14) | SAMA_PIN_N(PIOB_LCDDAT15) |
+   SAMA_PIN_N(PIOB_LCDDAT16) | SAMA_PIN_N(PIOB_LCDDAT17) |
+   SAMA_PIN_N(PIOB_LCDDAT18) | SAMA_PIN_N(PIOB_LCDDAT19) |
+   SAMA_PIN_N(PIOB_LCDDAT20),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  {SAMA_PIOC,
+   SAMA_PIN_N(PIOC_LCDDAT21) | SAMA_PIN_N(PIOC_LCDDAT22) |
+   SAMA_PIN_N(PIOC_LCDDAT23) | SAMA_PIN_N(PIOC_LCDPWM) |
+   SAMA_PIN_N(PIOC_LCDDISP) | SAMA_PIN_N(PIOC_LCDVSYNC) |
+   SAMA_PIN_N(PIOC_LCDHSYNC) | SAMA_PIN_N(PIOC_LCDPCK) |
+   SAMA_PIN_N(PIOC_LCDDEN),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  /* MMC Slot0 pads -J12 SD card */
+  {SAMA_PIOA,
+   SAMA_PIN_N(PIOA_SDMMC0_CK) | SAMA_PIN_N(PIOA_SDMMC0_CMD) |
+   SAMA_PIN_N(PIOA_SDMMC0_DAT0) | SAMA_PIN_N(PIOA_SDMMC0_DAT1) |
+   SAMA_PIN_N(PIOA_SDMMC0_DAT2) | SAMA_PIN_N(PIOA_SDMMC0_DAT3) |
+   SAMA_PIN_N(PIOA_SDMMC0_DAT4) | SAMA_PIN_N(PIOA_SDMMC0_DAT5) |
+   SAMA_PIN_N(PIOA_SDMMC0_DAT6) | SAMA_PIN_N(PIOA_SDMMC0_DAT7) |
+   SAMA_PIN_N(PIOA_SDMMC0_WP) | SAMA_PIN_N(PIOA_SDMMC0_CD) |
+   SAMA_PIN_N(PIOA_SDMMC0_VDDSEL),
+   SAMA_PIO_FUNC_PERIPH_A | SAMA_PIO_DRVSTR_HI,
+   SAMA_PIO_HIGH},
+   /* MMC Slot1 pads -J14 MicroSD card */
+  {SAMA_PIOA,
+   SAMA_PIN_N(PIOA_SDMMC1_CK) | SAMA_PIN_N(PIOA_SDMMC1_CMD) |
+   SAMA_PIN_N(PIOA_SDMMC1_DAT0) | SAMA_PIN_N(PIOA_SDMMC1_DAT1) |
+   SAMA_PIN_N(PIOA_SDMMC1_DAT2) | SAMA_PIN_N(PIOA_SDMMC1_DAT3) |
+   SAMA_PIN_N(PIOA_SDMMC1_CD),
+   SAMA_PIO_FUNC_PERIPH_E | SAMA_PIO_DRVSTR_HI,
+   SAMA_PIO_HIGH},
+  /* list terminated*/
+  {-1, 0, 0, 0}
+};
+
+/**
+ * @brief   Early initialization code.
+ * @details This initialization must be performed just after stack setup
+ *          and before any other initialization.
+ */
+void __early_init(void) {
+
+  sama_clock_init();
+  /* Configures ETH's pins */
+#if SAMA_HAL_IS_SECURE
+  palSetGroupMode(PIOD, PAL_PORT_BIT(PIOD_ETH_GTXCK) | PAL_PORT_BIT(PIOD_ETH_GTXEN) |
+                  PAL_PORT_BIT(PIOD_ETH_GRXDV) | PAL_PORT_BIT(PIOD_ETH_GRXER) |
+                  PAL_PORT_BIT(PIOD_ETH_GRX0) | PAL_PORT_BIT(PIOD_ETH_GRX1) |
+                  PAL_PORT_BIT(PIOD_ETH_GTX0) | PAL_PORT_BIT(PIOD_ETH_GTX1) |
+                  PAL_PORT_BIT(PIOD_ETH_GMDC) | PAL_PORT_BIT(PIOD_ETH_GMDIO),
+                  0U, PAL_SAMA_FUNC_PERIPH_D  |  PAL_MODE_SECURE);
+#else
+  palSetGroupMode(PIOD, PAL_PORT_BIT(PIOD_ETH_GTXCK) | PAL_PORT_BIT(PIOD_ETH_GTXEN) |
+                  PAL_PORT_BIT(PIOD_ETH_GRXDV) | PAL_PORT_BIT(PIOD_ETH_GRXER) |
+                  PAL_PORT_BIT(PIOD_ETH_GRX0) | PAL_PORT_BIT(PIOD_ETH_GRX1) |
+                  PAL_PORT_BIT(PIOD_ETH_GTX0) | PAL_PORT_BIT(PIOD_ETH_GTX1) |
+                  PAL_PORT_BIT(PIOD_ETH_GMDC) | PAL_PORT_BIT(PIOD_ETH_GMDIO),
+                  0U, PAL_SAMA_FUNC_PERIPH_D);
+#endif
+}
+
+/**
+ * @brief   Board-specific initialization code.
+ */
+void boardInit(void) {
+  unsigned i;
+
+#if SAMA_HAL_IS_SECURE
+  /* Disabling PMC write protection. */
+  pmcDisableWP();
+
+  /* Enabling port clock. */
+  pmcEnablePIO();
+
+  /* Enabling write protection.  */
+  pmcEnableWP();
+#endif /* SAMA_HAL_IS_SECURE */
+
+  /* Configuring all PIO A pads with default configuration.  */
+#if SAMA_HAS_PIOA
+#if SAMA_HAL_IS_SECURE
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_SIOSR = SAMA_DEFAULT_SIOSR;
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_SIONR = SAMA_DEFAULT_SIONR;
+#endif /* SAMA_HAL_IS_SECURE */
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOA */
+
+  /* Configuring all PIO B pads with default configuration.  */
+#if SAMA_HAS_PIOB
+#if SAMA_HAL_IS_SECURE
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_SIOSR = SAMA_DEFAULT_SIOSR;
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_SIONR = SAMA_DEFAULT_SIONR;
+#endif /* SAMA_HAL_IS_SECURE */
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOB */
+
+  /* Configuring all PIO C pads with default configuration.  */
+#if SAMA_HAS_PIOC
+#if SAMA_HAL_IS_SECURE
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_SIOSR = SAMA_DEFAULT_SIOSR;
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_SIONR = SAMA_DEFAULT_SIONR;
+#endif /* SAMA_HAL_IS_SECURE */
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOC */
+
+  /* Configuring all PIO D pads with default configuration.  */
+#if SAMA_HAS_PIOD
+#if SAMA_HAL_IS_SECURE
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_SIOSR = SAMA_DEFAULT_SIOSR;
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_SIONR = SAMA_DEFAULT_SIONR;
+#endif /* SAMA_HAL_IS_SECURE */
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOD */
+
+  /* Initialize PIO registers for defined pads.*/
+  i = 0;
+  while (sama_inits[i].pio_id != -1) {
+#if SAMA_HAL_IS_SECURE
+    _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_SIOSR = sama_inits[i].pio_msk;
+    _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_MSKR = sama_inits[i].pio_msk;
+    _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_CFGR = sama_inits[i].pio_cfg;
+    if(sama_inits[i].pio_ods == SAMA_PIO_HIGH) {
+      _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_SODR = sama_inits[i].pio_msk;
+    }
+    else {
+      _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_CODR = sama_inits[i].pio_msk;
+    }
+#else
+    _PIOA->PIO_IO_GROUP[sama_inits[i].pio_id].PIO_MSKR = sama_inits[i].pio_msk;
+    _PIOA->PIO_IO_GROUP[sama_inits[i].pio_id].PIO_CFGR = sama_inits[i].pio_cfg;
+    if(sama_inits[i].pio_ods == SAMA_PIO_HIGH) {
+      _PIOA->PIO_IO_GROUP[sama_inits[i].pio_id].PIO_SODR = sama_inits[i].pio_msk;
+    }
+    else {
+      _PIOA->PIO_IO_GROUP[sama_inits[i].pio_id].PIO_CODR = sama_inits[i].pio_msk;
+    }
+#endif /* SAMA_HAL_IS_SECURE */
+    i++;
+  }
+}
diff --git a/os/hal/boards/ATSAMA5D27_SOM1/board.h b/os/hal/boards/ATSAMA5D27_SOM1/board.h
new file mode 100644
index 000000000..78b37e07a
--- /dev/null
+++ b/os/hal/boards/ATSAMA5D27_SOM1/board.h
@@ -0,0 +1,238 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    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 _BOARD_H_
+#define _BOARD_H_
+
+/*
+ * Setup for Atmel SAM A5 D27 SOM1-EK1 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ATSAM5D27_SOM1
+#define BOARD_NAME                  "Atmel SAM A5 D27 SOM1 evaluation kit 1"
+
+/*
+ * Ethernet PHY type.
+ */
+#define BOARD_PHY_ID                MII_KSZ8081_ID
+#define BOARD_PHY_RMII
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(SAMA_OSCXTCLK)
+#define SAMA_OSCXTCLK               32768U
+#endif
+
+#if !defined(SAMA_MOSCXTCLK)
+#define SAMA_MOSCXTCLK              24000000U
+#endif
+
+/*
+ * MCU type as defined in the Atmel header.
+ */
+#define SAMA5D27
+
+/**
+ * Port identifiers.
+ */
+#define SAMA_PIOA                   0U
+#define SAMA_PIOB                   1U
+#define SAMA_PIOC                   2U
+#define SAMA_PIOD                   3U
+
+/*
+ * Forms a line identifier. In this driver the pad number is encoded in the
+ * lower 5 bits of line and the port in sixth and seventh bits.
+ */
+#define SAMA_LINE(port, pad)                                                \
+  ((uint32_t)((uint32_t)(port << 5U)) | ((uint32_t)(pad)))
+
+/*
+ * Decodes a port identifier from a line identifier.
+ */
+#define SAMA_PORT(line)                                                     \
+  ((uint32_t)((line & 0xFFFFFFE0U) >> 5U)
+
+/**
+ * Decodes a pad identifier from a line identifier.
+ */
+#define SAMA_PAD(line)                                                      \
+  ((uint32_t)(line & 0x0000001FU))
+
+
+/*
+ * IO pins assignments.
+ */
+#define PIOA_SDMMC0_CK              0U
+#define PIOA_SDMMC0_CMD             1U
+#define PIOA_SDMMC0_DAT0            2U
+#define PIOA_SDMMC0_DAT1            3U
+#define PIOA_SDMMC0_DAT2            4U
+#define PIOA_SDMMC0_DAT3            5U
+#define PIOA_SDMMC0_DAT4            6U
+#define PIOA_SDMMC0_DAT5            7U
+#define PIOA_SDMMC0_DAT6            8U
+#define PIOA_SDMMC0_DAT7            9U
+#define PIOA_LED_RED                10U
+#define PIOA_SDMMC0_VDDSEL          11U
+#define PIOA_SDMMC0_WP              12U
+#define PIOA_SDMMC0_CD              13U
+#define PIOA_PIN14                  14U
+#define PIOA_PIN15                  15U
+#define PIOA_PIN16                  16U
+#define PIOA_ONEWIRE                17U
+#define PIOA_SDMMC1_DAT0            18U
+#define PIOA_SDMMC1_DAT1            19U
+#define PIOA_SDMMC1_DAT2            20U
+#define PIOA_SDMMC1_DAT3            21U
+#define PIOA_SDMMC1_CK              22U
+#define PIOA_PIN23                  23U
+#define PIOA_PIN24                  24U
+#define PIOA_PIN25                  25U
+#define PIOA_PIN26                  26U
+#define PIOA_PIN27                  27U
+#define PIOA_SDMMC1_CMD             28U
+#define PIOA_USER_PB                29U
+#define PIOA_SDMMC1_CD              30U
+#define PIOA_LED_BLUE               31U
+
+#define PIOB_PIN0                   0U
+#define PIOB_LED_GREEN              1U
+#define PIOB_PIN2                   2U
+#define PIOB_URXD4                  3U
+#define PIOB_UTXD4                  4U
+#define PIOB_QSPI1_SCK              5U
+#define PIOB_QSPI1_CS               6U
+#define PIOB_QSPI1_IO0              7U
+#define PIOB_QSPI1_IO1              8U
+#define PIOB_QSPI1_IO2              9U
+#define PIOB_QSPI1_IO3              10U
+#define PIOB_LCDDAT0                11U
+#define PIOB_LCDDAT1                12U
+#define PIOB_LCDDAT2                13U
+#define PIOB_LCDDAT3                14U
+#define PIOB_LCDDAT4                15U
+#define PIOB_LCDDAT5                16U
+#define PIOB_LCDDAT6                17U
+#define PIOB_LCDDAT7                18U
+#define PIOB_LCDDAT8                19U
+#define PIOB_LCDDAT9                20U
+#define PIOB_LCDDAT10               21U
+#define PIOB_LCDDAT11               22U
+#define PIOB_LCDDAT12               23U
+#define PIOB_LCDDAT13               24U
+#define PIOB_LCDDAT14               25U
+#define PIOB_LCDDAT15               26U
+#define PIOB_LCDDAT16               27U
+#define PIOB_LCDDAT17               28U
+#define PIOB_LCDDAT18               29U
+#define PIOB_LCDDAT19               30U
+#define PIOB_LCDDAT20               31U
+
+#define PIOC_LCDDAT21               0U
+#define PIOC_LCDDAT22               1U
+#define PIOC_LCDDAT23               2U
+#define PIOC_LCDPWM                 3U
+#define PIOC_LCDDISP                4U
+#define PIOC_LCDVSYNC               5U
+#define PIOC_LCDHSYNC               6U
+#define PIOC_LCDPCK                 7U
+#define PIOC_LCDDEN                 8U
+#define PIOC_IRQ9                   9U
+#define PIOC_PIN10                  10U
+#define PIOC_PIN11                  11U
+#define PIOC_PIN12                  12U
+#define PIOC_PIN13                  13U
+#define PIOC_PIN14                  14U
+#define PIOC_PIN15                  15U
+#define PIOC_PIN16                  16U
+#define PIOC_PIN17                  17U
+#define PIOC_PIN18                  18U
+#define PIOC_PIN19                  19U
+#define PIOC_PIN20                  20U
+#define PIOC_PIN21                  21U
+#define PIOC_PIN22                  22U
+#define PIOC_PIN23                  23U
+#define PIOC_PIN24                  24U
+#define PIOC_PIN25                  25U
+#define PIOC_PIN26                  26U
+#define PIOC_PIN27                  27U
+#define PIOC_SPI_FLEXCOM4_IO0       28U
+#define PIOC_SPI_FLEXCOM4_IO1       29U
+#define PIOC_SPI_FLEXCOM4_IO2       30U
+#define PIOC_SPI_FLEXCOM4_IO3       31U
+
+#define PIOD_SPI_FLEXCOM4_IO4       0U
+#define PIOD_IRQ1                   1U
+#define PIOD_URXD1                  2U
+#define PIOD_UTXD1                  3U
+#define PIOD_TWD1                   4U
+#define PIOD_TWCK1                  5U
+#define PIOD_PIO6                   6U
+#define PIOD_PIO7                   7U
+#define PIOD_PIN8                   8U
+#define PIOD_ETH_GTXCK              9U
+#define PIOD_ETH_GTXEN              10U
+#define PIOD_ETH_GRXDV              11U
+#define PIOD_ETH_GRXER              12U
+#define PIOD_ETH_GRX0               13U
+#define PIOD_ETH_GRX1               14U
+#define PIOD_ETH_GTX0               15U
+#define PIOD_ETH_GTX1               16U
+#define PIOD_ETH_GMDC               17U
+#define PIOD_ETH_GMDIO              18U
+#define PIOD_PIO19                  19U
+#define PIOD_PIO20                  20U
+#define PIOD_PIO21                  21U
+#define PIOD_PIO22                  22U
+#define PIOD_URXD2                  23U
+#define PIOD_UTXD2                  24U
+#define PIOD_PIO25                  25U
+#define PIOD_PIO26                  26U
+#define PIOD_PIO27                  27U
+#define PIOD_PIO28                  28U
+#define PIOD_PIO29                  29U
+#define PIOD_PIN30                  30U
+#define PIOD_PIN31                  31U
+
+/*
+ * IO lines assignments.
+ */
+#define BOARD_LINE(port, pad)                                               \
+  ((uint32_t)((uint32_t)(port)) | ((uint32_t)(pad)))
+
+#define LINE_LED_BLUE               BOARD_LINE(PIOA, 31U)
+#define LINE_LED_GREEN              BOARD_LINE(PIOB, 1U)
+#define LINE_LED_RED                BOARD_LINE(PIOA, 10U)
+#define LINE_USER_PB                BOARD_LINE(PIOA, 29U)
+#define LINE_IRQ9                   BOARD_LINE(PIOC, 9U)
+#define LINE_ONEWIRE                BOARD_LINE(PIOA, 17U)
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* _BOARD_H_ */
diff --git a/os/hal/boards/ATSAMA5D27_SOM1/board.mk b/os/hal/boards/ATSAMA5D27_SOM1/board.mk
new file mode 100644
index 000000000..88d45be90
--- /dev/null
+++ b/os/hal/boards/ATSAMA5D27_SOM1/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ATSAMA5D27_SOM1/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ATSAMA5D27_SOM1
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC  += $(BOARDINC)
diff --git a/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.c b/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.c
new file mode 100644
index 000000000..74498464e
--- /dev/null
+++ b/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.c
@@ -0,0 +1,165 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    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 "hal.h"
+
+#define _PIOA                       ((Pio*)0xFC038000U)
+/*
+ * SAMA PIO CFGR masks.
+ */
+#define SAMA_PIO_FUNC_GPIO          0U
+#define SAMA_PIO_FUNC_PERIPH_A      1U
+#define SAMA_PIO_FUNC_PERIPH_B      2U
+#define SAMA_PIO_FUNC_PERIPH_C      3U
+#define SAMA_PIO_FUNC_PERIPH_D      4U
+#define SAMA_PIO_FUNC_PERIPH_E      5U
+#define SAMA_PIO_FUNC_PERIPH_F      6U
+#define SAMA_PIO_FUNC_PERIPH_G      7U
+#define SAMA_PIO_FUNC(n)            (n)
+#define SAMA_PIO_DIR_INPUT          (0U)
+#define SAMA_PIO_DIR_OUTPUT         (1U << 8U)
+#define SAMA_PIO_PUEN               (1U << 9U)
+#define SAMA_PIO_PDEN               (1U << 10U)
+#define SAMA_PIO_IFEN               (1U << 12U)
+#define SAMA_PIO_IFSCEN             (1U << 13U)
+#define SAMA_PIO_OPD                (1U << 14U)
+#define SAMA_PIO_SCHMITT            (1U << 15U)
+#define SAMA_PIO_DRVSTR_LO          (0U << 16U)
+#define SAMA_PIO_DRVSTR_ME          (2U << 16U)
+#define SAMA_PIO_DRVSTR_HI          (3U << 16U)
+
+#define SAMA_PIO_LOW                0U
+#define SAMA_PIO_HIGH               1U
+/*
+ * SAMA PIO default SIOSR, MSKR and CFGR values.
+ */
+#define SAMA_DEFAULT_SIOSR          0x00000000U
+#define SAMA_DEFAULT_SIONR          0xFFFFFFFFU
+#define SAMA_DEFAULT_MSKR           0xFFFFFFFFU
+#define SAMA_DEFAULT_CFGR           SAMA_PIO_FUNC_GPIO | SAMA_PIO_PUEN |    \
+                                    SAMA_PIO_DIR_INPUT | SAMA_PIO_SCHMITT
+
+/*
+ * This macro converts a pin identifier to a bitmask.
+ */
+#define SAMA_PIN_N(n)               (1U << n)
+
+/**
+ * @brief   SIU/SIUL register initializer type.
+ */
+typedef struct {
+  int32_t pio_id;
+  uint32_t pio_msk;
+  uint32_t pio_cfg;
+  uint32_t pio_ods;
+} sama_pio_init_t;
+
+/*
+ * @brief   Initial setup of all defined pads.
+ * @note    The list is terminated by a {-1, 0, 0, 0}
+ */
+static const sama_pio_init_t sama_inits[] = {
+  /* RGB Led Red */
+  {SAMA_PIOA,
+   SAMA_PIN_N(PIOA_LED_RED),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_OUTPUT | SAMA_PIO_DRVSTR_HI,
+   SAMA_PIO_LOW},
+  /* UART1 */
+  {SAMA_PIOD,
+   SAMA_PIN_N(PIOD_URXD1) | SAMA_PIN_N(PIOD_UTXD1),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  /* UART2 */
+  {SAMA_PIOD,
+   SAMA_PIN_N(PIOD_URXD2) | SAMA_PIN_N(PIOD_UTXD2),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  /* MMC Slot0 pads -J12 SD card */
+  {SAMA_PIOA,
+   SAMA_PIN_N(PIOA_SDMMC0_CK) | SAMA_PIN_N(PIOA_SDMMC0_CMD) |
+   SAMA_PIN_N(PIOA_SDMMC0_DAT0) | SAMA_PIN_N(PIOA_SDMMC0_DAT1) |
+   SAMA_PIN_N(PIOA_SDMMC0_DAT2) | SAMA_PIN_N(PIOA_SDMMC0_DAT3) |
+   SAMA_PIN_N(PIOA_SDMMC0_DAT4) | SAMA_PIN_N(PIOA_SDMMC0_DAT5) |
+   SAMA_PIN_N(PIOA_SDMMC0_DAT6) | SAMA_PIN_N(PIOA_SDMMC0_DAT7) |
+   SAMA_PIN_N(PIOA_SDMMC0_WP) | SAMA_PIN_N(PIOA_SDMMC0_CD) |
+   SAMA_PIN_N(PIOA_SDMMC0_VDDSEL),
+   SAMA_PIO_FUNC_PERIPH_A | SAMA_PIO_DRVSTR_HI,
+   SAMA_PIO_HIGH},
+  /* list terminated*/
+  {-1, 0, 0, 0}
+};
+
+/**
+ * @brief   Early initialization code.
+ * @details This initialization must be performed just after stack setup
+ *          and before any other initialization.
+ */
+void __early_init(void) {
+
+  sama_clock_init();
+  /* Configures ETH's pins */
+  palSetGroupMode(PIOD, PAL_PORT_BIT(PIOD_ETH_GTXCK) | PAL_PORT_BIT(PIOD_ETH_GTXEN) |
+                  PAL_PORT_BIT(PIOD_ETH_GRXDV) | PAL_PORT_BIT(PIOD_ETH_GRXER) |
+                  PAL_PORT_BIT(PIOD_ETH_GRX0) | PAL_PORT_BIT(PIOD_ETH_GRX1) |
+                  PAL_PORT_BIT(PIOD_ETH_GTX0) | PAL_PORT_BIT(PIOD_ETH_GTX1) |
+                  PAL_PORT_BIT(PIOD_ETH_GMDC) | PAL_PORT_BIT(PIOD_ETH_GMDIO),
+                  0U, PAL_SAMA_FUNC_PERIPH_D);
+}
+
+/**
+ * @brief   Board-specific initialization code.
+ */
+void boardInit(void) {
+  unsigned i;
+
+  /* Configuring all PIO A pads with default configuration.  */
+#if SAMA_HAS_PIOA
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOA */
+
+  /* Configuring all PIO B pads with default configuration.  */
+#if SAMA_HAS_PIOB
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOB */
+
+  /* Configuring all PIO C pads with default configuration.  */
+#if SAMA_HAS_PIOC
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOC */
+
+  /* Configuring all PIO D pads with default configuration.  */
+#if SAMA_HAS_PIOD
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOD */
+
+  /* Initialize PIO registers for defined pads.*/
+  i = 0;
+  while (sama_inits[i].pio_id != -1) {
+    _PIOA->PIO_IO_GROUP[sama_inits[i].pio_id].PIO_MSKR = sama_inits[i].pio_msk;
+    _PIOA->PIO_IO_GROUP[sama_inits[i].pio_id].PIO_CFGR = sama_inits[i].pio_cfg;
+    if(sama_inits[i].pio_ods == SAMA_PIO_HIGH) {
+      _PIOA->PIO_IO_GROUP[sama_inits[i].pio_id].PIO_SODR = sama_inits[i].pio_msk;
+    }
+    else {
+      _PIOA->PIO_IO_GROUP[sama_inits[i].pio_id].PIO_CODR = sama_inits[i].pio_msk;
+    }
+    i++;
+  }
+}
diff --git a/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.h b/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.h
new file mode 100644
index 000000000..a22cc1051
--- /dev/null
+++ b/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.h
@@ -0,0 +1,232 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    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 _BOARD_H_
+#define _BOARD_H_
+
+/*
+ * Setup for Atmel SAM A5 D27 SOM1-EK1 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ATSAM5D27_SOM1
+#define BOARD_NAME                  "Atmel SAM A5 D27 SOM1 evaluation kit 1"
+
+/*
+ * Ethernet PHY type.
+ */
+#define BOARD_PHY_ID                MII_KSZ8081_ID
+#define BOARD_PHY_RMII
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(SAMA_OSCXTCLK)
+#define SAMA_OSCXTCLK               32768U
+#endif
+
+#if !defined(SAMA_MOSCXTCLK)
+#define SAMA_MOSCXTCLK              24000000U
+#endif
+
+/*
+ * MCU type as defined in the Atmel header.
+ */
+#define SAMA5D27
+
+/**
+ * Port identifiers.
+ */
+#define SAMA_PIOA                   0U
+#define SAMA_PIOB                   1U
+#define SAMA_PIOC                   2U
+#define SAMA_PIOD                   3U
+
+/*
+ * Forms a line identifier. In this driver the pad number is encoded in the
+ * lower 5 bits of line and the port in sixth and seventh bits.
+ */
+#define SAMA_LINE(port, pad)                                                \
+  ((uint32_t)((uint32_t)(port << 5U)) | ((uint32_t)(pad)))
+
+/*
+ * Decodes a port identifier from a line identifier.
+ */
+#define SAMA_PORT(line)                                                     \
+  ((uint32_t)((line & 0xFFFFFFE0U) >> 5U)
+
+/**
+ * Decodes a pad identifier from a line identifier.
+ */
+#define SAMA_PAD(line)                                                      \
+  ((uint32_t)(line & 0x0000001FU))
+
+/*
+ * IO pins assignments.
+ */
+#define PIOA_SDMMC0_CK              0U
+#define PIOA_SDMMC0_CMD             1U
+#define PIOA_SDMMC0_DAT0            2U
+#define PIOA_SDMMC0_DAT1            3U
+#define PIOA_SDMMC0_DAT2            4U
+#define PIOA_SDMMC0_DAT3            5U
+#define PIOA_SDMMC0_DAT4            6U
+#define PIOA_SDMMC0_DAT5            7U
+#define PIOA_SDMMC0_DAT6            8U
+#define PIOA_SDMMC0_DAT7            9U
+#define PIOA_LED_RED                10U
+#define PIOA_SDMMC0_VDDSEL          11U
+#define PIOA_SDMMC0_WP              12U
+#define PIOA_SDMMC0_CD              13U
+#define PIOA_PIN14                  14U
+#define PIOA_PIN15                  15U
+#define PIOA_PIN16                  16U
+#define PIOA_PIN17                  17U
+#define PIOA_PIN18                  18U
+#define PIOA_PIN19                  19U
+#define PIOA_PIN20                  20U
+#define PIOA_PIN21                  21U
+#define PIOA_PIN22                  22U
+#define PIOA_PIN23                  23U
+#define PIOA_PIN24                  24U
+#define PIOA_PIN25                  25U
+#define PIOA_PIN26                  26U
+#define PIOA_PIN27                  27U
+#define PIOA_PIN28                  28U
+#define PIOA_PIN29                  29U
+#define PIOA_PIN30                  30U
+#define PIOA_PIN31                  31U
+
+#define PIOB_PIN0                   0U
+#define PIOB_PIN1                   1U
+#define PIOB_PIN2                   2U
+#define PIOB_PIN3                   3U
+#define PIOB_PIN4                   4U
+#define PIOB_PIN5                   5U
+#define PIOB_PIN6                   6U
+#define PIOB_PIN7                   7U
+#define PIOB_PIN8                   8U
+#define PIOB_PIN9                   9U
+#define PIOB_PIN10                  10U
+#define PIOB_PIN11                  11U
+#define PIOB_PIN12                  12U
+#define PIOB_PIN13                  13U
+#define PIOB_PIN14                  14U
+#define PIOB_PIN15                  15U
+#define PIOB_PIN16                  16U
+#define PIOB_PIN17                  17U
+#define PIOB_PIN18                  18U
+#define PIOB_PIN19                  19U
+#define PIOB_PIN20                  20U
+#define PIOB_PIN21                  21U
+#define PIOB_PIN22                  22U
+#define PIOB_PIN23                  23U
+#define PIOB_PIN24                  24U
+#define PIOB_PIN25                  25U
+#define PIOB_PIN26                  26U
+#define PIOB_PIN27                  27U
+#define PIOB_PIN28                  28U
+#define PIOB_PIN29                  29U
+#define PIOB_PIN30                  30U
+#define PIOB_PIN31                  31U
+
+#define PIOC_PIN0                   0U
+#define PIOC_PIN1                   1U
+#define PIOC_PIN2                   2U
+#define PIOC_PIN3                   3U
+#define PIOC_PIN4                   4U
+#define PIOC_PIN5                   5U
+#define PIOC_PIN6                   6U
+#define PIOC_PIN7                   7U
+#define PIOC_PIN8                   8U
+#define PIOC_PIN9                   9U
+#define PIOC_PIN10                  10U
+#define PIOC_PIN11                  11U
+#define PIOC_PIN12                  12U
+#define PIOC_PIN13                  13U
+#define PIOC_PIN14                  14U
+#define PIOC_PIN15                  15U
+#define PIOC_PIN16                  16U
+#define PIOC_PIN17                  17U
+#define PIOC_PIN18                  18U
+#define PIOC_PIN19                  19U
+#define PIOC_PIN20                  20U
+#define PIOC_PIN21                  21U
+#define PIOC_PIN22                  22U
+#define PIOC_PIN23                  23U
+#define PIOC_PIN24                  24U
+#define PIOC_PIN25                  25U
+#define PIOC_PIN26                  26U
+#define PIOC_PIN27                  27U
+#define PIOC_PIN28                  28U
+#define PIOC_PIN29                  29U
+#define PIOC_PIN30                  30U
+#define PIOC_PIN31                  31U
+
+#define PIOD_PIO0                   0U
+#define PIOD_PIN1                   1U
+#define PIOD_URXD1                  2U
+#define PIOD_UTXD1                  3U
+#define PIOD_PIO4                   4U
+#define PIOD_PIO5                   5U
+#define PIOD_PIO6                   6U
+#define PIOD_PIO7                   7U
+#define PIOD_PIN8                   8U
+#define PIOD_ETH_GTXCK              9U
+#define PIOD_ETH_GTXEN              10U
+#define PIOD_ETH_GRXDV              11U
+#define PIOD_ETH_GRXER              12U
+#define PIOD_ETH_GRX0               13U
+#define PIOD_ETH_GRX1               14U
+#define PIOD_ETH_GTX0               15U
+#define PIOD_ETH_GTX1               16U
+#define PIOD_ETH_GMDC               17U
+#define PIOD_ETH_GMDIO              18U
+#define PIOD_PIO19                  19U
+#define PIOD_PIO20                  20U
+#define PIOD_PIO21                  21U
+#define PIOD_PIO22                  22U
+#define PIOD_URXD2                  23U
+#define PIOD_UTXD2                  24U
+#define PIOD_PIO25                  25U
+#define PIOD_PIO26                  26U
+#define PIOD_PIO27                  27U
+#define PIOD_PIO28                  28U
+#define PIOD_PIO29                  29U
+#define PIOD_PIN30                  30U
+#define PIOD_PIN31                  31U
+
+/*
+ * IO lines assignments.
+ */
+#define BOARD_LINE(port, pad)                                               \
+  ((uint32_t)((uint32_t)(port)) | ((uint32_t)(pad)))
+
+#define LINE_LED_RED                BOARD_LINE(PIOA, 10U)
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* _BOARD_H_ */
diff --git a/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.mk b/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.mk
new file mode 100644
index 000000000..fbc9baba7
--- /dev/null
+++ b/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ATSAMA5D27_SOM1_NSEC/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ATSAMA5D27_SOM1_NSEC
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC  += $(BOARDINC)
diff --git a/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.c b/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.c
new file mode 100644
index 000000000..d07ee39e7
--- /dev/null
+++ b/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.c
@@ -0,0 +1,229 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    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 "hal.h"
+
+#define _PIOA                       ((Pio*)0xFC038000U)
+
+/*===========================================================================*/
+/* Configuration checks.                                                     */
+/*===========================================================================*/
+
+#if !SAMA_HAL_IS_SECURE
+#error "SAMA PROJECT REQUIRES SECURE CONFIGURATION"
+#endif
+
+/*
+ * SAMA PIO CFGR masks.
+ */
+#define SAMA_PIO_FUNC_GPIO          0U
+#define SAMA_PIO_FUNC_PERIPH_A      1U
+#define SAMA_PIO_FUNC_PERIPH_B      2U
+#define SAMA_PIO_FUNC_PERIPH_C      3U
+#define SAMA_PIO_FUNC_PERIPH_D      4U
+#define SAMA_PIO_FUNC_PERIPH_E      5U
+#define SAMA_PIO_FUNC_PERIPH_F      6U
+#define SAMA_PIO_FUNC_PERIPH_G      7U
+#define SAMA_PIO_FUNC(n)            (n)
+#define SAMA_PIO_DIR_INPUT          (0U)
+#define SAMA_PIO_DIR_OUTPUT         (1U << 8U)
+#define SAMA_PIO_PUEN               (1U << 9U)
+#define SAMA_PIO_PDEN               (1U << 10U)
+#define SAMA_PIO_IFEN               (1U << 12U)
+#define SAMA_PIO_IFSCEN             (1U << 13U)
+#define SAMA_PIO_OPD                (1U << 14U)
+#define SAMA_PIO_SCHMITT            (1U << 15U)
+#define SAMA_PIO_DRVSTR_LO          (0U << 16U)
+#define SAMA_PIO_DRVSTR_ME          (2U << 16U)
+#define SAMA_PIO_DRVSTR_HI          (3U << 16U)
+
+#define SAMA_PIO_LOW                0U
+#define SAMA_PIO_HIGH               1U
+/*
+ * SAMA PIO default SIOSR, MSKR and CFGR values.
+ */
+#define SAMA_DEFAULT_SIOSR          0x00000000U
+#define SAMA_DEFAULT_SIONR          0xFFFFFFFFU
+#define SAMA_DEFAULT_MSKR           0xFFFFFFFFU
+#define SAMA_DEFAULT_CFGR           SAMA_PIO_FUNC_GPIO | SAMA_PIO_PUEN |    \
+                                    SAMA_PIO_DIR_INPUT | SAMA_PIO_SCHMITT
+
+/*
+ * This macro converts a pin identifier to a bitmask.
+ */
+#define SAMA_PIN_N(n)               (1U << n)
+
+/**
+ * @brief   SIU/SIUL register initializer type.
+ */
+typedef struct {
+  int32_t pio_id;
+  uint32_t pio_msk;
+  uint32_t pio_cfg;
+  uint32_t pio_ods;
+} sama_pio_init_t;
+
+/*
+ * @brief   Initial setup of all defined pads.
+ * @note    All pads are secured.
+ * @note    The list is terminated by a {-1, 0, 0, 0}
+ */
+static const sama_pio_init_t sama_inits[] = {
+  /* RGB Led Blue */
+  {SAMA_PIOA,
+   SAMA_PIN_N(PIOA_LED_BLUE),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_OUTPUT | SAMA_PIO_DRVSTR_HI,
+   SAMA_PIO_LOW},
+  /* User Button */
+  {SAMA_PIOA,
+   SAMA_PIN_N(PIOA_USER_PB),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_INPUT | SAMA_PIO_PUEN | SAMA_PIO_SCHMITT,
+   SAMA_PIO_LOW},
+  /* QSPI1 */
+  {SAMA_PIOB,
+   SAMA_PIN_N(PIOB_QSPI1_SCK) | SAMA_PIN_N(PIOB_QSPI1_CS) |
+   SAMA_PIN_N(PIOB_QSPI1_IO0) | SAMA_PIN_N(PIOB_QSPI1_IO1) |
+   SAMA_PIN_N(PIOB_QSPI1_IO2) | SAMA_PIN_N(PIOB_QSPI1_IO3),
+   SAMA_PIO_FUNC_PERIPH_D | SAMA_PIO_PUEN,
+   SAMA_PIO_HIGH},
+  /* UART4 */
+  {SAMA_PIOB,
+   SAMA_PIN_N(PIOB_URXD4) | SAMA_PIN_N(PIOB_UTXD4),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  /* FLEXSPI4 */
+  {SAMA_PIOC,
+   SAMA_PIN_N(PIOC_SPI_FLEXCOM4_IO0) |
+   SAMA_PIN_N(PIOC_SPI_FLEXCOM4_IO1) |
+   SAMA_PIN_N(PIOC_SPI_FLEXCOM4_IO2) |
+   SAMA_PIN_N(PIOC_SPI_FLEXCOM4_IO3),
+   SAMA_PIO_FUNC_PERIPH_B,
+   SAMA_PIO_HIGH},
+  {SAMA_PIOD,
+   SAMA_PIN_N(PIOD_SPI_FLEXCOM4_IO4),
+   SAMA_PIO_FUNC_PERIPH_B,
+   SAMA_PIO_HIGH},
+  /* IRQ9 */
+  {SAMA_PIOC,
+   SAMA_PIN_N(PIOC_IRQ9),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_INPUT | SAMA_PIO_PUEN | SAMA_PIO_SCHMITT,
+   SAMA_PIO_LOW},
+   /* PIOD_IRQ1 Touch */
+  {SAMA_PIOD,
+   SAMA_PIN_N(PIOD_IRQ1),
+   SAMA_PIO_FUNC_GPIO | SAMA_PIO_DIR_INPUT | SAMA_PIO_PUEN | SAMA_PIO_SCHMITT,
+   SAMA_PIO_HIGH},
+  /* LCDC */
+  {SAMA_PIOB,
+   SAMA_PIN_N(PIOB_LCDDAT0) | SAMA_PIN_N(PIOB_LCDDAT1) |
+   SAMA_PIN_N(PIOB_LCDDAT2) | SAMA_PIN_N(PIOB_LCDDAT3) |
+   SAMA_PIN_N(PIOB_LCDDAT4) | SAMA_PIN_N(PIOB_LCDDAT5) |
+   SAMA_PIN_N(PIOB_LCDDAT6) | SAMA_PIN_N(PIOB_LCDDAT7) |
+   SAMA_PIN_N(PIOB_LCDDAT8) | SAMA_PIN_N(PIOB_LCDDAT9) |
+   SAMA_PIN_N(PIOB_LCDDAT10) | SAMA_PIN_N(PIOB_LCDDAT11) |
+   SAMA_PIN_N(PIOB_LCDDAT12) | SAMA_PIN_N(PIOB_LCDDAT13) |
+   SAMA_PIN_N(PIOB_LCDDAT14) | SAMA_PIN_N(PIOB_LCDDAT15) |
+   SAMA_PIN_N(PIOB_LCDDAT16) | SAMA_PIN_N(PIOB_LCDDAT17) |
+   SAMA_PIN_N(PIOB_LCDDAT18) | SAMA_PIN_N(PIOB_LCDDAT19) |
+   SAMA_PIN_N(PIOB_LCDDAT20),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  {SAMA_PIOC,
+   SAMA_PIN_N(PIOC_LCDDAT21) | SAMA_PIN_N(PIOC_LCDDAT22) |
+   SAMA_PIN_N(PIOC_LCDDAT23) | SAMA_PIN_N(PIOC_LCDPWM) |
+   SAMA_PIN_N(PIOC_LCDDISP) | SAMA_PIN_N(PIOC_LCDVSYNC) |
+   SAMA_PIN_N(PIOC_LCDHSYNC) | SAMA_PIN_N(PIOC_LCDPCK) |
+   SAMA_PIN_N(PIOC_LCDDEN),
+   SAMA_PIO_FUNC_PERIPH_A,
+   SAMA_PIO_HIGH},
+  /* list terminated*/
+  {-1, 0, 0, 0}
+};
+
+/**
+ * @brief   Early initialization code.
+ * @details This initialization must be performed just after stack setup
+ *          and before any other initialization.
+ */
+void __early_init(void) {
+
+  sama_clock_init();
+}
+
+/**
+ * @brief   Board-specific initialization code.
+ */
+void boardInit(void) {
+  unsigned i;
+
+  /* Disabling PMC write protection. */
+  pmcDisableWP();
+
+  /* Enabling port clock. */
+  pmcEnablePIO();
+
+  /* Enabling write protection.  */
+  pmcEnableWP();
+
+  _PIOA->S_PIO_WPMR = PIO_WPMR_WPKEY_PASSWD;
+
+  /* Configuring all PIO A pads with default configuration.  */
+#if SAMA_HAS_PIOA
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_SIOSR = SAMA_DEFAULT_SIOSR;
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_SIONR = SAMA_DEFAULT_SIONR;
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOA].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOA */
+
+  /* Configuring all PIO B pads with default configuration.  */
+#if SAMA_HAS_PIOB
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_SIOSR = SAMA_DEFAULT_SIOSR;
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_SIONR = SAMA_DEFAULT_SIONR;
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOB].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOB */
+
+  /* Configuring all PIO C pads with default configuration.  */
+#if SAMA_HAS_PIOC
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_SIOSR = SAMA_DEFAULT_SIOSR;
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_SIONR = SAMA_DEFAULT_SIONR;
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOC].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOC */
+
+  /* Configuring all PIO D pads with default configuration.  */
+#if SAMA_HAS_PIOD
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_SIOSR = SAMA_DEFAULT_SIOSR;
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_SIONR = SAMA_DEFAULT_SIONR;
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_MSKR = SAMA_DEFAULT_MSKR;
+  _PIOA->PIO_PIO_[SAMA_PIOD].S_PIO_CFGR = SAMA_DEFAULT_CFGR;
+#endif /* SAMA_HAS_PIOD */
+
+  /* Initialize PIO registers for defined pads.*/
+  i = 0;
+  while (sama_inits[i].pio_id != -1) {
+    _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_SIOSR = sama_inits[i].pio_msk;
+    _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_MSKR = sama_inits[i].pio_msk;
+    _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_CFGR = sama_inits[i].pio_cfg;
+    if(sama_inits[i].pio_ods == SAMA_PIO_HIGH) {
+      _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_SODR = sama_inits[i].pio_msk;
+    }
+    else {
+      _PIOA->PIO_PIO_[sama_inits[i].pio_id].S_PIO_CODR = sama_inits[i].pio_msk;
+    }
+    i++;
+  }
+}
diff --git a/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.h b/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.h
new file mode 100644
index 000000000..5e7ffb214
--- /dev/null
+++ b/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.h
@@ -0,0 +1,236 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    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 _BOARD_H_
+#define _BOARD_H_
+
+/*
+ * Setup for Atmel SAM A5 D27 SOM1-EK1 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ATSAM5D27_SOM1
+#define BOARD_NAME                  "Atmel SAM A5 D27 SOM1 evaluation kit 1"
+
+/*
+ * Ethernet PHY type.
+ */
+#define BOARD_PHY_ID                MII_KSZ8081_ID
+#define BOARD_PHY_RMII
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(SAMA_OSCXTCLK)
+#define SAMA_OSCXTCLK               32768U
+#endif
+
+#if !defined(SAMA_MOSCXTCLK)
+#define SAMA_MOSCXTCLK              24000000U
+#endif
+
+/*
+ * MCU type as defined in the Atmel header.
+ */
+#define SAMA5D27
+
+/**
+ * Port identifiers.
+ */
+#define SAMA_PIOA                   0U
+#define SAMA_PIOB                   1U
+#define SAMA_PIOC                   2U
+#define SAMA_PIOD                   3U
+
+/*
+ * Forms a line identifier. In this driver the pad number is encoded in the
+ * lower 5 bits of line and the port in sixth and seventh bits.
+ */
+#define SAMA_LINE(port, pad)                                                \
+  ((uint32_t)((uint32_t)(port << 5U)) | ((uint32_t)(pad)))
+
+/*
+ * Decodes a port identifier from a line identifier.
+ */
+#define SAMA_PORT(line)                                                     \
+  ((uint32_t)((line & 0xFFFFFFE0U) >> 5U)
+
+/**
+ * Decodes a pad identifier from a line identifier.
+ */
+#define SAMA_PAD(line)                                                      \
+  ((uint32_t)(line & 0x0000001FU))
+
+
+/*
+ * IO pins assignments.
+ */
+#define PIOA_PIN0                   0U
+#define PIOA_PIN1                   1U
+#define PIOA_PIN2                   2U
+#define PIOA_PIN3                   3U
+#define PIOA_PIN4                   4U
+#define PIOA_PIN5                   5U
+#define PIOA_PIN6                   6U
+#define PIOA_PIN7                   7U
+#define PIOA_PIN8                   8U
+#define PIOA_PIN9                   9U
+#define PIOA_PIN10                  10U
+#define PIOA_PIN11                  11U
+#define PIOA_PIN12                  12U
+#define PIOA_PIN13                  13U
+#define PIOA_PIN14                  14U
+#define PIOA_PIN15                  15U
+#define PIOA_PIN16                  16U
+#define PIOA_ONEWIRE                17U
+#define PIOA_PIN18                  18U
+#define PIOA_PIN19                  19U
+#define PIOA_PIN20                  20U
+#define PIOA_PIN21                  21U
+#define PIOA_PIN22                  22U
+#define PIOA_PIN23                  23U
+#define PIOA_PIN24                  24U
+#define PIOA_PIN25                  25U
+#define PIOA_PIN26                  26U
+#define PIOA_PIN27                  27U
+#define PIOA_PIN28                  28U
+#define PIOA_USER_PB                29U
+#define PIOA_PIN30                  30U
+#define PIOA_LED_BLUE               31U
+
+#define PIOB_PIN0                   0U
+#define PIOB_PIN1                   1U
+#define PIOB_PIN2                   2U
+#define PIOB_URXD4                  3U
+#define PIOB_UTXD4                  4U
+#define PIOB_QSPI1_SCK              5U
+#define PIOB_QSPI1_CS               6U
+#define PIOB_QSPI1_IO0              7U
+#define PIOB_QSPI1_IO1              8U
+#define PIOB_QSPI1_IO2              9U
+#define PIOB_QSPI1_IO3              10U
+#define PIOB_LCDDAT0                11U
+#define PIOB_LCDDAT1                12U
+#define PIOB_LCDDAT2                13U
+#define PIOB_LCDDAT3                14U
+#define PIOB_LCDDAT4                15U
+#define PIOB_LCDDAT5                16U
+#define PIOB_LCDDAT6                17U
+#define PIOB_LCDDAT7                18U
+#define PIOB_LCDDAT8                19U
+#define PIOB_LCDDAT9                20U
+#define PIOB_LCDDAT10               21U
+#define PIOB_LCDDAT11               22U
+#define PIOB_LCDDAT12               23U
+#define PIOB_LCDDAT13               24U
+#define PIOB_LCDDAT14               25U
+#define PIOB_LCDDAT15               26U
+#define PIOB_LCDDAT16               27U
+#define PIOB_LCDDAT17               28U
+#define PIOB_LCDDAT18               29U
+#define PIOB_LCDDAT19               30U
+#define PIOB_LCDDAT20               31U
+
+#define PIOC_LCDDAT21               0U
+#define PIOC_LCDDAT22               1U
+#define PIOC_LCDDAT23               2U
+#define PIOC_LCDPWM                 3U
+#define PIOC_LCDDISP                4U
+#define PIOC_LCDVSYNC               5U
+#define PIOC_LCDHSYNC               6U
+#define PIOC_LCDPCK                 7U
+#define PIOC_LCDDEN                 8U
+#define PIOC_IRQ9                   9U
+#define PIOC_PIN10                  10U
+#define PIOC_PIN11                  11U
+#define PIOC_PIN12                  12U
+#define PIOC_PIN13                  13U
+#define PIOC_PIN14                  14U
+#define PIOC_PIN15                  15U
+#define PIOC_PIN16                  16U
+#define PIOC_PIN17                  17U
+#define PIOC_PIN18                  18U
+#define PIOC_PIN19                  19U
+#define PIOC_PIN20                  20U
+#define PIOC_PIN21                  21U
+#define PIOC_PIN22                  22U
+#define PIOC_PIN23                  23U
+#define PIOC_PIN24                  24U
+#define PIOC_PIN25                  25U
+#define PIOC_PIN26                  26U
+#define PIOC_PIN27                  27U
+#define PIOC_SPI_FLEXCOM4_IO0       28U
+#define PIOC_SPI_FLEXCOM4_IO1       29U
+#define PIOC_SPI_FLEXCOM4_IO2       30U
+#define PIOC_SPI_FLEXCOM4_IO3       31U
+
+#define PIOD_SPI_FLEXCOM4_IO4       0U
+#define PIOD_IRQ1                   1U
+#define PIOD_PIN2                   2U
+#define PIOD_PIN3                   3U
+#define PIOD_TWD1                   4U
+#define PIOD_TWCK1                  5U
+#define PIOD_PIO6                   6U
+#define PIOD_PIO7                   7U
+#define PIOD_PIN8                   8U
+#define PIOD_PIN9                   9U
+#define PIOD_PIO10                  10U
+#define PIOD_PIO11                  11U
+#define PIOD_PIN12                  12U
+#define PIOD_PIN13                  13U
+#define PIOD_PIN14                  14U
+#define PIOD_PIN15                  15U
+#define PIOD_PIN16                  16U
+#define PIOD_PIN17                  17U
+#define PIOD_PIN18                  18U
+#define PIOD_PIO19                  19U
+#define PIOD_PIO20                  20U
+#define PIOD_PIO21                  21U
+#define PIOD_PIO22                  22U
+#define PIOD_PIN23                  23U
+#define PIOD_PIO24                  24U
+#define PIOD_PIO25                  25U
+#define PIOD_PIO26                  26U
+#define PIOD_PIO27                  27U
+#define PIOD_PIO28                  28U
+#define PIOD_PIO29                  29U
+#define PIOD_PIN30                  30U
+#define PIOD_PIN31                  31U
+
+/*
+ * IO lines assignments.
+ */
+#define BOARD_LINE(port, pad)                                               \
+  ((uint32_t)((uint32_t)(port)) | ((uint32_t)(pad)))
+
+#define LINE_LED_BLUE               BOARD_LINE(PIOA, 31U)
+#define LINE_USER_PB                BOARD_LINE(PIOA, 29U)
+#define LINE_IRQ9                   BOARD_LINE(PIOC, 9U)
+#define LINE_ONEWIRE                BOARD_LINE(PIOA, 17U)
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* _BOARD_H_ */
diff --git a/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.mk b/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.mk
new file mode 100644
index 000000000..11f46f92d
--- /dev/null
+++ b/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ATSAMA5D27_SOM1_SEC/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ATSAMA5D27_SOM1_SEC
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC  += $(BOARDINC)
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c
index 0ed4af4a2..a6cb4ee12 100644
--- a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c
@@ -165,9 +165,29 @@ cryerror_t sama_aes_lld_process_dma(CRYDriver *cryp,  aesparams *params,
 	cryerror_t ret;
 
 	osalDbgAssert(cryp->thread == NULL, "already waiting");
+  osalDbgAssert(!((uint32_t) in & (L1_CACHE_BYTES - 1)), "in address not cache aligned");
+  osalDbgAssert(!((uint32_t) out & (L1_CACHE_BYTES - 1)), "out address not cache aligned");
+
+#if 0
+  osalDbgAssert(!(indata_len & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+#endif
+
+  /*
+   * If size is not multiple of cache line, clean cache region is required.
+   * TODO: remove when size assert works
+   */
+  if (indata_len & (L1_CACHE_BYTES - 1)) {
+    cacheCleanRegion((uint8_t *) out, indata_len);
+  }
 
 	osalMutexLock(&cryp->mutex);
 
+  cacheCleanRegion((uint8_t *) in, indata_len);
+
+  cryp->out = out;
+  cryp->in = in;
+  cryp->len = indata_len;
+
 	//set chunk size
 	cryp->dmachunksize = DMA_CHUNK_SIZE_4;
 
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c
index a4e19d7c7..764b1b915 100644
--- a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c
@@ -19,8 +19,6 @@
 
 #include "sama_crypto_lld.h"
 
-
-
 #if defined(SAMA_DMA_REQUIRED)
 static void crypto_lld_serve_read_interrupt(CRYDriver *cryp, uint32_t flags);
 static void crypto_lld_serve_write_interrupt(CRYDriver *cryp, uint32_t flags);
@@ -50,7 +48,7 @@ static void crypto_lld_serve_write_interrupt(CRYDriver *cryp, uint32_t flags);
  * @note    This macro is meant to be used in the low level drivers
  *          implementation only.
  *
- * @param[in] spip      pointer to the @p SPIDriver object
+ * @param[in] cryp      pointer to the @p CRYDriver object
  *
  * @notapi
  */
@@ -132,6 +130,9 @@ static void crypto_lld_serve_read_interrupt(CRYDriver *cryp, uint32_t flags) {
   (void)flags;
 #endif
 
+  /* D-Cache L1 is enabled */
+  cacheInvalidateRegion(cryp->out, cryp->len);
+
   /* Stop everything.*/
   dmaChannelDisable(cryp->dmarx);
   /* Portable CRY ISR code defined in the high level driver, note, it is
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_gcm_lld.c b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_gcm_lld.c
index 2496c03d3..3e9471a2a 100644
--- a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_gcm_lld.c
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_gcm_lld.c
@@ -36,8 +36,27 @@ static cryerror_t sama_gcm_lld_process_dma(CRYDriver *cryp,cgmcontext * cxt)
 {
 #if defined(SAMA_DMA_REQUIRED)
 
+  osalDbgAssert(!((uint32_t) cxt->in & (L1_CACHE_BYTES - 1)), "in address not cache aligned");
+  osalDbgAssert(!((uint32_t) cxt->out & (L1_CACHE_BYTES - 1)), "out address not cache aligned");
 	osalDbgAssert(cryp->thread == NULL, "already waiting");
 
+#if 0
+  osalDbgAssert(!(cxt->c_size & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+#endif
+
+  cacheCleanRegion((uint8_t *) cxt->in, cxt->c_size);
+
+  /*
+   * If size is not multiple of cache line, clean cache region is required.
+   * TODO: remove when size assert works
+   */
+  if (cxt->c_size & (L1_CACHE_BYTES - 1)) {
+    cacheCleanRegion((uint8_t *) cxt->out, cxt->c_size);
+  }
+
+  cryp->out = cxt->out;
+  cryp->in = cxt->in;
+  cryp->len = cxt->c_size;
 
 	//set chunk size
 	cryp->dmachunksize = DMA_CHUNK_SIZE_4;
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_sha_lld.c b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_sha_lld.c
index b88386366..cf38e75d0 100644
--- a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_sha_lld.c
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_sha_lld.c
@@ -357,10 +357,22 @@ static uint32_t processBlockPolling(const uint8_t *data,uint32_t len, uint32_t b
 	return processed;
 }
 
-static uint32_t processBlockDMA(CRYDriver *cryp, const uint8_t *data,uint32_t len, uint32_t block_size)
-{
+static uint32_t processBlockDMA(CRYDriver *cryp, const uint8_t *data,uint32_t len, uint32_t block_size) {
+
+  osalDbgAssert(!((uint32_t) data & (L1_CACHE_BYTES - 1)), "data address not cache aligned");
+
+#if 0
+  osalDbgAssert(!(block_size & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+#endif
+
 	uint32_t processed = 0;
 
+  cryp->out = 0;
+  cryp->in = data;
+  cryp->len = len;
+
+  cacheCleanRegion((uint8_t *) data, len);
+
 	while ((len - processed) >= block_size) {
 
 		// load data in the sha input registers
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c
index fbe000e47..bfbfffe7a 100644
--- a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c
@@ -142,11 +142,32 @@ cryerror_t sama_tdes_lld_dma(CRYDriver *cryp, tdes_config_t *params,
 		bool encrypt, const uint8_t *data, size_t data_len, uint8_t * out,
 		const uint8_t *iv) {
 
+  osalDbgAssert(!((uint32_t) data & (L1_CACHE_BYTES - 1)), "data address not cache aligned");
+  osalDbgAssert(!((uint32_t) out & (L1_CACHE_BYTES - 1)), "out address not cache aligned");
+
+#if 0
+  osalDbgAssert(!(data_len & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+#endif
+
+  /*
+   * If size is not multiple of cache line, clean cache region is required.
+   * TODO: remove when size assert works
+   */
+  if (data_len & (L1_CACHE_BYTES - 1)) {
+    cacheCleanRegion((uint8_t *) out, data_len);
+  }
+
 	uint32_t mode = 0;
 	uint32_t *vectors = (uint32_t *) iv;
 
 	osalMutexLock(&cryp->mutex);
 
+  cacheCleanRegion((uint8_t *) data, data_len);
+
+  cryp->out = out;
+  cryp->in = data;
+  cryp->len = data_len;
+
 	cryp->dmachunksize = DMA_CHUNK_SIZE_1;
 
 	cryp->dmawith = DMA_DATA_WIDTH_WORD;
diff --git a/os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.c b/os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.c
index 28e2e38e5..fa925e88a 100644
--- a/os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.c
+++ b/os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.c
@@ -95,9 +95,9 @@ OSAL_IRQ_HANDLER(dmaHandler) {
   OSAL_IRQ_PROLOGUE();
 
 #if SAMA_HAL_IS_SECURE
-  Xdmac *xdmac = XDMAC0;
-#else
   Xdmac *xdmac = XDMAC1;
+#else
+  Xdmac *xdmac = XDMAC0;
 #endif /* SAMA_HAL_IS_SECURE */
 
   uint32_t chan, gis;
@@ -137,10 +137,10 @@ OSAL_IRQ_HANDLER(dmaHandler) {
 void dmaInit(void) {
 
 #if SAMA_HAL_IS_SECURE
-  Xdmac *xdmac = XDMAC0;
-  mtxConfigPeriphSecurity(MATRIX0, ID_XDMAC0, SECURE_PER);
-#else
   Xdmac *xdmac = XDMAC1;
+  mtxConfigPeriphSecurity(MATRIX0, ID_XDMAC1, SECURE_PER);
+#else
+  Xdmac *xdmac = XDMAC0;
 #endif /* SAMA_HAL_IS_SECURE */
 
   uint8_t chan;
@@ -160,9 +160,9 @@ void dmaInit(void) {
 
   /* Setting aic source handler */
 #if SAMA_HAL_IS_SECURE
-  aicSetSourceHandler(ID_XDMAC0, dmaHandler);
-#else
   aicSetSourceHandler(ID_XDMAC1, dmaHandler);
+#else
+  aicSetSourceHandler(ID_XDMAC0, dmaHandler);
 #endif /* SAMA_HAL_IS_SECURE */
 }
 
@@ -248,13 +248,13 @@ sama_dma_channel_t* dmaChannelAllocate(uint32_t priority,
 
   /* Setting AIC and enabling DMA clocks required by the current channel set.*/
 #if SAMA_HAL_IS_SECURE
-    aicSetSourcePriority(ID_XDMAC0, priority);
-    aicEnableInt(ID_XDMAC0);
-    pmcEnableXDMAC0();
-#else
     aicSetSourcePriority(ID_XDMAC1, priority);
     aicEnableInt(ID_XDMAC1);
     pmcEnableXDMAC1();
+#else
+    aicSetSourcePriority(ID_XDMAC0, priority);
+    aicEnableInt(ID_XDMAC0);
+    pmcEnableXDMAC0();
 #endif /* SAMA_HAL_IS_SECURE */
 
   /* Enabling channel's interrupt */
@@ -290,6 +290,10 @@ void dmaChannelRelease(sama_dma_channel_t *dmachp) {
   /* Disables interrupt */
   (dmachp)->xdmac->XDMAC_GID = XDMAC_GID_ID0 << ((dmachp)->chid);
 
+  /* Clear dma descriptor */
+  (dmachp)->xdmac->XDMAC_CHID[((dmachp)->chid)].XDMAC_CNDA = 0;
+  (dmachp)->xdmac->XDMAC_CHID[((dmachp)->chid)].XDMAC_CNDC = 0;
+
   /* Marks the stream as not allocated.*/
   (dmachp)->state = SAMA_DMA_FREE;
 }
diff --git a/os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.h b/os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.h
index 7918d834d..4e3ccf089 100644
--- a/os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.h
+++ b/os/hal/ports/SAMA/LLD/DMAv1/sama_xdmac.h
@@ -146,11 +146,11 @@ typedef struct {
 /**
  * @brief   Returns the number of transfers to be performed.
  * @note    This function can be invoked in both ISR or thread context.
- * @pre     The channel must have been allocated using @p dmaChannelAllocate().
- * @post    After use the channel can be released using @p dmaChannelRelease().
+ * @pre     The stream must have been allocated using @p dmaChannelAllocate().
+ * @post    After use the stream can be released using @p dmaChannelRelease().
  *
- * @param[in] dmachp     pointer to a @p sama_dma_channel_t structure
- * @return               The number of transfers to be performed.
+ * @param[in] dmachp       pointer to a @p sama_dma_channel_t structure
+ * @return              The number of transfers to be performed.
  *
  * @special
  */
@@ -214,7 +214,7 @@ typedef struct {
  * @special
  */
 #define dmaChannelEnable(dmachp) {                                      \
-  (dmachp)->xdmac->XDMAC_GE |= (XDMAC_GE_EN0 << ((dmachp)->chid));      \
+  (dmachp)->xdmac->XDMAC_GE = (XDMAC_GE_EN0 << ((dmachp)->chid));       \
 }
 
 /**
@@ -229,7 +229,7 @@ typedef struct {
  * @special
  */
 #define dmaChannelDisable(dmachp) {                                               \
-  (dmachp)->xdmac->XDMAC_GD |= XDMAC_GD_DI0 << ((dmachp)->chid);                  \
+  (dmachp)->xdmac->XDMAC_GD = XDMAC_GD_DI0 << ((dmachp)->chid);                   \
   while ((((dmachp)->xdmac->XDMAC_GS) & (XDMAC_GS_ST0 << (dmachp)->chid)) == 1) { \
     ;                                                                             \
   }                                                                               \
diff --git a/os/hal/ports/SAMA/LLD/I2Cv1/driver.mk b/os/hal/ports/SAMA/LLD/I2Cv1/driver.mk
new file mode 100644
index 000000000..2534798aa
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/I2Cv1/driver.mk
@@ -0,0 +1,21 @@
+ifeq ($(USE_HAL_I2C_FALLBACK),yes)
+  # Fallback SW driver.
+  ifeq ($(USE_SMART_BUILD),yes)
+    ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+      PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+    endif
+  else
+    PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+  endif
+  PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C
+else
+  # Default HW driver.
+  ifeq ($(USE_SMART_BUILD),yes)
+    ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+      PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.c
+    endif
+  else
+    PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.c
+  endif
+  PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/I2Cv1
+endif
diff --git a/os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.c b/os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.c
new file mode 100644
index 000000000..490364452
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.c
@@ -0,0 +1,963 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    I2Cv1/hal_i2c_lld.c
+ * @brief   SAMA I2C subsystem low level driver source.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+/* SAMA5D2 Clock offset. */
+#define TWI_CLK_OFFSET                      3
+
+/* Mask for 10-bit address. */
+#define TWI_ADDR_MASK_10                    0x380
+
+/* Mask for 10-bit address case for DADR field. */
+#define TWI_ADDR_10_DADR_MASK               0x78
+#define TWI_ADDR_10_IADR_MASK               0xFF
+
+/* Mask for internal address check. */
+#define TWI_INTERNAL_ADDR_MASK              0xFF
+
+/* Mask for TWI errors interrupt. */
+#define TWI_ERROR_MASK                      (TWI_SR_OVRE | TWI_SR_UNRE |      \
+                                             TWI_SR_NACK | TWI_SR_ARBLST |    \
+                                             TWI_SR_TOUT | TWI_SR_PECERR)
+
+/*===========================================================================*/
+/* Driver local macros.                                                      */
+/*===========================================================================*/
+#if !defined ROUND_INT_DIV
+#define ROUND_INT_DIV(n,d)                  (((n) + ((d)-1)) / (d))
+#endif
+
+/**
+ * @brief   Enable write protection on TWI registers block.
+ *
+ * @param[in] i2cp   pointer to a TWI register block
+ *
+ * @notapi
+ */
+#define twiEnableWP(i2cp) {                                                   \
+  i2cp->TWI_WPMR = TWI_WPMR_WPKEY_PASSWD | TWI_WPMR_WPEN;                     \
+}
+
+/**
+ * @brief   Disable write protection on TWI registers block.
+ *
+ * @param[in] i2cp    pointer to a TWI register block
+ *
+ * @notapi
+ */
+#define twiDisableWP(i2cp) {                                                  \
+  i2cp->TWI_WPMR = TWI_WPMR_WPKEY_PASSWD;                                     \
+}
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/** @brief I2C0 driver identifier.*/
+#if SAMA_I2C_USE_TWIHS0 || defined(__DOXYGEN__)
+I2CDriver I2CD0;
+#endif
+
+/** @brief I2C1 driver identifier.*/
+#if SAMA_I2C_USE_TWIHS1 || defined(__DOXYGEN__)
+I2CDriver I2CD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types.                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+/**
+ * @brief   Read a byte from TWI_RHR register.
+ *
+ * @param[in] reg       pointer to the target register
+ * @param[in] value     pointer to the transmit variable
+ *
+ * @notapi
+ */
+static inline void i2c_lld_read_byte(volatile const void* reg, uint8_t* value) {
+  *value = *(volatile const uint8_t*)reg;
+}
+
+/**
+ * @brief   Write a byte to TWI_THR register.
+ *
+ * @param[in] reg       pointer to the target register
+ * @param[in] value     pointer to the receive variable
+ *
+ * @notapi
+ */
+static inline void i2c_lld_write_byte(volatile void* reg, uint8_t value) {
+  *(volatile uint8_t*)reg = value;
+}
+
+/**
+ * @brief   Read bytes.
+ * @note    Disables WRITE PROTECTION before using
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_read_bytes(I2CDriver *i2cp) {
+
+  if (i2cp->rxbytes == 1) {
+
+    /* Starts and stops the operation for 1 byte read.*/
+    i2cp->i2c->TWI_CR = TWI_CR_START | TWI_CR_STOP;
+    i2cp->i2c->TWI_IER = TWI_IER_TXCOMP;
+    while ((i2cp->i2c->TWI_SR & TWI_SR_RXRDY) == 0);
+
+    i2c_lld_read_byte(&i2cp->i2c->TWI_RHR, i2cp->rxbuf);
+  }
+
+  if (i2cp->rxbytes == 2) {
+
+    /* Starts the operation.*/
+    i2cp->i2c->TWI_CR = TWI_CR_START;
+    i2cp->i2c->TWI_IER = TWI_IER_TXCOMP;
+    while ((i2cp->i2c->TWI_SR & TWI_SR_RXRDY) == 0);
+
+    /* Stops the operation and read penultimate byte. */
+    i2cp->i2c->TWI_CR = TWI_CR_STOP;
+
+    i2c_lld_read_byte(&i2cp->i2c->TWI_RHR, &i2cp->rxbuf[0]);
+
+    while ((i2cp->i2c->TWI_SR & TWI_SR_RXRDY) == 0);
+
+    /* Read last byte. */
+    i2c_lld_read_byte(&i2cp->i2c->TWI_RHR, &i2cp->rxbuf[1]);
+  }
+
+  if (i2cp->rxbytes > 2) {
+
+    /* RX DMA setup.*/
+    dmaChannelSetDestination(i2cp->dmarx, i2cp->rxbuf);
+    dmaChannelSetTransactionSize(i2cp->dmarx, i2cp->rxbytes -2);
+
+    /* Starts the operation.*/
+    i2cp->i2c->TWI_CR = TWI_CR_START;
+
+    /* Start the DMA. */
+    dmaChannelEnable(i2cp->dmarx);
+  }
+}
+
+/**
+ * @brief   Write bytes.
+ * @note    Disables WRITE PROTECTION before using
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_write_bytes(I2CDriver *i2cp) {
+
+  size_t txsize = i2cp->txbytes;
+
+  if (txsize == 1) {
+
+    i2c_lld_write_byte(&i2cp->i2c->TWI_THR, i2cp->txbuf[0]);
+
+    /* Enable TXCOMP interrupt. */
+    i2cp->i2c->TWI_IER = TWI_IER_TXCOMP;
+
+    i2cp->i2c->TWI_CR = TWI_CR_STOP;
+
+    /* Starts and stops the operation for 1 byte write.*/
+    while ((i2cp->i2c->TWI_SR & TWI_SR_TXRDY) == 0);
+  }
+
+  if (txsize > 1) {
+    /* RX DMA setup.*/
+    dmaChannelSetSource(i2cp->dmatx, i2cp->txbuf);
+    dmaChannelSetTransactionSize(i2cp->dmatx, (txsize - 1));
+    dmaChannelEnable(i2cp->dmatx);
+  }
+}
+
+/**
+ * @brief   Set operation mode of I2C hardware.
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_set_opmode(I2CDriver *i2cp) {
+
+  switch (i2cp->config->op_mode) {
+  case OPMODE_I2C:
+    i2cp->i2c->TWI_CR = TWI_CR_SMBDIS;
+    break;
+  case OPMODE_SMBUS:
+    i2cp->i2c->TWI_CR = TWI_CR_SMBEN;
+    break;
+  }
+}
+
+/**
+ * @brief   DMA RX end IRQ handler.
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ * @param[in] flags     pre-shifted content of the ISR register
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_rx_interrupt(I2CDriver *i2cp, uint32_t flags) {
+
+  /* DMA errors handling.*/
+#if defined(SAMA_I2C_DMA_ERROR_HOOK)
+  if ((flags & (XDMAC_CIS_RBEIS | XDMAC_CIS_ROIS)) != 0) {
+    SAMA_I2C_DMA_ERROR_HOOK(i2cp);
+  }
+#else
+  (void)flags;
+#endif
+
+  /* DMA channel disable. */
+  dmaChannelDisable(i2cp->dmarx);
+
+  /* Cache is enabled */
+  cacheInvalidateRegion(i2cp->rxbuf, i2cp->rxbytes - 1);
+
+  /* Wait for RXRDY flag. */
+  while ((i2cp->i2c->TWI_SR & TWI_SR_RXRDY) == 0);
+
+  /* Stops the operation and read the last 2 bytes.*/
+  i2cp->i2c->TWI_CR = TWI_CR_STOP;
+  i2c_lld_read_byte(&i2cp->i2c->TWI_RHR, &i2cp->rxbuf[i2cp->rxbytes - 2]);
+
+  /* Wait for the last byte. */
+  while ((i2cp->i2c->TWI_SR & TWI_SR_RXRDY) == 0);
+
+  /* Enable TXCOMP interrupt. */
+  i2cp->i2c->TWI_IER = TWI_IER_TXCOMP;
+
+  /* Read the last byte. */
+  i2c_lld_read_byte(&i2cp->i2c->TWI_RHR, &i2cp->rxbuf[i2cp->rxbytes - 1]);
+
+}
+
+
+/**
+ * @brief    DMA TX end IRQ handler.
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_tx_interrupt(I2CDriver *i2cp, uint32_t flags) {
+
+  const uint8_t tx_last_byte = i2cp->txbuf[i2cp->txbytes - 1];
+  /* DMA errors handling.*/
+#if defined(SAMA_I2C_DMA_ERROR_HOOK)
+  if ((flags & (XDMAC_CIS_WBEIS | XDMAC_CIS_ROIS)) != 0) {
+    SAMA_I2C_DMA_ERROR_HOOK(i2cp);
+  }
+#else
+  (void)flags;
+#endif
+
+  dmaChannelDisable(i2cp->dmatx);
+
+  /* Wait for the TX ready flag. */
+  while ((i2cp->i2c->TWI_SR & TWI_SR_TXRDY) == 0);
+
+  /* Stops the operation and transmit the last byte.*/
+  i2cp->i2c->TWI_CR = TWI_CR_STOP;
+
+  i2cp->i2c->TWI_IER = TWI_IER_TXCOMP;
+
+  i2c_lld_write_byte(&i2cp->i2c->TWI_THR, tx_last_byte);
+}
+
+/**
+ * @brief   I2C interrupts handler.
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t flags) {
+
+  /* Used only in 1/2 bytes transmissions in order to wake up the thread. */
+  if (flags & TWI_SR_TXCOMP) {
+    _i2c_wakeup_isr(i2cp);
+  }
+
+  i2cp->errors = I2C_NO_ERROR;
+
+  if (flags & TWI_SR_OVRE)                             /* Overrun error. */
+    i2cp->errors |= I2C_OVERRUN;
+
+  if (flags & TWI_SR_UNRE)                             /* Underrun error. */
+    i2cp->errors |= I2C_OVERRUN;
+
+  if (flags & TWI_SR_NACK) {                           /* Acknowledge fail. */
+    i2cp->i2c->TWI_CR = TWI_CR_STOP;                   /* Setting stop bit. */
+    i2cp->errors |= I2C_ACK_FAILURE;
+  }
+
+  if (flags & TWI_SR_ARBLST)                           /* Arbitration lost. */
+    i2cp->errors |= I2C_ARBITRATION_LOST;
+
+  if (flags & TWI_SR_TOUT)                             /* SMBus Timeout. */
+    i2cp->errors |= I2C_TIMEOUT;
+
+  if (flags & TWI_SR_PECERR)                           /* PEC error. */
+    i2cp->errors |= I2C_PEC_ERROR;
+
+  /* If some error has been identified then sends wakes the waiting thread.*/
+  if (i2cp->errors != I2C_NO_ERROR)
+    _i2c_wakeup_error_isr(i2cp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+#if SAMA_I2C_USE_TWIHS0 || defined(__DOXYGEN__)
+/**
+ * @brief   TWIHS0 interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(SAMA_TWIHS0_HANDLER) {
+
+  OSAL_IRQ_PROLOGUE();
+
+  uint32_t sr = I2CD0.i2c->TWI_SR;
+
+  I2CD0.i2c->TWI_IDR = TWI_IDR_TXCOMP;
+
+  i2c_lld_serve_interrupt(&I2CD0, sr);
+  aicAckInt();
+
+  OSAL_IRQ_EPILOGUE();
+}
+#endif /* SAMA_I2C_USE_TWIHS0 */
+
+#if SAMA_I2C_USE_TWIHS1 || defined(__DOXYGEN__)
+/**
+ * @brief   TWIHS1 interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(SAMA_TWIHS1_HANDLER) {
+
+  OSAL_IRQ_PROLOGUE();
+
+  uint32_t sr = I2CD1.i2c->TWI_SR;
+
+  I2CD1.i2c->TWI_IDR = TWI_IDR_TXCOMP;
+
+  i2c_lld_serve_interrupt(&I2CD1, sr);
+  aicAckInt();
+
+  OSAL_IRQ_EPILOGUE();
+}
+
+#endif /* SAMA_I2C_USE_TWIHS1 */
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+/**
+ * @brief   Low level I2C driver initialization.
+ *
+ * @notapi
+ */
+void i2c_lld_init(void) {
+
+#if SAMA_I2C_USE_TWIHS0
+#if SAMA_HAL_IS_SECURE
+  mtxConfigPeriphSecurity(MATRIX1, ID_TWIHS0, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+  /* Driver initialization.*/
+  i2cObjectInit(&I2CD0);
+  I2CD0.thread    = NULL;
+  I2CD0.i2c       = TWIHS0;
+  I2CD0.dmarx     = NULL;
+  I2CD0.dmatx     = NULL;
+  I2CD0.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+                    XDMAC_CC_MBSIZE_SIXTEEN |
+                    XDMAC_CC_DSYNC_PER2MEM |
+                    XDMAC_CC_PROT_SEC |
+                    XDMAC_CC_CSIZE_CHK_1 |
+                    XDMAC_CC_DWIDTH_BYTE |
+                    XDMAC_CC_SIF_AHB_IF1 |
+                    XDMAC_CC_DIF_AHB_IF0 |
+                    XDMAC_CC_SAM_FIXED_AM |
+                    XDMAC_CC_DAM_INCREMENTED_AM |
+                    XDMAC_CC_PERID(PERID_TWIHS0_RX);
+  I2CD0.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+                    XDMAC_CC_MBSIZE_SIXTEEN |
+                    XDMAC_CC_DSYNC_MEM2PER |
+                    XDMAC_CC_PROT_SEC |
+                    XDMAC_CC_CSIZE_CHK_1 |
+                    XDMAC_CC_DWIDTH_BYTE |
+                    XDMAC_CC_SIF_AHB_IF0 |
+                    XDMAC_CC_DIF_AHB_IF1 |
+                    XDMAC_CC_SAM_INCREMENTED_AM |
+                    XDMAC_CC_DAM_FIXED_AM |
+                    XDMAC_CC_PERID(PERID_TWIHS0_TX);
+#endif /* SAMA_I2C_USE_TWIHS0 */
+
+#if SAMA_I2C_USE_TWIHS1
+#if SAMA_HAL_IS_SECURE
+  mtxConfigPeriphSecurity(MATRIX1, ID_TWIHS1, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+  /* Driver initialization.*/
+  i2cObjectInit(&I2CD1);
+  I2CD1.thread    = NULL;
+  I2CD1.i2c       = TWIHS1;
+  I2CD1.dmarx     = NULL;
+  I2CD1.dmatx     = NULL;
+  I2CD1.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+                    XDMAC_CC_MBSIZE_SIXTEEN |
+                    XDMAC_CC_DSYNC_PER2MEM |
+                    XDMAC_CC_PROT_SEC |
+                    XDMAC_CC_CSIZE_CHK_1 |
+                    XDMAC_CC_DWIDTH_BYTE |
+                    XDMAC_CC_SIF_AHB_IF1 |
+                    XDMAC_CC_DIF_AHB_IF0 |
+                    XDMAC_CC_SAM_FIXED_AM |
+                    XDMAC_CC_DAM_INCREMENTED_AM |
+                    XDMAC_CC_PERID(PERID_TWIHS1_RX);
+  I2CD1.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+                    XDMAC_CC_MBSIZE_SIXTEEN |
+                    XDMAC_CC_DSYNC_MEM2PER |
+                    XDMAC_CC_PROT_SEC |
+                    XDMAC_CC_CSIZE_CHK_1 |
+                    XDMAC_CC_DWIDTH_BYTE |
+                    XDMAC_CC_SIF_AHB_IF0 |
+                    XDMAC_CC_DIF_AHB_IF1 |
+                    XDMAC_CC_SAM_INCREMENTED_AM |
+                    XDMAC_CC_DAM_FIXED_AM |
+                    XDMAC_CC_PERID(PERID_TWIHS1_TX);
+#endif /* SAMA_I2C_USE_TWIHS1 */
+}
+
+/**
+ * @brief   Configures and activates the I2C peripheral.
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_start(I2CDriver *i2cp) {
+
+  uint32_t ck_div, clh_div, hold;
+
+  /* If in stopped state then enables the I2C and DMA clocks.*/
+  if (i2cp->state == I2C_STOP) {
+
+#if SAMA_I2C_USE_TWIHS0
+    if (&I2CD0 == i2cp) {
+
+      i2cp->dmarx = dmaChannelAllocate(SAMA_I2C_TWIHS0_DMA_IRQ_PRIORITY,
+                                       (sama_dmaisr_t)i2c_lld_serve_rx_interrupt,
+                                       (void *)i2cp);
+      osalDbgAssert(i2cp->dmarx != NULL, "no channel allocated");
+
+      i2cp->dmatx = dmaChannelAllocate(SAMA_I2C_TWIHS0_DMA_IRQ_PRIORITY,
+                                       (sama_dmaisr_t)i2c_lld_serve_tx_interrupt,
+                                       (void *)i2cp);
+      osalDbgAssert(i2cp->dmatx != NULL, "no channel allocated");
+
+      pmcEnableTWIHS0();
+      /* To prevent spurious interrupt */
+      aicSetIntSourceType(ID_TWIHS0, EXT_NEGATIVE_EDGE);
+      aicSetSourcePriority(ID_TWIHS0, SAMA_I2C_TWIHS0_IRQ_PRIORITY);
+      aicSetSourceHandler(ID_TWIHS0, SAMA_TWIHS0_HANDLER);
+      aicEnableInt(ID_TWIHS0);
+    }
+#endif /* SAMA_I2C_USE_TWIHS0 */
+
+#if SAMA_I2C_USE_TWIHS1
+    if (&I2CD1 == i2cp) {
+
+      i2cp->dmarx = dmaChannelAllocate(SAMA_I2C_TWIHS1_DMA_IRQ_PRIORITY,
+                                       (sama_dmaisr_t)i2c_lld_serve_rx_interrupt,
+                                       (void *)i2cp);
+      osalDbgAssert(i2cp->dmarx != NULL, "no channel allocated");
+
+      i2cp->dmatx = dmaChannelAllocate(SAMA_I2C_TWIHS1_DMA_IRQ_PRIORITY,
+                                       (sama_dmaisr_t)i2c_lld_serve_tx_interrupt,
+                                       (void *)i2cp);
+      osalDbgAssert(i2cp->dmatx != NULL, "no channel allocated");
+
+      pmcEnableTWIHS1();
+      /* To prevent spurious interrupt */
+      aicSetIntSourceType(ID_TWIHS1, EXT_NEGATIVE_EDGE);
+      aicSetSourcePriority(ID_TWIHS1, SAMA_I2C_TWIHS1_IRQ_PRIORITY);
+      aicSetSourceHandler(ID_TWIHS1, SAMA_TWIHS1_HANDLER);
+      aicEnableInt(ID_TWIHS1);
+    }
+#endif /* SAMA_I2C_USE_TWIHS1 */
+  }
+
+  /* Set mode */
+  dmaChannelSetMode(i2cp->dmarx, i2cp->rxdmamode);
+  dmaChannelSetSource(i2cp->dmarx, &i2cp->i2c->TWI_RHR);
+
+  dmaChannelSetMode(i2cp->dmatx, i2cp->txdmamode);
+  dmaChannelSetDestination(i2cp->dmatx, &i2cp->i2c->TWI_THR);
+
+  /* Disable write protection. */
+  twiDisableWP(i2cp->i2c);
+
+  /* TWI software reset */
+  i2cp->i2c->TWI_CR = TWI_CR_SWRST;
+
+  /* TWI set operation mode. */
+  i2c_lld_set_opmode(i2cp);
+
+  /* Configure dummy slave address */
+  i2cp->i2c->TWI_MMR = 0;
+
+  /* Compute clock */
+  for (ck_div = 0; ck_div < 7; ck_div++) {
+    clh_div = ((SAMA_TWIHSxCLK / i2cp->config->clock_speed) - 2 * (TWI_CLK_OFFSET)) >> ck_div;
+    if (clh_div <= 511) {
+      break;
+    }
+  }
+
+  /* Compute holding time (I2C spec requires 300ns) */
+  hold = TWI_CWGR_HOLD(ROUND_INT_DIV((uint32_t)(0.3 * SAMA_TWIHSxCLK), 1000000) - 3);
+
+  /* Configure clock */
+  i2cp->i2c->TWI_CWGR = TWI_CWGR_CKDIV(ck_div) |
+                        TWI_CWGR_CHDIV(clh_div >> 1) |
+                        TWI_CWGR_CLDIV(clh_div >> 1) |
+                        hold;
+
+  /* Clear status flag */
+  i2cp->i2c->TWI_SR;
+
+  /* Enable Interrupt. */
+  i2cp->i2c->TWI_IER = TWI_ERROR_MASK;
+
+  /* Set master mode */
+  i2cp->i2c->TWI_CR = TWI_CR_SVDIS;
+  i2cp->i2c->TWI_CR = TWI_CR_MSEN;
+
+  /* Enable write protection. */
+  twiEnableWP(i2cp->i2c);
+}
+
+/**
+ * @brief   Deactivates the I2C peripheral.
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_stop(I2CDriver *i2cp) {
+
+  /* If not in stopped state then disables the I2C clock.*/
+  if (i2cp->state != I2C_STOP) {
+
+    /* Disable write protection. */
+    twiDisableWP(i2cp->i2c);
+
+    /* I2C disable.*/
+
+    /* Disable interrupts. */
+    i2cp->i2c->TWI_IDR = TWI_ERROR_MASK;
+
+    /* TWI software reset. */
+    i2cp->i2c->TWI_CR = TWI_CR_SWRST;
+    i2cp->i2c->TWI_MMR = 0;
+
+    /* DMA channel release. */
+    dmaChannelRelease(i2cp->dmatx);
+    dmaChannelRelease(i2cp->dmarx);
+
+#if SAMA_I2C_USE_TWIHS0
+    if (&I2CD0 == i2cp) {
+      pmcDisableTWIHS0();
+    }
+#endif
+
+#if SAMA_I2C_USE_TWIHS1
+    if (&I2CD1 == i2cp) {
+      pmcDisableTWIHS1();
+    }
+#endif
+
+    /* Enable write protection. */
+    twiEnableWP(i2cp->i2c);
+  }
+
+  i2cp->txbuf = NULL;
+  i2cp->rxbuf = NULL;
+  i2cp->txbytes = 0;
+  i2cp->rxbytes = 0;
+}
+
+/**
+ * @brief   Receives data via the I2C bus as master.
+ * @details
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ * @param[in] addr      slave device address
+ * @param[out] rxbuf    pointer to the receive buffer
+ * @param[in] rxbytes   number of bytes to be received
+ * @param[in] timeout   the number of ticks before the operation timeouts,
+ *                      the following special values are allowed:
+ *                      - @a TIME_INFINITE no timeout.
+ *                      .
+ * @return              The operation status.
+ * @retval MSG_OK       if the function succeeded.
+ * @retval MSG_RESET    if one or more I2C errors occurred, the errors can
+ *                      be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT  if a timeout occurred before operation end. <b>After a
+ *                      timeout the driver must be stopped and restarted
+ *                      because the bus is in an uncertain state</b>.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+                                     uint8_t *rxbuf, size_t rxbytes,
+                                     sysinterval_t timeout) {
+
+  osalDbgAssert(!((uint32_t) rxbuf & (L1_CACHE_BYTES - 1)), "rxbuf address not cache aligned");
+
+#if 0
+  osalDbgAssert(!(rxbytes & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+#endif
+
+  i2cp->txbuf = NULL;
+  i2cp->rxbuf = rxbuf;
+  i2cp->txbytes = 0;
+  i2cp->rxbytes = rxbytes;
+
+  /*
+   * If size is not multiple of cache line, clean cache region is required.
+   * TODO: remove when size assert works
+   */
+  if (rxbytes & (L1_CACHE_BYTES - 1)) {
+    cacheCleanRegion((uint8_t *) rxbuf, rxbytes);
+  }
+
+  systime_t start, end;
+
+  /* Resetting error flags for this transfer.*/
+  i2cp->errors = I2C_NO_ERROR;
+
+  /* Disable write protection. */
+  twiDisableWP(i2cp->i2c);
+
+  /* Compute device address and/or internal address. */
+  i2cp->i2c->TWI_MMR = 0;
+
+  if ((addr & TWI_ADDR_MASK_10) != 0) {
+    /* 10-bit address. */
+    if (i2cp->config->op_mode == OPMODE_I2C) {
+
+      /* Store 2 slave device address MSB bits in MMR_DADR with 11110 mask. Configure number of internal slave address bytes in MMR_IADRSZ as 1. */
+      i2cp->i2c->TWI_MMR = TWI_MMR_DADR((addr >> 8) | TWI_ADDR_10_DADR_MASK) |
+                           TWI_MMR_IADRSZ_1_BYTE | TWI_MMR_MREAD;
+      i2cp->i2c->TWI_IADR = TWI_ADDR_10_IADR_MASK & addr;
+
+    } else if (i2cp->config->op_mode == OPMODE_SMBUS)
+      osalDbgAssert((addr & TWI_ADDR_MASK_10) != 0, "10-bit address not supported in SMBus mode");
+
+  } else {
+    /* 7-bit address. */
+    /* Store slave device address in MMR_DADR. */
+    i2cp->i2c->TWI_MMR |= TWI_MMR_DADR(addr);
+
+    /* Configure read direction. */
+    i2cp->i2c->TWI_MMR |= TWI_MMR_MREAD;
+  }
+  /* Releases the lock from high level driver.*/
+  osalSysUnlock();
+
+  /* Calculating the time window for the timeout on the busy bus condition.*/
+  start = osalOsGetSystemTimeX();
+  end = osalTimeAddX(start, OSAL_MS2I(SAMA_I2C_BUSY_TIMEOUT));
+
+  /* Waits until BUSY flag is reset or, alternatively, for a timeout
+     condition.*/
+  while (true) {
+    osalSysLock();
+
+    /* If the bus is not busy then the operation can continue, note, the
+       loop is exited in the locked state.*/
+    if (i2cp->i2c->TWI_SR & (TWI_SR_TXCOMP | TWI_SR_RXRDY))
+      break;
+
+    /* If the system time went outside the allowed window then a timeout
+       condition is returned.*/
+    if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end))
+      return MSG_TIMEOUT;
+
+    osalSysUnlock();
+  }
+
+  i2c_lld_read_bytes(i2cp);
+
+  /* Enable write protection. */
+  twiEnableWP(i2cp->i2c);
+
+  /* Waits for the operation completion or a timeout.*/
+  return osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+}
+
+/**
+ * @brief   Transmits data via the I2C bus as master.
+ * @details When performing reading through write you can not write more than
+ *          3 bytes of data to I2C slave. This is SAMA platform limitation.
+ *          Internal address bytes must be set in txbuf from LSB (position 0 of the buffer) to MSB
+ *          (position 1 or 2 of the buffer depending from the number of internal address bytes.
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ * @param[in] addr      slave device address
+ * @param[in] txbuf     pointer to the transmit buffer
+ * @param[in] txbytes   number of bytes to be transmitted
+ * @param[out] rxbuf    pointer to the receive buffer
+ * @param[in] rxbytes   number of bytes to be received
+ * @param[in] timeout   the number of ticks before the operation timeouts,
+ *                      the following special values are allowed:
+ *                      - @a TIME_INFINITE no timeout.
+ *                      .
+ * @return              The operation status.
+ * @retval MSG_OK       if the function succeeded.
+ * @retval MSG_RESET    if one or more I2C errors occurred, the errors can
+ *                      be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT  if a timeout occurred before operation end. <b>After a
+ *                      timeout the driver must be stopped and restarted
+ *                      because the bus is in an uncertain state</b>.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+                                      const uint8_t *txbuf, size_t txbytes,
+                                      uint8_t *rxbuf, size_t rxbytes,
+                                      sysinterval_t timeout) {
+
+  osalDbgAssert(!((uint32_t) txbuf & (L1_CACHE_BYTES - 1)), "txbuf address not cache aligned");
+  osalDbgAssert(!((uint32_t) rxbuf & (L1_CACHE_BYTES - 1)), "rxbuf address not cache aligned");
+
+#if 0
+  osalDbgAssert(!(rxbytes & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+#endif
+
+  i2cp->txbuf = txbuf;
+  i2cp->rxbuf = rxbuf;
+  i2cp->txbytes = txbytes;
+  i2cp->rxbytes = rxbytes;
+
+  /* Cache is enabled */
+  cacheCleanRegion((uint8_t *)i2cp->txbuf, txbytes);
+
+  /*
+   * If size is not multiple of cache line, clean cache region is required.
+   * TODO: remove when size assert works
+   */
+  if (rxbytes & (L1_CACHE_BYTES - 1)) {
+    cacheCleanRegion((uint8_t *) rxbuf, rxbytes);
+  }
+
+  systime_t start, end;
+
+  /* Resetting error flags for this transfer.*/
+  i2cp->errors = I2C_NO_ERROR;
+
+  /* Disable write protection. */
+  twiDisableWP(i2cp->i2c);
+
+  /* prepare to read through write operation */
+  if (rxbytes > 0){
+
+    osalDbgAssert(txbytes <= 3, "Number of internal address bytes not supported. Max number of internal address bytes is 3.");
+
+    i2cp->i2c->TWI_MMR  = 0;
+
+    /* Compute slave address and internal addresses. */
+
+    /* Internal address of I2C slave was set in special Atmel registers.
+     * Now we must call read function. The I2C cell automatically sends
+     * bytes from IADR register to bus and issues repeated start. */
+
+    if ((addr & TWI_ADDR_MASK_10) != 0) {
+      /* 10-bit address. */
+      if (i2cp->config->op_mode == OPMODE_I2C) {
+
+        uint16_t mem_addr = 0;
+
+        osalDbgAssert(txbytes <= 2, "Number of internal address bytes not supported");
+
+        /* Store 2 slave device address MSB bits in MMR_DADR with 11110 mask. Configure number of internal slave address bytes in
+         * MMR_IADRSZ as 1 + slave internal addresses. */
+        i2cp->i2c->TWI_MMR = TWI_MMR_DADR((addr >> 8) | TWI_ADDR_10_DADR_MASK) |
+                             TWI_MMR_IADRSZ(txbytes + 1);
+
+        if(txbytes == 1)
+          mem_addr = i2cp->txbuf[0];
+
+        else if(txbytes == 2)
+          mem_addr = i2cp->txbuf[0] | (i2cp->txbuf[1] << 8);
+
+        /* Store the rest of the 10-bit address in IADR register. Also store the internal slave address bytes. */
+        i2cp->i2c->TWI_IADR = (TWI_ADDR_10_IADR_MASK & addr) | (mem_addr << 8);
+
+      } else if (i2cp->config->op_mode == OPMODE_SMBUS)
+        osalDbgAssert((addr & TWI_ADDR_MASK_10) != 0, "10-bit address not supported in SMBus mode");
+
+    } else {
+      /* 7-bit address. */
+      i2cp->i2c->TWI_MMR |= txbytes << 8;
+
+      /* Store internal slave address in TWI_IADR registers */
+      i2cp->i2c->TWI_IADR = 0;
+      while (txbytes > 0){
+        i2cp->i2c->TWI_IADR = (i2cp->i2c->TWI_IADR << 8);
+        i2cp->i2c->TWI_IADR |= *(txbuf++);
+        txbytes--;
+      }
+      /* Store slave device address in MMR_DADR. */
+      i2cp->i2c->TWI_MMR |= TWI_MMR_DADR(addr);
+    }
+
+  #if 0
+    osalDbgAssert(!(rxbytes & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+  #endif
+
+    /* Configure read direction. */
+    i2cp->i2c->TWI_MMR |= TWI_MMR_MREAD;
+
+    /* Releases the lock from high level driver.*/
+    osalSysUnlock();
+
+    /* Calculating the time window for the timeout on the busy bus condition.*/
+    start = osalOsGetSystemTimeX();
+    end = osalTimeAddX(start, OSAL_MS2I(SAMA_I2C_BUSY_TIMEOUT));
+
+    /* Waits until BUSY flag is reset or, alternatively, for a timeout
+       condition.*/
+    while (true) {
+      osalSysLock();
+
+      /* If the bus is not busy then the operation can continue, note, the
+         loop is exited in the locked state.*/
+      if (i2cp->i2c->TWI_SR & (TWI_SR_TXCOMP | TWI_SR_RXRDY))
+        break;
+
+      /* If the system time went outside the allowed window then a timeout
+         condition is returned.*/
+      if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end))
+        return MSG_TIMEOUT;
+
+      osalSysUnlock();
+    }
+
+    i2c_lld_read_bytes(i2cp);
+
+    /* Enable write protection. */
+    twiEnableWP(i2cp->i2c);
+
+    /* Waits for the operation completion or a timeout.*/
+    return osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+
+  } else {
+    /* Compute device slave address. Internal slave address are sent as data. */
+
+    i2cp->i2c->TWI_MMR = 0;
+
+    if ((addr & TWI_ADDR_MASK_10) != 0) {
+      /* 10-bit address. */
+      if (i2cp->config->op_mode == OPMODE_I2C) {
+
+        /* Store 2 slave device address MSB bits in MMR_DADR with 11110 mask. Configure number of internal slave address bytes in MMR_IADRSZ as 1. */
+        i2cp->i2c->TWI_MMR = TWI_MMR_DADR((addr >> 8) | TWI_ADDR_10_DADR_MASK) |
+                             TWI_MMR_IADRSZ_1_BYTE;
+        i2cp->i2c->TWI_IADR = TWI_ADDR_10_IADR_MASK & addr;
+
+      } else if (i2cp->config->op_mode == OPMODE_SMBUS)
+        osalDbgAssert((addr & TWI_ADDR_MASK_10) != 0, "10-bit address not supported in SMBus mode");
+
+    } else {
+      /* 7-bit address. */
+      /* Store slave device address in MMR_DADR. */
+      i2cp->i2c->TWI_MMR |= TWI_MMR_DADR(addr);
+    }
+
+    /* Releases the lock from high level driver.*/
+    osalSysUnlock();
+
+    /* Calculating the time window for the timeout on the busy bus condition.*/
+    start = osalOsGetSystemTimeX();
+    end = osalTimeAddX(start, OSAL_MS2I(SAMA_I2C_BUSY_TIMEOUT));
+
+    /* Waits until BUSY flag is reset or, alternatively, for a timeout
+       condition.*/
+    while (true) {
+      osalSysLock();
+
+      /* If the bus is not busy then the operation can continue, note, the
+         loop is exited in the locked state.*/
+      if (i2cp->i2c->TWI_SR & (TWI_SR_TXCOMP | TWI_SR_RXRDY))
+        break;
+
+      /* If the system time went outside the allowed window then a timeout
+         condition is returned.*/
+      if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end))
+        return MSG_TIMEOUT;
+
+      osalSysUnlock();
+    }
+
+    i2c_lld_write_bytes(i2cp);
+
+    /* Enable write protection. */
+    twiEnableWP(i2cp->i2c);
+
+    /* Waits for the operation completion or a timeout.*/
+    return osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+  }
+}
+
+#endif /* HAL_USE_I2C */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.h b/os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.h
new file mode 100644
index 000000000..1d3538852
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/I2Cv1/hal_i2c_lld.h
@@ -0,0 +1,277 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    I2Cv1/hal_i2c_lld.h
+ * @brief   SAMA I2C subsystem low level driver header.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#ifndef HAL_I2C_LLD_H
+#define HAL_I2C_LLD_H
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings.                                         */
+/*===========================================================================*/
+
+/**
+ * @name    Configuration options
+ * @{
+ */
+/**
+ * @brief   I2C0 driver enable switch.
+ * @details If set to @p TRUE the support for TWIHS0 is included.
+ * @note    The default is @p FALSE.
+ */
+#if !defined(SAMA_I2C_USE_TWIHS0) || defined(__DOXYGEN__)
+#define SAMA_I2C_USE_TWIHS0                 FALSE
+#endif
+
+/**
+ * @brief   I2C1 driver enable switch.
+ * @details If set to @p TRUE the support for TWIHS1 is included.
+ * @note    The default is @p FALSE.
+ */
+#if !defined(SAMA_I2C_USE_TWIHS1) || defined(__DOXYGEN__)
+#define SAMA_I2C_USE_TWIHS1                 FALSE
+#endif
+
+/**
+ * @brief   I2C timeout on busy condition in milliseconds.
+ */
+#if !defined(SAMA_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__)
+#define SAMA_I2C_BUSY_TIMEOUT               50
+#endif
+
+/**
+ * @brief   I2C0 interrupt priority level setting.
+ */
+#if !defined(SAMA_I2C_TWIHS0_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SAMA_I2C_TWIHS0_IRQ_PRIORITY        6
+#endif
+
+/**
+ * @brief   I2C1 interrupt priority level setting.
+ */
+#if !defined(SAMA_I2C_TWIHS1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SAMA_I2C_TWIHS1_IRQ_PRIORITY        6
+#endif
+
+/**
+* @brief   I2C0 DMA IRQ priority (0..7|lowest..highest).
+* @note    The priority level is used for both the TX and RX DMA channels.
+*/
+#if !defined(SAMA_I2C_TWIHS0_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SAMA_I2C_TWIHS0_DMA_IRQ_PRIORITY    6
+#endif
+
+/**
+* @brief   I2C1 DMA IRQ priority (0..7|lowest..highest).
+* @note    The priority level is used for both the TX and RX DMA streams.
+*/
+#if !defined(SAMA_I2C_TWIHS1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SAMA_I2C_TWIHS1_DMA_IRQ_PRIORITY    6
+#endif
+
+/**
+ * @brief   I2C DMA error hook.
+ * @note    The default action for DMA errors is a system halt because DMA
+ *          error can only happen because programming errors.
+ */
+#if !defined(SAMA_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define SAMA_I2C_DMA_ERROR_HOOK(i2cp)      osalSysHalt("DMA failure")
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks.                                       */
+/*===========================================================================*/
+
+/** @brief  error checks */
+
+#if !SAMA_I2C_USE_TWIHS0 && !SAMA_I2C_USE_TWIHS1
+#error "I2C driver activated but no TWIHS peripheral assigned"
+#endif
+
+#if !defined(SAMA_DMA_REQUIRED)
+#define SAMA_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+
+/**
+ * @brief   Type representing an I2C address.
+ */
+typedef uint32_t i2caddr_t;
+
+/**
+ * @brief   Type of I2C driver condition flags.
+ */
+typedef uint32_t i2cflags_t;
+
+/**
+ * @brief   Supported modes for the I2C bus.
+ */
+typedef enum {
+  OPMODE_I2C = 1,
+  OPMODE_SMBUS = 2,
+} i2copmode_t;
+
+/**
+ * @brief   Type of I2C driver configuration structure.
+ */
+typedef struct {
+  /* End of the mandatory fields.*/
+  i2copmode_t     op_mode;       /**< @brief Specifies the I2C mode.        */
+  uint32_t        clock_speed;   /**< @brief Specifies the clock frequency.
+                                      @note Must be set to a value lower
+                                      than 400kHz.                          */
+} I2CConfig;
+
+/**
+ * @brief   Type of a structure representing an I2C driver.
+ */
+typedef struct I2CDriver I2CDriver;
+
+/**
+ * @brief   Structure representing an I2C driver.
+ */
+struct I2CDriver {
+  /**
+   * @brief   Driver state.
+   */
+  i2cstate_t                state;
+  /**
+   * @brief   Current configuration data.
+   */
+  const I2CConfig           *config;
+  /**
+   * @brief   Error flags.
+   */
+  i2cflags_t                errors;
+#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
+  /**
+   * @brief   Mutex protecting the bus.
+   */
+  mutex_t                   mutex;
+#endif /* I2C_USE_MUTUAL_EXCLUSION */
+#if defined(I2C_DRIVER_EXT_FIELDS)
+  I2C_DRIVER_EXT_FIELDS
+#endif
+  /* End of the mandatory fields.*/
+  /**
+   * @brief   Thread waiting for I/O completion.
+   */
+  thread_reference_t        thread;
+  /**
+   * @brief     Number of bytes in TX phase.
+   */
+  size_t                    txbytes;
+  /**
+   * @brief     Number of bytes in RX phase.
+   */
+  size_t                    rxbytes;
+  /**
+   * @brief     Pointer to the TX buffer location.
+   */
+  const uint8_t             *txbuf;
+  /**
+   * @brief     Pointer to the RX buffer location.
+   */
+  uint8_t                   *rxbuf;
+  /**
+   * @brief   Receive DMA stream.
+   */
+  sama_dma_channel_t       *dmarx;
+  /**
+   * @brief   Transmit DMA stream.
+   */
+  sama_dma_channel_t       *dmatx;
+  /**
+    * @brief   RX DMA mode bit mask.
+    */
+  uint32_t                 rxdmamode;
+  /**
+    * @brief   TX DMA mode bit mask.
+    */
+  uint32_t                 txdmamode;
+  /**
+   * @brief     Pointer to the TWIHSx registers block.
+   */
+  Twi                      *i2c;
+};
+
+/*===========================================================================*/
+/* Driver macros.                                                            */
+/*===========================================================================*/
+
+/**
+ * @brief   Get errors from I2C driver.
+ *
+ * @param[in] i2cp      pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
+
+/*===========================================================================*/
+/* External declarations.                                                    */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+#if SAMA_I2C_USE_TWIHS0
+extern I2CDriver I2CD0;
+#endif
+
+#if SAMA_I2C_USE_TWIHS1
+extern I2CDriver I2CD1;
+#endif
+
+#endif /* !defined(__DOXYGEN__) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void i2c_lld_init(void);
+  void i2c_lld_start(I2CDriver *i2cp);
+  void i2c_lld_stop(I2CDriver *i2cp);
+  msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+                                        const uint8_t *txbuf, size_t txbytes,
+                                        uint8_t *rxbuf, size_t rxbytes,
+                                        sysinterval_t timeout);
+  msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+                                       uint8_t *rxbuf, size_t rxbytes,
+                                       sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2C  */
+
+#endif /* HAL_I2C_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/LLD/MACv1/hal_mac_lld.c b/os/hal/ports/SAMA/LLD/MACv1/hal_mac_lld.c
index 862a7618c..86edb1877 100644
--- a/os/hal/ports/SAMA/LLD/MACv1/hal_mac_lld.c
+++ b/os/hal/ports/SAMA/LLD/MACv1/hal_mac_lld.c
@@ -33,8 +33,18 @@
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
 /*===========================================================================*/
+/*
+ * @brief    Buffer size.
+ */
 #define BUFFER_SIZE ((((SAMA_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4)
 
+/*
+ * @brief    NO CACHE attribute
+ */
+#if !defined(NO_CACHE)
+#define NO_CACHE                        __attribute__((section (".nocache")))
+#endif
+
 /* MII divider optimal value.*/
 #if (SAMA_GMAC0CLK <= 20000000)
 #define GMAC_CLK     GMAC_NCFGR_CLK_MCK_8
@@ -73,17 +83,28 @@ MACDriver ETHD0;
 
 static const uint8_t default_mac_address[] = {0x54, 0x54, 0x08, 0x34, 0x1f, 0x3a};
 
+/*
+ * In terms of AMBA AHB operation, the descriptors are read from memory using
+ * a single 32-bit AHB access. The descriptors should be aligned at 32-bit
+ * boundaries and the descriptors are written to using two individual non
+ * sequential accesses.
+ */
+
 /* Rx descriptor list */
-ALIGNED_VAR(8)
+NO_CACHE ALIGNED_VAR(4)
 static sama_eth_rx_descriptor_t __eth_rd[SAMA_MAC_RECEIVE_BUFFERS];
 
 /* Tx descriptor list */
-ALIGNED_VAR(8)
+NO_CACHE ALIGNED_VAR(4)
 static sama_eth_tx_descriptor_t __eth_td[SAMA_MAC_TRANSMIT_BUFFERS];
+NO_CACHE ALIGNED_VAR(4)
 static sama_eth_tx_descriptor_t __eth_td1[1];
+NO_CACHE ALIGNED_VAR(4)
 static sama_eth_tx_descriptor_t __eth_td2[1];
 
+NO_CACHE
 static uint32_t __eth_rb[SAMA_MAC_RECEIVE_BUFFERS][BUFFER_SIZE];
+NO_CACHE
 static uint32_t __eth_tb[SAMA_MAC_TRANSMIT_BUFFERS][BUFFER_SIZE];
 
 /*===========================================================================*/
diff --git a/os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.c b/os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.c
index 81f8d6cd0..dbf5c36a4 100644
--- a/os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.c
+++ b/os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.c
@@ -29,10 +29,36 @@
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
 /*===========================================================================*/
+#define __PIOA                                 ((Pio      *)0xFC038000U)
 
+#define EVENTS_NUMBER                          (4 * 32)
+
+/**
+ * @brief   PIOA interrupt priority level setting.
+ */
+#define SAMA_PIOA_IRQ_PRIORITY                 2
+
+/**
+ * @brief   PIOB interrupt priority level setting.
+ */
+#define SAMA_PIOB_IRQ_PRIORITY                 2
+
+/**
+ * @brief   PIOC interrupt priority level setting.
+ */
+#define SAMA_PIOC_IRQ_PRIORITY                 2
+
+/**
+ * @brief   PIOD interrupt priority level setting.
+ */
+#define SAMA_PIOD_IRQ_PRIORITY                 2
 /*===========================================================================*/
 /* Driver exported variables.                                                */
 /*===========================================================================*/
+/**
+ * @brief   Event records for the GPIO interrupts.
+ */
+palevent_t _pal_events[EVENTS_NUMBER];
 
 /*===========================================================================*/
 /* Driver local variables and types.                                         */
@@ -45,10 +71,167 @@
 /*===========================================================================*/
 /* Driver interrupt handlers.                                                */
 /*===========================================================================*/
+/**
+ * @brief   PIOA interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(SAMA_PIOA_HANDLER) {
+
+  OSAL_IRQ_PROLOGUE();
+
+  uint32_t sr, imr, is;
+  uint8_t i, j;
+
+  sr = pal_lld_read_status(PIOA);
+  imr = pal_lld_read_int_mask(PIOA);
+
+  is = sr & imr;
+  for (j = 0, i = 0; i < 32; i++, j++) {
+    if (!(is & (0x1 << j))) {
+      continue;
+    }
+#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+    if (_pal_events[i].cb != NULL) {
+      _pal_events[i].cb(&is);
+    }
+#endif
+  }
+  aicAckInt();
+  OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief   PIOB interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(SAMA_PIOB_HANDLER) {
+
+  OSAL_IRQ_PROLOGUE();
+
+  uint32_t sr, imr, is;
+  uint8_t i, j;
+
+  sr = pal_lld_read_status(PIOB);
+  imr = pal_lld_read_int_mask(PIOB);
+
+  is = sr & imr;
+  for (j = 0, i = 32; i < 64; i++, j++) {
+    if (!(is & (0x1 << j))) {
+      continue;
+    }
+#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+    if (_pal_events[i].cb != NULL) {
+      _pal_events[i].cb(&is);
+    }
+#endif
+  }
+  aicAckInt();
+  OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief   PIOC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(SAMA_PIOC_HANDLER) {
+
+  OSAL_IRQ_PROLOGUE();
+
+  uint32_t sr, imr, is;
+  uint8_t i, j;
+
+  sr = pal_lld_read_status(PIOC);
+  imr = pal_lld_read_int_mask(PIOC);
+
+  is = sr & imr;
+  for (j = 0, i = 64; i < 96; i++, j++) {
+    if (!(is & (0x1 << j))) {
+      continue;
+    }
+#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+    if (_pal_events[i].cb != NULL) {
+      _pal_events[i].cb(&is);
+    }
+#endif
+  }
+  aicAckInt();
+  OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief   PIOD interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(SAMA_PIOD_HANDLER) {
 
+  OSAL_IRQ_PROLOGUE();
+
+  uint32_t sr, imr, is;
+  uint8_t i, j;
+
+  sr = pal_lld_read_status(PIOD);
+  imr = pal_lld_read_int_mask(PIOD);
+
+  is = sr & imr;
+  for (j = 0, i = 96; i < 128; i++, j++) {
+    if (!(is & (0x1 << j))) {
+      continue;
+    }
+#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+    if (_pal_events[i].cb != NULL) {
+      _pal_events[i].cb(&is);
+    }
+#endif
+  }
+  aicAckInt();
+  OSAL_IRQ_EPILOGUE();
+}
 /*===========================================================================*/
 /* Driver exported functions.                                                */
 /*===========================================================================*/
+/**
+ * @brief   PAL driver initialization.
+ *
+ * @notapi
+ */
+void _pal_lld_init(void) {
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+  unsigned i;
+
+  for (i = 0; i < EVENTS_NUMBER; i++) {
+    _pal_init_event(i);
+  }
+
+  /*
+   * Clears status register
+   */
+  pal_lld_read_status(PIOA);
+  pal_lld_read_status(PIOB);
+  pal_lld_read_status(PIOC);
+  pal_lld_read_status(PIOD);
+
+  aicSetSourcePriority(ID_PIOA, SAMA_PIOA_IRQ_PRIORITY);
+  aicSetSourceHandler(ID_PIOA, SAMA_PIOA_HANDLER);
+  aicEnableInt(ID_PIOA);
+
+  aicSetSourcePriority(ID_PIOB, SAMA_PIOB_IRQ_PRIORITY);
+  aicSetSourceHandler(ID_PIOB, SAMA_PIOB_HANDLER);
+  aicEnableInt(ID_PIOB);
+
+  aicSetSourcePriority(ID_PIOC, SAMA_PIOC_IRQ_PRIORITY);
+  aicSetSourceHandler(ID_PIOC, SAMA_PIOC_HANDLER);
+  aicEnableInt(ID_PIOC);
+
+  aicSetSourcePriority(ID_PIOD, SAMA_PIOD_IRQ_PRIORITY);
+  aicSetSourceHandler(ID_PIOD, SAMA_PIOD_HANDLER);
+  aicEnableInt(ID_PIOD);
+#endif /* #if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) */
+}
 
 /**
  * @brief   Pads mode setup.
@@ -82,5 +265,123 @@ void _pal_lld_setgroupmode(ioportid_t port,
   port->CFGR = cfgr;
 }
 
+#if SAMA_HAL_IS_SECURE
+/**
+ * @brief   Configures debouncing time for pads.
+ *
+ * @param[in] db_time      debouncing time
+ *
+ * @api
+ */
+void pal_lld_cfg_debouncing_time(uint32_t db_time) {
+
+  /*
+   * Debouncing time configuration only in SECURE STATE
+   */
+  __PIOA->S_PIO_SCDR = db_time & 0x3FFF;
+}
+#endif
+
+/**
+ * @brief   Reads/Clears Interrupt Status Register.
+ *
+ * @param[in] port      port identifier
+ *
+ * @api
+ */
+uint32_t pal_lld_read_status(ioportid_t port) {
+  return port->ISR;
+}
+
+/**
+ * @brief   Reads Interrupt Mask Register.
+ *
+ * @param[in] port      port identifier
+ *
+ * @api
+ */
+uint32_t pal_lld_read_int_mask(ioportid_t port) {
+  return port->IMR;
+}
+
+/**
+ * @brief   Reads Configuration Register.
+ *
+ * @param[in] port      port identifier
+ *
+ * @api
+ */
+uint32_t pal_lld_read_cfgr(ioportid_t port) {
+  return port->CFGR;
+}
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+/**
+ * @brief   Pad event enable.
+ * @note    Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port      port identifier
+ * @param[in] pad       pad number within the port
+ * @param[in] mode      pad event mode
+ *
+ * @notapi
+ */
+void _pal_lld_enablepadevent(ioportid_t port,
+                             iopadid_t pad,
+                             ioeventmode_t mode) {
+
+  port->MSKR = pad;
+  port->CFGR |= mode;
+  port->IER = pad;
+}
+
+/**
+ * @brief   Returns a PAL event structure associated to a pad.
+ *
+ * @param[in] port      port identifier
+ * @param[in] pad       pad number within the port
+ *
+ * @notapi
+ */
+palevent_t* pal_lld_get_pad_event(ioportid_t port, iopadid_t pad) {
+
+  palevent_t* palevt = NULL;
+
+  if (port == PIOA) {
+    palevt = &_pal_events[pad];
+  }
+  else if (port == PIOB) {
+    palevt = &_pal_events[32 + pad];
+  }
+  else if (port == PIOC) {
+    palevt = &_pal_events[64 + pad];
+  }
+  else {
+    palevt = &_pal_events[96 + pad];
+  }
+
+  return palevt;
+}
+
+/**
+ * @brief   Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port      port identifier
+ * @param[in] pad       pad number within the port
+ *
+ * @notapi
+ */
+void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
+
+  port->IDR |= pad;
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT
+  /* Callback cleared and/or thread reset.*/
+  _pal_clear_event(pad);
+#endif
+}
+#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
+
 #endif /* HAL_USE_PAL */
 /** @} */
diff --git a/os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.h b/os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.h
index e2ede7c52..53386ba5b 100644
--- a/os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.h
+++ b/os/hal/ports/SAMA/LLD/PIOv1/hal_pal_lld.h
@@ -30,6 +30,9 @@
 /*===========================================================================*/
 /* Unsupported modes and specific modes                                      */
 /*===========================================================================*/
+/* Specifies palInit() without parameter, required until all platforms will
+   be updated to the new style.*/
+#define PAL_NEW_INIT
 
 #undef PAL_MODE_RESET
 #undef PAL_MODE_UNCONNECTED
@@ -102,7 +105,8 @@
                                        PAL_SAMA_IFSCEN_MASK |               \
                                        PAL_SAMA_OPD_MASK |                  \
                                        PAL_SAMA_SCHMITT_MASK |              \
-                                       PAL_SAMA_DRVSTR_MASK
+                                       PAL_SAMA_DRVSTR_MASK |               \
+                                       PAL_SAMA_EVTSEL_MASK
 
 #if SAMA_HAL_IS_SECURE
 #define PAL_SAMA_SECURE_MASK           (1U << 31U)
@@ -146,7 +150,7 @@
  */
 #define PAL_MODE_INPUT_PULLDOWN         (PAL_SAMA_DIR_INPUT |               \
                                          PAL_SAMA_SCHMITT |                 \
-                                         PAL_SAMA_PUEN_PULLDOWN)
+                                         PAL_SAMA_PDEN_PULLDOWN)
 
 /**
  * @brief   Analog input mode.
@@ -365,13 +369,12 @@ typedef uint32_t iopadid_t;
 /* Implementation, some of the following macros could be implemented as      */
 /* functions, if so please put them in pal_lld.c.                            */
 /*===========================================================================*/
-
 /**
- * @brief   PIO ports subsystem initialization.
+ * @brief   GPIO ports subsystem initialization.
  *
  * @notapi
  */
-#define pal_lld_init(config)
+#define pal_lld_init() _pal_lld_init()
 
 /**
  * @brief   Reads an I/O port.
@@ -497,7 +500,8 @@ typedef uint32_t iopadid_t;
  *
  * @notapi
  */
-#define pal_lld_enablepadevent(port, pad, mode)
+#define pal_lld_enablepadevent(port, pad, mode)                             \
+  _pal_lld_enablepadevent(port, pad, mode)
 
 /**
  * @brief   Pad event disable.
@@ -508,17 +512,8 @@ typedef uint32_t iopadid_t;
  *
  * @notapi
  */
-#define pal_lld_disablepadevent(port, pad)
-
-/**
- * @brief   Returns a PAL event structure associated to a pad.
- *
- * @param[in] port      port identifier
- * @param[in] pad       pad number within the port
- *
- * @notapi
- */
-#define pal_lld_get_pad_event(port, pad)
+#define pal_lld_disablepadevent(port, pad)                                  \
+  _pal_lld_disablepadevent(port, pad)
 
 /**
  * @brief   Returns a PAL event structure associated to a line.
@@ -527,14 +522,32 @@ typedef uint32_t iopadid_t;
  *
  * @notapi
  */
-#define pal_lld_get_line_event(line)
+#define pal_lld_get_line_event(line)                                        \
+  &_pal_events[PAL_PAD(line)]
+
+#if !defined(__DOXYGEN__)
+extern palevent_t _pal_events[4 * 32];
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
+   void _pal_lld_init(void);
    void _pal_lld_setgroupmode(ioportid_t port,
                               ioportmask_t mask,
                               iomode_t mode);
+   void _pal_lld_enablepadevent(ioportid_t port,
+                                iopadid_t pad,
+                                ioeventmode_t mode);
+   void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad);
+   palevent_t* pal_lld_get_pad_event(ioportid_t port, iopadid_t pad);
+   /* LLD only functions */
+#if SAMA_HAL_IS_SECURE
+   void pal_lld_cfg_debouncing_time(uint32_t db_time);
+#endif
+   uint32_t pal_lld_read_status(ioportid_t port);
+   uint32_t pal_lld_read_int_mask(ioportid_t port);
+   uint32_t pal_lld_read_cfgr(ioportid_t port);
 #ifdef __cplusplus
 }
 #endif
diff --git a/os/hal/ports/SAMA/LLD/RNGv1/driver.mk b/os/hal/ports/SAMA/LLD/RNGv1/driver.mk
new file mode 100644
index 000000000..163c48a70
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/RNGv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_TRNG TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/RNGv1
diff --git a/os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.c b/os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.c
new file mode 100644
index 000000000..6d8fde7d6
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.c
@@ -0,0 +1,175 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    hal_trng_lld.c
+ * @brief   STM32 TRNG subsystem low level driver source.
+ *
+ * @addtogroup TRNG
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/**
+ * @brief   TRNGD0 driver identifier.
+ */
+#if (SAMA_TRNG_USE_TRNG0 == TRUE) || defined(__DOXYGEN__)
+TRNGDriver TRNGD0;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types.                                         */
+/*===========================================================================*/
+
+static const TRNGConfig default_cfg = {0};
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+/**
+ * @brief   Low level TRNG driver initialization.
+ *
+ * @notapi
+ */
+void trng_lld_init(void) {
+
+#if SAMA_TRNG_USE_TRNG0 == TRUE
+
+#if SAMA_HAL_IS_SECURE
+  mtxConfigPeriphSecurity(MATRIX1, ID_TRNG, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+
+  /* Driver initialization.*/
+  trngObjectInit(&TRNGD0);
+  TRNGD0.trng = TRNG;
+#endif
+}
+
+/**
+ * @brief   Configures and activates the TRNG peripheral.
+ *
+ * @param[in] trngp      pointer to the @p TRNGDriver object
+ *
+ * @notapi
+ */
+void trng_lld_start(TRNGDriver *trngp) {
+
+  /* There is no real configuration but setting up a valid pointer anyway.*/
+  if (trngp->config == NULL) {
+    trngp->config = &default_cfg;
+  }
+
+  if (trngp->state == TRNG_STOP) {
+    /* Enables the peripheral.*/
+#if SAMA_TRNG_USE_TRNG0 == TRUE
+    if (&TRNGD0 == trngp) {
+      pmcEnableTRNG0();
+    }
+#endif
+  }
+  /* Configures the peripheral.*/
+  trngp->trng->TRNG_CR = TRNG_CR_ENABLE | TRNG_CR_KEY_PASSWD;
+}
+
+/**
+ * @brief   Deactivates the TRNG peripheral.
+ *
+ * @param[in] trngp      pointer to the @p TRNGDriver object
+ *
+ * @notapi
+ */
+void trng_lld_stop(TRNGDriver *trngp) {
+
+  if (trngp->state == TRNG_READY) {
+    /* Resets the peripheral.*/
+    trngp->trng->TRNG_CR = TRNG_CR_KEY_PASSWD;
+
+    /* Disables the peripheral.*/
+#if SAMA_TRNG_USE_TRNG0 == TRUE
+    if (&TRNGD0 == trngp) {
+      pmcDisableTRNG0();
+    }
+#endif
+  }
+}
+
+/**
+ * @brief   True random numbers generator.
+ * @note    The function is blocking and likely performs polled waiting
+ *          inside the low level implementation.
+ *
+ * @param[in] trngp             pointer to the @p TRNGDriver object
+ * @param[in] size              size of output buffer
+ * @param[out] out              output buffer
+ * @return                      The operation status.
+ * @retval false                if a random number has been generated.
+ * @retval true                 if an HW error occurred.
+ *
+ * @api
+ */
+bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out) {
+
+  while (true) {
+    uint32_t r, tmo;
+    size_t i;
+
+    /* Waiting for a random number in data register.*/
+    tmo = SAMA_DATA_FETCH_ATTEMPTS;
+    while ((tmo > 0) && ((trngp->trng->TRNG_ISR & TRNG_ISR_DATRDY) == 0)) {
+      tmo--;
+      if (tmo == 0) {
+        return true;
+      }
+    }
+
+    /* Getting the generated random number.*/
+    r = trngp->trng->TRNG_ODATA;
+
+    /* Writing in the output buffer.*/
+    for (i = 0; i < sizeof (uint32_t) / sizeof (uint8_t); i++) {
+      *out++ = (uint8_t)r;
+      r = r >> 8;
+      size--;
+      if (size == 0) {
+        return false;
+      }
+    }
+  }
+}
+
+#endif /* HAL_USE_TRNG == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.h b/os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.h
new file mode 100644
index 000000000..146635db4
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/RNGv1/hal_trng_lld.h
@@ -0,0 +1,113 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    hal_trng_lld.h
+ * @brief   SAMA TRNG subsystem low level driver header.
+ *
+ * @addtogroup TRNG
+ * @{
+ */
+
+#ifndef HAL_TRNG_LLD_H
+#define HAL_TRNG_LLD_H
+
+#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings.                                         */
+/*===========================================================================*/
+
+/**
+ * @name    SAMA configuration options
+ * @{
+ */
+/**
+ * @brief   TRNGD0 driver enable switch.
+ * @details If set to @p TRUE the support for TRNGD0 is included.
+ * @note    The default is @p FALSE.
+ */
+#if !defined(SAMA_TRNG_USE_TRNG0) || defined(__DOXYGEN__)
+#define SAMA_TRNG_USE_TRNG0                 FALSE
+#endif
+
+/**
+ * @brief   TRNGD0 data available timeout counter.
+ * @details Number of status register fetches before failing.
+ */
+#if !defined(SAMA_DATA_FETCH_ATTEMPTS) || defined(__DOXYGEN__)
+#define SAMA_DATA_FETCH_ATTEMPTS            1000
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks.                                       */
+/*===========================================================================*/
+
+#if !SAMA_TRNG_USE_TRNG0
+#error "TRNG driver activated but no RNG peripheral assigned"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros.                                                            */
+/*===========================================================================*/
+
+/**
+ * @brief   Low level fields of the TRNG configuration structure.
+ */
+#define trng_lld_config_fields                                              \
+  /* Dummy configuration, it is not needed.*/                               \
+  uint32_t                   dummy
+
+/**
+ * @brief   Low level fields of the TRNG driver structure.
+ */
+#define trng_lld_driver_fields                                              \
+  /* Pointer to the RNG registers block.*/                                  \
+  Trng                       *trng;
+
+/*===========================================================================*/
+/* External declarations.                                                    */
+/*===========================================================================*/
+
+#if (SAMA_TRNG_USE_TRNG0 == TRUE) && !defined(__DOXYGEN__)
+extern TRNGDriver TRNGD0;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void trng_lld_init(void);
+  void trng_lld_start(TRNGDriver *trngp);
+  void trng_lld_stop(TRNGDriver *trngp);
+  bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_TRNG == TRUE */
+
+#endif /* HAL_TRNG_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.c b/os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.c
index 174996b8e..691a3cc15 100644
--- a/os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.c
+++ b/os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.c
@@ -106,8 +106,6 @@ static void rtc_enter_init(void) {
   /* Stop RTC_TIMR and RTC_CALR */
   RTCD0.rtc->RTC_CR |= RTC_CR_UPDCAL;
   RTCD0.rtc->RTC_CR |= RTC_CR_UPDTIM;
-  while ((RTCD0.rtc->RTC_SR & RTC_SR_ACKUPD) == 0)
-    ;
 }
 
 /**
@@ -364,8 +362,7 @@ void rtc_lld_init(void) {
 
 /**
  * @brief   Set current time.
- * @note    Fractional part will be silently ignored. There is no possibility
- *          to set it on STM32 platform.
+ * @note    Fractional part will be silently ignored.
  * @note    The function can be called from any context.
  *
  * @param[in] rtcp      pointer to RTC driver structure
@@ -384,15 +381,35 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) {
   /* Disable write protection */
 //  syscDisableWP();
 
+  /* Synchronization on a second periodic event polling the RTC_SR.SEC status bit */
+  wait: while ((rtcp->rtc->RTC_SR & RTC_SR_SEC) == 0);
+
   /* Entering a reentrant critical zone.*/
   sts = osalSysGetStatusAndLockX();
 
-  /* Synchronization on a second periodic event polling the RTC_SR.SEC status bit */
-  while ((rtcp->rtc->RTC_SR & RTC_SR_SEC) == 0)
-    ;
+  if (!(rtcp->rtc->RTC_SR & RTC_SR_SEC)) {
+    /* Leaving a reentrant critical zone.*/
+    osalSysRestoreStatusX(sts);
+    goto wait;
+  }
+
   /* Writing the registers.*/
   rtc_enter_init();
 
+  /* Leaving a reentrant critical zone.*/
+  osalSysRestoreStatusX(sts);
+
+  while ((RTCD0.rtc->RTC_SR & RTC_SR_ACKUPD) == 0);
+
+  /* Entering a reentrant critical zone.*/
+  sts = osalSysGetStatusAndLockX();
+
+  if (!(rtcp->rtc->RTC_SR & RTC_SR_SEC)) {
+    /* Leaving a reentrant critical zone.*/
+    osalSysRestoreStatusX(sts);
+    goto wait;
+  }
+
   /* Clear ACKUPD status flag */
   rtcp->rtc->RTC_SCCR = RTC_SCCR_ACKCLR;
 
diff --git a/os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.h b/os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.h
index a5d4b8918..7b5fb3cd2 100644
--- a/os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.h
+++ b/os/hal/ports/SAMA/LLD/RTCv1/hal_rtc_lld.h
@@ -79,17 +79,6 @@
 /* Driver data structures and types.                                         */
 /*===========================================================================*/
 
-/**
- * @brief   FileStream specific methods.
- */
-#define _rtc_driver_methods                                                 \
-  _file_stream_methods
-
-/**
- * @brief   Type of an RTC alarm number.
- */
-typedef uint32_t rtcalarm_t;
-
 /**
   * @brief   Type of an RTC event.
   */
@@ -106,7 +95,7 @@ typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event);
 /**
  * @brief   Type of a structure representing an RTC alarm time stamp.
  */
-typedef struct {
+typedef struct hal_rtc_alarm {
   /**
    * @brief   Type of an alarm as encoded in RTC registers.
    */
@@ -114,37 +103,14 @@ typedef struct {
   uint32_t                  calralrm;
 } RTCAlarm;
 
-#if RTC_HAS_STORAGE || defined(__DOXYGEN__)
 /**
- * @extends FileStream
- *
- * @brief   @p RTCDriver virtual methods table.
+ * @brief   Implementation-specific @p RTCDriver fields.
  */
-struct RTCDriverVMT {
-  _rtc_driver_methods
-};
-#endif
-
-/**
- * @brief   Structure representing an RTC driver.
- */
-struct RTCDriver {
-#if RTC_HAS_STORAGE || defined(__DOXYGEN__)
-  /**
-   * @brief Virtual Methods Table.
-   */
-  const struct RTCDriverVMT *vmt;
-#endif
-  /* End of the mandatory fields.*/
-  /**
-   * @brief   Pointer to the RTC registers block.
-   */
-  Rtc               *rtc;
-  /**
-   * @brief   Callback pointer.
-   */
-  rtccb_t           callback;
-};
+#define rtc_lld_driver_fields                                               \
+  /* Pointer to the RTC registers block.*/                                  \
+  Rtc               *rtc;                                                   \
+  /* Callback pointer.*/                                                    \
+  rtccb_t           callback
 
 /*===========================================================================*/
 /* Driver macros.                                                            */
@@ -182,13 +148,6 @@ struct RTCDriver {
 /* External declarations.                                                    */
 /*===========================================================================*/
 
-#if !defined(__DOXYGEN__)
-extern RTCDriver RTCD0;
-#if RTC_HAS_STORAGE
-extern struct RTCDriverVMT _rtc_lld_vmt;
-#endif
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c
index a337ee6d7..d019da05a 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c
@@ -1,7 +1,7 @@
 #include <string.h>
 #include "hal.h"
 
-#if (HAL_USE_SDMMC == TRUE)
+#if (SAMA_USE_SDMMC == TRUE)
 
 #include "sama_sdmmc_lld.h"
 #include "ch_sdmmc_device.h"
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h
index 29f1119da..2370d36a9 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h
@@ -99,7 +99,7 @@ typedef struct _SdmmcCommand {
 	/** Command index */
 	uint8_t bCmd;
 	/** Command return status */
-	uint8_t bStatus;
+	volatile uint8_t bStatus;
 } sSdmmcCommand;
 
 
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c
index 4323b5876..dbfa8bd7a 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c
@@ -1,7 +1,7 @@
 #include <string.h>
 #include "hal.h"
 
-#if (HAL_USE_SDMMC == TRUE)
+#if (SAMA_USE_SDMMC == TRUE)
 
 #include "sama_sdmmc_lld.h"
 #include "ch_sdmmc_device.h"
@@ -145,7 +145,7 @@ uint8_t Cmd1(SdmmcDriver *drv, bool * hc)
 	/* Tell the MMC device which voltage the host supplies to the VDD line
 	 * (MMC card) or VCC line (e.MMC device).
 	 * TODO get this board-specific value from platform code. On the
-	 * SAMA5D2-XULT board, VDD is 3.3V � 1%. */
+	 * SAMA5D2-XULT board, VDD is 3.3V � 1%. */
 	arg |= SD_OCR_VDD_32_33 | SD_OCR_VDD_33_34;
 
 	/* Fill command */
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c
index 5861508b2..7bdd136e0 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c
@@ -1,7 +1,7 @@
 #include <string.h>
 #include "hal.h"
 
-#if (HAL_USE_SDMMC == TRUE)
+#if (SAMA_USE_SDMMC == TRUE)
 
 #include "sama_sdmmc_lld.h"
 #include "ch_sdmmc_device.h"
@@ -148,29 +148,7 @@ uint8_t  sdmmc_device_lowlevelcfg(SdmmcDriver *driver)
 		break;
 	}
 
-
-	if (res) {
-		//check res
-		res = IS_CACHE_ALIGNED(driver->config->data_buf);
-		TRACE_DEBUG_2("check data buf %d %08x\r\n", res, driver->config->data_buf);
-		res &= IS_CACHE_ALIGNED(driver->config->data_buf_size);
-		TRACE_DEBUG_2("check data_buf_size %d %08x\r\n", res,
-				driver->config->data_buf_size);
-		res &= IS_CACHE_ALIGNED(driver->card.EXT);
-		TRACE_DEBUG_2("check libExt %d %08x\r\n", res, driver->card.EXT);
-
-
-		if (!res) {
-			TRACE_WARNING("WARNING: buffers are not aligned on data cache lines. Please fix this before enabling DMA.\n\r");
-			driver->use_polling = true;
-		} else {
-			driver->use_polling = false;
-		}
-
-	}
-
 	return res;
-
 }
 
 bool sdmmc_device_initialize(SdmmcDriver *driver)
@@ -890,8 +868,12 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
  			 * anticipated reading had to be supported, the data
  			 * cache lines would need to be invalidated twice: both
  			 * now and upon Transfer Complete. */
- 			cacheInvalidateRegion(driver->cmd.pData, len);
-
+      if(((uint32_t) driver->cmd.pData & (L1_CACHE_BYTES - 1)) || (len & (L1_CACHE_BYTES - 1))) {
+        cacheCleanInvalidateRegion(driver->cmd.pData, len);
+      }
+      else {
+        cacheInvalidateRegion(driver->cmd.pData, len);
+      }
  		}
  	}
 
@@ -1310,7 +1292,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
 
  	do {
 
- 		now = chVTTimeElapsedSinceX(time);
+ 		now =  chVTGetSystemTimeX(); /* chVTTimeElapsedSinceX(time) */
 
  		if (now >= end) {
  			f = 1;
@@ -1328,18 +1310,18 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
  	}
  }
 
- void sdmmc_device_checkTimeCount(SdmmcDriver *driver)
- {
- 	if (driver->timeout_elapsed != -1) {
+void sdmmc_device_checkTimeCount(SdmmcDriver *driver)
+{
+  if (driver->timeout_elapsed != -1) {
 
- 		driver->timeout_elapsed = 0;
- 				 driver->now = chVTTimeElapsedSinceX( driver->time);
- 					 if (driver->now >= driver->timeout_ticks ) {
- 						 driver->timeout_elapsed = 1;
- 					 }
+    driver->timeout_elapsed = 0;
+    driver->now = chVTTimeElapsedSinceX(driver->time);
+    if (driver->now >= driver->timeout_ticks ) {
+      driver->timeout_elapsed = 1;
+    }
 
- 	}
- }
+  }
+}
 
  static void calibrate_zout(Sdmmc * regs)
  {
@@ -1575,12 +1557,6 @@ static uint8_t sdmmc_build_dma_table( SdmmcDriver *driver )
 		    line[1], line[0] & SDMMC_DMA0DL_ATTR_END ? '.' : ' ');
 #endif
 	}
-	/* Clean the underlying cache lines, to ensure the DMA gets our table
-	 * when it reads from RAM.
-	 * CPU access to the table is write-only, peripheral/DMA access is read-
-	 * only, hence there is no need to invalidate. */
-	cacheCleanRegion(driver->config->dma_table, (uint32_t)line - (uint32_t)driver->config->dma_table);
-
 	return rc;
 }
 
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_macros.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_macros.h
index 52f82fd03..c973d1e4a 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_macros.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_macros.h
@@ -2,12 +2,21 @@
 #define CH_SDMMC_MACROS_H_
 
 
-
+#if !defined(CACHE_ALIGNED)
 #define CACHE_ALIGNED  __attribute__((aligned(L1_CACHE_BYTES)))
+#endif
 
+/*
+ * @brief    NO CACHE attribute
+ */
+#if !defined(NO_CACHE)
+#define NO_CACHE                      __attribute__((section (".nocache")))
+#endif
 
 #define IS_CACHE_ALIGNED(x) ((((uint32_t)(x)) & (L1_CACHE_BYTES - 1)) == 0)
+#if !defined(ROUND_INT_DIV)
 #define ROUND_INT_DIV(n,d) (((n) + ((d)-1)) / (d))
+#endif
 #define ROUND_UP_MULT(x,m) (((x) + ((m)-1)) & ~((m)-1))
 #define CEIL_INT_DIV(n,d) (((n) + (d) - 1) / (d))
 #define ABS_DIFF(a,b) ((a) < (b) ? (b) - (a) : (a) - (b))
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c
index 5ddbdaed9..7720b4ba3 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c
@@ -1,7 +1,7 @@
 #include <string.h>
 #include "hal.h"
 
-#if (HAL_USE_SDMMC == TRUE)
+#if (SAMA_USE_SDMMC == TRUE)
 
 #include "sama_sdmmc_lld.h"
 #include "ch_sdmmc_device.h"
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h
index adbd63a41..8c71753f3 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h
@@ -20,7 +20,24 @@ typedef enum
 #define CAPS0_MASK (SDMMC_CA0R_V33VSUP | SDMMC_CA0R_V30VSUP | \
                     SDMMC_CA0R_V18VSUP | SDMMC_CA0R_SLTYPE_Msk | \
                     SDMMC_CA0R_ED8SUP)
+/* SOM1 */
+#if defined(BOARD_ATSAM5D27_SOM1)
+#define BOARD_SDMMC0_CAPS0 (SDMMC_CA0R_V33VSUP | \
+                            SDMMC_CA0R_V18VSUP | \
+                            SDMMC_CA0R_SLTYPE_REMOVABLECARD | \
+                            SDMMC_CA0R_ED8SUP)
+
+#define BOARD_SDMMC1_CAPS0 (SDMMC_CA0R_V33VSUP | \
+                            SDMMC_CA0R_SLTYPE_REMOVABLECARD)
+#elif defined(BOARD_ATSAM5D2_XULT)
+#define BOARD_SDMMC0_CAPS0 (SDMMC_CA0R_V33VSUP | \
+                            SDMMC_CA0R_V18VSUP | \
+                            SDMMC_CA0R_SLTYPE_EMBEDDED | \
+                            SDMMC_CA0R_ED8SUP)
 
+#define BOARD_SDMMC1_CAPS0 (SDMMC_CA0R_V33VSUP | \
+                            SDMMC_CA0R_SLTYPE_REMOVABLECARD)
+#else
 #define BOARD_SDMMC0_CAPS0 (SDMMC_CA0R_V33VSUP | \
                             SDMMC_CA0R_V18VSUP | \
                             SDMMC_CA0R_SLTYPE_EMBEDDED | \
@@ -28,5 +45,6 @@ typedef enum
 
 #define BOARD_SDMMC1_CAPS0 (SDMMC_CA0R_V33VSUP | \
                             SDMMC_CA0R_SLTYPE_REMOVABLECARD)
+#endif
 
 #endif /* CH_SDMMC_SAMA5D2_H_ */
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c
index ed2286bbc..d1e0f4532 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c
@@ -1,7 +1,7 @@
 #include <string.h>
 #include "hal.h"
 
-#if (HAL_USE_SDMMC == TRUE)
+#if (SAMA_USE_SDMMC == TRUE)
 #include "sama_sdmmc_lld.h"
 #include "ch_sdmmc_device.h"
 #include "ch_sdmmc_cmds.h"
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sdio.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sdio.c
index c9916620a..a7cd77a15 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sdio.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sdio.c
@@ -1,6 +1,6 @@
 #include "hal.h"
 
-#if (HAL_USE_SDMMC == TRUE)
+#if (SAMA_USE_SDMMC == TRUE)
 
 #include "sama_sdmmc_lld.h"
 #include "ch_sdmmc_device.h"
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk b/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk
index 32695db51..49c64f5fc 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk
@@ -1,3 +1,12 @@
+# Configuration files directory
+ifeq ($(CONFDIR),)
+  CONFDIR = .
+endif
+
+MCUCONF := $(strip $(shell cat $(CONFDIR)/mcuconf.h | egrep -e "\#define"))
+
+ifneq ($(findstring SAMA_USE_SDMMC TRUE,$(MCUCONF)),)
+
 PLATFORMSRC +=	$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c	\
 				$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c	\
 				$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sdio.c	\
@@ -8,3 +17,4 @@ PLATFORMSRC +=	$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c	\
 					
 PLATFORMINC +=  $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1
 
+endif
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c
index 8ea88a347..725d52415 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c
@@ -25,7 +25,7 @@
 #include "hal.h"
 #include "ccportab.h"
 
-#if (HAL_USE_SDMMC == TRUE) || defined(__DOXYGEN__)
+#if (SAMA_USE_SDMMC == TRUE) || defined(__DOXYGEN__)
 #include <string.h>
 #include "sama_sdmmc_lld.h"
 #include "ch_sdmmc_device.h"
@@ -314,6 +314,6 @@ bool CC_WEAK sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp)
 	return false;
 }
 
-#endif /* HAL_USE_SDMMC == TRUE */
+#endif /* SAMA_USE_SDMMC == TRUE */
 
 /** @} */
diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h
index a340f7786..1526f7ccc 100644
--- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h
+++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h
@@ -25,7 +25,7 @@
 #ifndef SAMA_SDMMC_LLD_H
 #define SAMA_SDMMC_LLD_H
 
-#if (HAL_USE_SDMMC == TRUE) || defined(__DOXYGEN__)
+#if (SAMA_USE_SDMMC == TRUE) || defined(__DOXYGEN__)
 
 #include "ch_sdmmc.h"
 
@@ -76,8 +76,6 @@ typedef struct {
 	sdmmcslots_t slot_id;
 
 	uint8_t * bp;
-	uint8_t * data_buf;
-	uint32_t 	data_buf_size;
 
 	uint32_t * dma_table;
 	uint32_t   dma_table_size;
@@ -87,7 +85,7 @@ typedef struct {
 
 struct SamaSDMMCDriver
 {
-	sdmmcstate_t                 		state;
+	volatile sdmmcstate_t        		state;
 	const SamaSDMMCConfig            *config;
 
 	Sdmmc * regs;                 /* set of SDMMC hardware registers */
@@ -160,7 +158,7 @@ bool sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp)  ;
 }
 #endif
 
-#endif /* HAL_USE_SDMMC == TRUE */
+#endif /* SAMA_USE_SDMMC == TRUE */
 
 #endif /* SAMA_SDMMC_LLD_H */
 
diff --git a/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c b/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c
index ccacf5e70..95625ca07 100644
--- a/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c
+++ b/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.c
@@ -56,7 +56,6 @@
   spip->SPI_WPMR = SPI_WPMR_WPKEY_PASSWD;                                    \
 }
 
-
 /*===========================================================================*/
 /* Driver exported variables.                                                */
 /*===========================================================================*/
@@ -114,8 +113,8 @@ SPIDriver FSPID4;
 /* Driver local variables and types.                                         */
 /*===========================================================================*/
 
-static const uint8_t dummytx = 0xFFU;
-static uint8_t dummyrx;
+static const CACHE_ALIGNED uint8_t dummytx = 0xFFU;
+CACHE_ALIGNED static uint8_t dummyrx;
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
@@ -142,6 +141,13 @@ static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
   dmaChannelDisable(spip->dmatx);
   dmaChannelDisable(spip->dmarx);
 
+#if (SAMA_SPI_CACHE_USER_MANAGED == FALSE)
+  /* D-Cache is enabled */
+  /* No operation for dummyrx */
+  if ((uint32_t) spip->rxbuf != (uint32_t) &dummyrx)
+    cacheInvalidateRegion(spip->rxbuf, spip->rxbytes);
+#endif
+
   /* Portable SPI ISR code defined in the high level driver, note, it is
      a macro.*/
   _spi_isr_code(spip);
@@ -156,7 +162,6 @@ static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
 static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) {
 
   /* DMA errors handling.*/
-
 #if defined(SAMA_SPI_DMA_ERROR_HOOK)
   (void)spip;
   if ((flags & (XDMAC_CIS_WBEIS | XDMAC_CIS_ROIS)) != 0) {
@@ -189,6 +194,7 @@ void spi_lld_init(void) {
   /* Driver initialization.*/
   spiObjectInit(&SPID0);
   SPID0.spi       = SPI0;
+  SPID0.flexcom   = NULL;
   SPID0.dmarx     = NULL;
   SPID0.dmatx     = NULL;
   SPID0.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
@@ -222,6 +228,7 @@ void spi_lld_init(void) {
   /* Driver initialization.*/
   spiObjectInit(&SPID1);
   SPID1.spi       = SPI1;
+  SPID1.flexcom   = NULL;
   SPID1.dmarx     = NULL;
   SPID1.dmatx     = NULL;
   SPID1.rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
@@ -443,6 +450,15 @@ void spi_lld_start(SPIDriver *spip) {
                                        (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
                                        (void *)spip);
       osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
+
+#if SAMA_SPI0_USE_GCLK
+#if SAMA_SPI0_GCLK_DIV > 256
+    #error "SPI0 GCLK divider out of range"
+#endif
+      pmcConfigGclk(ID_SPI0, SAMA_SPI0_GCLK_SOURCE, SAMA_SPI0_GCLK_DIV);
+      pmcEnableGclk(ID_SPI0);
+#endif /* SAMA_SPI0_USE_GCLK */
+
     /* Enable SPI0 clock */
       pmcEnableSPI0();
     }
@@ -458,6 +474,15 @@ void spi_lld_start(SPIDriver *spip) {
                                        (sama_dmaisr_t)spi_lld_serve_tx_interrupt,
                                        (void *)spip);
       osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
+
+#if SAMA_SPI1_USE_GCLK
+#if SAMA_SPI1_GCLK_DIV > 256
+    #error "SPI1 GCLK divider out of range"
+#endif
+      pmcConfigGclk(ID_SPI1, SAMA_SPI1_GCLK_SOURCE, SAMA_SPI1_GCLK_DIV);
+      pmcEnableGclk(ID_SPI1);
+#endif /* SAMA_SPI1_USE_GCLK */
+
     /* Enable SPI1 clock */
       pmcEnableSPI1();
     }
@@ -475,6 +500,15 @@ void spi_lld_start(SPIDriver *spip) {
       osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
     /* Enabling SPI on FLEXCOM */
       spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
+
+#if SAMA_FSPI0_USE_GCLK
+#if SAMA_FSPI0_GCLK_DIV > 256
+    #error "FSPI0 GCLK divider out of range"
+#endif
+      pmcConfigGclk(ID_FLEXCOM0, SAMA_FSPI0_GCLK_SOURCE, SAMA_FSPI0_GCLK_DIV);
+      pmcEnableGclk(ID_FLEXCOM0);
+#endif /* SAMA_FSPI0_USE_GCLK */
+
     /* Enable FLEXCOM0 clock */
       pmcEnableFLEXCOM0();
     }
@@ -492,6 +526,15 @@ void spi_lld_start(SPIDriver *spip) {
       osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
     /* Enabling SPI on FLEXCOM */
       spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
+
+#if SAMA_FSPI1_USE_GCLK
+#if SAMA_FSPI1_GCLK_DIV > 256
+    #error "FSPI1 GCLK divider out of range"
+#endif
+      pmcConfigGclk(ID_FLEXCOM1, SAMA_FSPI1_GCLK_SOURCE, SAMA_FSPI1_GCLK_DIV);
+      pmcEnableGclk(ID_FLEXCOM1);
+#endif /* SAMA_FSPI1_USE_GCLK */
+
     /* Enable FLEXCOM1 clock */
       pmcEnableFLEXCOM1();
     }
@@ -509,6 +552,15 @@ void spi_lld_start(SPIDriver *spip) {
       osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
     /* Enabling SPI on FLEXCOM */
       spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
+
+#if SAMA_FSPI2_USE_GCLK
+#if SAMA_FSPI2_GCLK_DIV > 256
+    #error "FSPI2 GCLK divider out of range"
+#endif
+      pmcConfigGclk(ID_FLEXCOM2, SAMA_FSPI2_GCLK_SOURCE, SAMA_FSPI2_GCLK_DIV);
+      pmcEnableGclk(ID_FLEXCOM2);
+#endif /* SAMA_FSPI2_USE_GCLK */
+
     /* Enable FLEXCOM2 clock */
       pmcEnableFLEXCOM2();
     }
@@ -526,6 +578,15 @@ void spi_lld_start(SPIDriver *spip) {
       osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
     /* Enabling SPI on FLEXCOM */
       spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
+
+#if SAMA_FSPI3_USE_GCLK
+#if SAMA_FSPI3_GCLK_DIV > 256
+    #error "FSPI3 GCLK divider out of range"
+#endif
+      pmcConfigGclk(ID_FLEXCOM3, SAMA_FSPI3_GCLK_SOURCE, SAMA_FSPI3_GCLK_DIV);
+      pmcEnableGclk(ID_FLEXCOM3);
+#endif /* SAMA_FSPI3_USE_GCLK */
+
     /* Enable FLEXCOM3 clock */
       pmcEnableFLEXCOM3();
     }
@@ -543,7 +604,16 @@ void spi_lld_start(SPIDriver *spip) {
       osalDbgAssert(spip->dmatx != NULL, "no channel allocated");
     /* Enabling SPI on FLEXCOM */
       spip->flexcom->FLEX_MR = FLEX_MR_OPMODE_SPI;
-    /* Enable FLEXCOM4 clock */
+
+#if SAMA_FSPI4_USE_GCLK
+#if SAMA_FSPI4_GCLK_DIV > 256
+    #error "FSPI4 GCLK divider out of range"
+#endif
+      pmcConfigGclk(ID_FLEXCOM4, SAMA_FSPI4_GCLK_SOURCE, SAMA_FSPI4_GCLK_DIV);
+      pmcEnableGclk(ID_FLEXCOM4);
+#endif /* SAMA_FSPI4_USE_GCLK */
+
+      /* Enable FLEXCOM4 clock */
       pmcEnableFLEXCOM4();
     }
 #endif /* SAMA_SPI_USE_FLEXCOM4 */
@@ -605,20 +675,32 @@ void spi_lld_stop(SPIDriver *spip) {
     if (&SPID0 == spip)
     /* Disable SPI0 clock */
       pmcDisableSPI0();
+#if SAMA_SPI0_USE_GCLK
+      pmcDisableGclk(ID_SPI0);
+#endif /* SAMA_SPI0_USE_GCLK */
+
+#endif /* SAMA_SPI_USE_SPI0 */
 
-#endif /* SAMA_SPI_USE_SPI1 */
 #if SAMA_SPI_USE_SPI1
     if (&SPID1 == spip)
     /* Disable SPI1 clock */
       pmcDisableSPI1();
 
-#endif /* SAMA_SPI_USE_FLEXCOM0 */
+#if SAMA_SPI1_USE_GCLK
+      pmcDisableGclk(ID_SPI1);
+#endif /* SAMA_SPI1_USE_GCLK */
+
+#endif /* SAMA_SPI_USE_SPI1 */
 
 #if SAMA_SPI_USE_FLEXCOM0
     if (&FSPID0 == spip)
     /* Disable FLEXCOM0 clock */
       pmcDisableFLEXCOM0();
 
+#if SAMA_FSPI0_USE_GCLK
+      pmcDisableGclk(ID_FLEXCOM0);
+#endif /* SAMA_FSPI0_USE_GCLK */
+
 #endif /* SAMA_SPI_USE_FLEXCOM0 */
 
 #if SAMA_SPI_USE_FLEXCOM1
@@ -626,6 +708,10 @@ void spi_lld_stop(SPIDriver *spip) {
     /* Disable FLEXCOM1 clock */
       pmcDisableFLEXCOM1();
 
+#if SAMA_FSPI1_USE_GCLK
+      pmcDisableGclk(ID_FLEXCOM1);
+#endif /* SAMA_FSPI1_USE_GCLK */
+
 #endif /* SAMA_SPI_USE_FLEXCOM1 */
 
 #if SAMA_SPI_USE_FLEXCOM2
@@ -633,6 +719,10 @@ void spi_lld_stop(SPIDriver *spip) {
     /* Disable FLEXCOM2 clock */
       pmcDisableFLEXCOM2();
 
+#if SAMA_FSPI2_USE_GCLK
+      pmcDisableGclk(ID_FLEXCOM2);
+#endif /* SAMA_FSPI2_USE_GCLK */
+
 #endif /* SAMA_SPI_USE_FLEXCOM2 */
 
 #if SAMA_SPI_USE_FLEXCOM3
@@ -640,6 +730,10 @@ void spi_lld_stop(SPIDriver *spip) {
     /* Disable FLEXCOM3 clock */
       pmcDisableFLEXCOM3();
 
+#if SAMA_FSPI3_USE_GCLK
+      pmcDisableGclk(ID_FLEXCOM3);
+#endif /* SAMA_FSPI3_USE_GCLK */
+
 #endif /* SAMA_SPI_USE_FLEXCOM3 */
 
 #if SAMA_SPI_USE_FLEXCOM4
@@ -647,8 +741,16 @@ void spi_lld_stop(SPIDriver *spip) {
     /* Disable FLEXCOM4 clock */
       pmcDisableFLEXCOM4();
 
+#if SAMA_FSPI4_USE_GCLK
+      pmcDisableGclk(ID_FLEXCOM4);
+#endif /* SAMA_FSPI4_USE_GCLK */
+
 #endif /* SAMA_SPI_USE_FLEXCOM4 */
   }
+
+  spip->txbuf = NULL;
+  spip->rxbuf = NULL;
+  spip->rxbytes = 0;
 }
 
 #if (SPI_SELECT_MODE == (SPI_SELECT_MODE_LLD || SPI_SELECT_MODE_PAD ||        \
@@ -695,12 +797,35 @@ void spi_lld_unselect(SPIDriver *spip) {
 void spi_lld_exchange(SPIDriver *spip, size_t n,
                       const void *txbuf, void *rxbuf) {
 
+  spip->txbuf = txbuf;
+  spip->rxbuf = rxbuf;
+  spip->rxbytes = n;
+
+#if (SAMA_SPI_CACHE_USER_MANAGED == FALSE)
+
+  osalDbgAssert(!((uint32_t) txbuf & (L1_CACHE_BYTES - 1)), "txbuf address not cache aligned");
+  osalDbgAssert(!((uint32_t) rxbuf & (L1_CACHE_BYTES - 1)), "rxbuf address not cache aligned");
+
+  /*
+   * If size is not multiple of cache line, clean cache region is required.
+   */
+  if (n & (L1_CACHE_BYTES - 1)) {
+    cacheCleanRegion((uint8_t *) rxbuf, n);
+  }
+  /* Cache is enabled */
+  cacheCleanRegion((uint8_t *) txbuf, n);
+#endif /* SAMA_SPI_CACHE_USER_MANAGED */
+
   /* Writing channel */
+  /* Change mode to incremented address for dummytx */
+  dmaChannelSetMode(spip->dmatx, spip->txdmamode | XDMAC_CC_SAM_INCREMENTED_AM);
   dmaChannelSetSource(spip->dmatx, txbuf);
   dmaChannelSetDestination(spip->dmatx, &spip->spi->SPI_TDR);
   dmaChannelSetTransactionSize(spip->dmatx, n);
 
   /* Reading channel */
+  /* Change mode to incremented address */
+  dmaChannelSetMode(spip->dmarx, spip->rxdmamode | XDMAC_CC_DAM_INCREMENTED_AM);
   dmaChannelSetSource(spip->dmarx, &spip->spi->SPI_RDR);
   dmaChannelSetDestination(spip->dmarx, rxbuf);
   dmaChannelSetTransactionSize(spip->dmarx, n);
@@ -724,17 +849,37 @@ void spi_lld_exchange(SPIDriver *spip, size_t n,
  */
 void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
 
+  spip->txbuf = txbuf;
+  spip->rxbuf = &dummyrx;
+  spip->rxbytes = n;
+
+#if (SAMA_SPI_CACHE_USER_MANAGED == FALSE)
+
+  osalDbgAssert(!((uint32_t) txbuf & (L1_CACHE_BYTES - 1)), "address not cache aligned");
+
+  /* Cache is enabled */
+  cacheCleanRegion((uint8_t *) txbuf, n);
+#endif /* SAMA_SPI_CACHE_USER_MANAGED */
+
   /* Writing channel */
+
+  /* Change mode to incremented address for dummytx */
+  dmaChannelSetMode(spip->dmatx, spip->txdmamode | XDMAC_CC_SAM_INCREMENTED_AM);
+
   dmaChannelSetSource(spip->dmatx, txbuf);
   dmaChannelSetDestination(spip->dmatx, &spip->spi->SPI_TDR);
   dmaChannelSetTransactionSize(spip->dmatx, n);
 
   /* Reading channel */
+
+  /* Change mode from incremented to fixed address for dummyrx */
+  dmaChannelSetMode(spip->dmarx, spip->rxdmamode & ~XDMAC_CC_DAM_INCREMENTED_AM);
+
   dmaChannelSetSource(spip->dmarx, &spip->spi->SPI_RDR);
   dmaChannelSetDestination(spip->dmarx, &dummyrx);
   dmaChannelSetTransactionSize(spip->dmarx, n);
-  /* Enable write protection.  */
 
+  /* Enable channel.  */
   dmaChannelEnable(spip->dmarx);
   dmaChannelEnable(spip->dmatx);
 
@@ -759,12 +904,33 @@ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
  */
 void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
 
+  spip->rxbuf = rxbuf;
+  spip->rxbytes = n;
+
+#if (SAMA_SPI_CACHE_USER_MANAGED == FALSE)
+
+  osalDbgAssert(!((uint32_t) rxbuf & (L1_CACHE_BYTES - 1)), "address not cache aligned");
+
+  /*
+   * If size is not multiple of cache line, clean cache region is required.
+   */
+  if (n & (L1_CACHE_BYTES - 1)) {
+    cacheCleanRegion((uint8_t *) rxbuf, n);
+  }
+#endif /* SAMA_SPI_CACHE_USER_MANAGED */
+
   /* Writing channel */
+  /* Change mode from incremented to fixed address for dummytx */
+  dmaChannelSetMode(spip->dmatx, spip->txdmamode & ~XDMAC_CC_SAM_INCREMENTED_AM);
+
   dmaChannelSetSource(spip->dmatx, &dummytx);
   dmaChannelSetDestination(spip->dmatx, &spip->spi->SPI_TDR);
   dmaChannelSetTransactionSize(spip->dmatx, n);
 
   /* Reading channel */
+  /* Change mode to incremented address */
+  dmaChannelSetMode(spip->dmarx, spip->rxdmamode | XDMAC_CC_DAM_INCREMENTED_AM);
+
   dmaChannelSetSource(spip->dmarx, &spip->spi->SPI_RDR);
   dmaChannelSetDestination(spip->dmarx, rxbuf);
   dmaChannelSetTransactionSize(spip->dmarx, n);
@@ -773,6 +939,29 @@ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
   dmaChannelEnable(spip->dmatx);
 }
 
+/**
+ * @brief   Exchanges one frame using a polled wait.
+ * @details This synchronous function exchanges one frame using a polled
+ *          synchronization method. This function is useful when exchanging
+ *          small amount of data on high speed channels, usually in this
+ *          situation is much more efficient just wait for completion using
+ *          polling than suspending the thread waiting for an interrupt.
+ *
+ * @param[in] spip      pointer to the @p SPIDriver object
+ * @param[in] frame     the data frame to send over the SPI bus
+ * @return              The received data frame from the SPI bus.
+ */
+uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
+
+  while((spip->spi->SPI_SR & SPI_SR_TXEMPTY) == 1);
+
+  spip->spi->SPI_TDR = (uint8_t) frame;
+
+  while((spip->spi->SPI_SR & SPI_SR_RDRF) == 0);
+
+  return (uint16_t) spip->spi->SPI_RDR;
+}
+
 #endif /* HAL_USE_SPI */
 
 /** @} */
diff --git a/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.h b/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.h
index f9be8bdee..df448eaec 100644
--- a/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.h
+++ b/os/hal/ports/SAMA/LLD/SPIv1/hal_spi_lld.h
@@ -25,7 +25,7 @@
 #ifndef HAL_SPI_LLD_H
 #define HAL_SPI_LLD_H
 
-#if HAL_USE_SPI || defined(__DOXYGEN__)
+#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
 
 /*===========================================================================*/
 /* Driver constants.                                                         */
@@ -52,15 +52,58 @@
 #define SAMA_SPI_USE_SPI0                   FALSE
 #endif
 
+/**
+ * @brief   SPI0 Generic clock enable.
+ * @details If set to @p TRUE the support for GCLK SPI0 is included.
+ */
+#if !defined(SAMA_SPI0_USE_GCLK) || defined(__DOXYGEN__)
+#define SAMA_SPI0_USE_GCLK                  FALSE
+#endif
+
+/**
+ * @brief   SPI0 Generic clock source.
+ */
+#if !defined(SAMA_SPI0_GCLK_SOURCE) || defined(__DOXYGEN__)
+#define SAMA_SPI0_GCLK_SOURCE               SAMA_GCLK_MCK_CLK
+#endif
+
+/**
+ * @brief   SPI0 Generic clock div.
+ */
+#if !defined(SAMA_SPI0_GCLK_DIV) || defined(__DOXYGEN__)
+#define SAMA_SPI0_GCLK_DIV                  21
+#endif
+
 /**
  * @brief   SPI1 driver enable switch.
  * @details If set to @p TRUE the support for SPI1 is included.
- * @note    The default is @p FALSE.
  */
 #if !defined(SAMA_SPI_USE_SPI1) || defined(__DOXYGEN__)
 #define SAMA_SPI_USE_SPI1                   FALSE
 #endif
 
+/**
+ * @brief   SPI1 Generic clock enable.
+ * @details If set to @p TRUE the support for GCLK SPI1 is included.
+ */
+#if !defined(SAMA_SPI1_USE_GCLK) || defined(__DOXYGEN__)
+#define SAMA_SPI1_USE_GCLK                  FALSE
+#endif
+
+/**
+ * @brief   SPI1 Generic clock source.
+ */
+#if !defined(SAMA_SPI1_GCLK_SOURCE) || defined(__DOXYGEN__)
+#define SAMA_SPI1_GCLK_SOURCE               SAMA_GCLK_MCK_CLK
+#endif
+
+/**
+ * @brief   SPI1 Generic clock div.
+ */
+#if !defined(SAMA_SPI1_GCLK_DIV) || defined(__DOXYGEN__)
+#define SAMA_SPI1_GCLK_DIV                  21
+#endif
+
 /**
  * @brief   SPI FLEXCOM0 driver enable switch.
  * @details If set to @p TRUE the support for FLEXCOM0 is included.
@@ -69,6 +112,28 @@
 #define SAMA_SPI_USE_FLEXCOM0               FALSE
 #endif
 
+/**
+ * @brief   FSPI0 Generic clock enable.
+ * @details If set to @p TRUE the support for GCLK FSPI0 is included.
+ */
+#if !defined(SAMA_FSPI0_USE_GCLK) || defined(__DOXYGEN__)
+#define SAMA_FSPI0_USE_GCLK                 FALSE
+#endif
+
+/**
+ * @brief   FSPI0 Generic clock source.
+ */
+#if !defined(SAMA_FSPI0_GCLK_SOURCE) || defined(__DOXYGEN__)
+#define SAMA_FSPI0_GCLK_SOURCE              SAMA_GCLK_MCK_CLK
+#endif
+
+/**
+ * @brief   FSPI0 Generic clock div.
+ */
+#if !defined(SAMA_FSPI0_GCLK_DIV) || defined(__DOXYGEN__)
+#define SAMA_FSPI0_GCLK_DIV                 21
+#endif
+
 /**
  * @brief   SPI FLEXCOM1 driver enable switch.
  * @details If set to @p TRUE the support for FLEXCOM1 is included.
@@ -77,6 +142,28 @@
 #define SAMA_SPI_USE_FLEXCOM1               FALSE
 #endif
 
+/**
+ * @brief   FSPI1 Generic clock enable.
+ * @details If set to @p TRUE the support for GCLK FSPI1 is included.
+ */
+#if !defined(SAMA_FSPI1_USE_GCLK) || defined(__DOXYGEN__)
+#define SAMA_FSPI1_USE_GCLK                 FALSE
+#endif
+
+/**
+ * @brief   FSPI1 Generic clock source.
+ */
+#if !defined(SAMA_FSPI1_GCLK_SOURCE) || defined(__DOXYGEN__)
+#define SAMA_FSPI1_GCLK_SOURCE              SAMA_GCLK_MCK_CLK
+#endif
+
+/**
+ * @brief   FSPI1 Generic clock div.
+ */
+#if !defined(SAMA_FSPI1_GCLK_DIV) || defined(__DOXYGEN__)
+#define SAMA_FSPI1_GCLK_DIV                 21
+#endif
+
 /**
  * @brief   SPI FLEXCOM2 driver enable switch.
  * @details If set to @p TRUE the support for FLEXCOM2 is included.
@@ -85,6 +172,28 @@
 #define SAMA_SPI_USE_FLEXCOM2               FALSE
 #endif
 
+/**
+ * @brief   FSPI2 Generic clock enable.
+ * @details If set to @p TRUE the support for GCLK FSPI2 is included.
+ */
+#if !defined(SAMA_FSPI2_USE_GCLK) || defined(__DOXYGEN__)
+#define SAMA_FSPI2_USE_GCLK                 FALSE
+#endif
+
+/**
+ * @brief   FSPI2 Generic clock source.
+ */
+#if !defined(SAMA_FSPI2_GCLK_SOURCE) || defined(__DOXYGEN__)
+#define SAMA_FSPI2_GCLK_SOURCE              SAMA_GCLK_MCK_CLK
+#endif
+
+/**
+ * @brief   FSPI2 Generic clock div.
+ */
+#if !defined(SAMA_FSPI2_GCLK_DIV) || defined(__DOXYGEN__)
+#define SAMA_FSPI2_GCLK_DIV                 21
+#endif
+
 /**
  * @brief   SPI FLEXCOM3 driver enable switch.
  * @details If set to @p TRUE the support for FLEXCOM3 is included.
@@ -93,6 +202,28 @@
 #define SAMA_SPI_USE_FLEXCOM3               FALSE
 #endif
 
+/**
+ * @brief   FSPI3 Generic clock enable.
+ * @details If set to @p TRUE the support for GCLK FSPI3 is included.
+ */
+#if !defined(SAMA_FSPI3_USE_GCLK) || defined(__DOXYGEN__)
+#define SAMA_FSPI3_USE_GCLK                 FALSE
+#endif
+
+/**
+ * @brief   FSPI3 Generic clock source.
+ */
+#if !defined(SAMA_FSPI3_GCLK_SOURCE) || defined(__DOXYGEN__)
+#define SAMA_FSPI3_GCLK_SOURCE              SAMA_GCLK_MCK_CLK
+#endif
+
+/**
+ * @brief   FSPI3 Generic clock div.
+ */
+#if !defined(SAMA_FSPI3_GCLK_DIV) || defined(__DOXYGEN__)
+#define SAMA_FSPI3_GCLK_DIV                 21
+#endif
+
 /**
  * @brief   SPI FLEXCOM4 driver enable switch.
  * @details If set to @p TRUE the support for FLEXCOM4 is included.
@@ -101,6 +232,28 @@
 #define SAMA_SPI_USE_FLEXCOM4               FALSE
 #endif
 
+/**
+ * @brief   FSPI4 Generic clock enable.
+ * @details If set to @p TRUE the support for GCLK FSPI4 is included.
+ */
+#if !defined(SAMA_FSPI4_USE_GCLK) || defined(__DOXYGEN__)
+#define SAMA_FSPI4_USE_GCLK                 FALSE
+#endif
+
+/**
+ * @brief   FSPI4 Generic clock source.
+ */
+#if !defined(SAMA_FSPI4_GCLK_SOURCE) || defined(__DOXYGEN__)
+#define SAMA_FSPI4_GCLK_SOURCE              SAMA_GCLK_MCK_CLK
+#endif
+
+/**
+ * @brief   FSPI4 Generic clock div.
+ */
+#if !defined(SAMA_FSPI4_GCLK_DIV) || defined(__DOXYGEN__)
+#define SAMA_FSPI4_GCLK_DIV                 21
+#endif
+
 /**
  * @brief   SPI0 DMA interrupt priority level setting.
  */
@@ -151,6 +304,22 @@
 #endif
 /** @} */
 
+/**
+ * @brief   SPI DMA error hook.
+ * @note    The default action for DMA errors is a system halt because DMA
+ *          error can only happen because programming errors.
+ */
+#if !defined(SAMA_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define SAMA_SPI_DMA_ERROR_HOOK(spip)      osalSysHalt("DMA failure")
+#endif
+
+/**
+ * @brief   SPI cache managing.
+ */
+#if !defined(SAMA_SPI_CACHE_USER_MANAGED) || defined(__DOXYGEN__)
+#define SAMA_SPI_CACHE_USER_MANAGED        FALSE
+#endif
+
 /*===========================================================================*/
 /* Derived constants and error checks.                                       */
 /*===========================================================================*/
@@ -230,106 +399,36 @@
 /* Driver data structures and types.                                         */
 /*===========================================================================*/
 
-/**
- * @brief   Type of a structure representing an SPI driver.
- */
-typedef struct SPIDriver SPIDriver;
+#define spi_lld_driver_fields                                               \
+  /* Pointer to the SPIx registers block.*/                                 \
+  Spi                      *spi;                                            \
+  /* Pointer to the FLEXCOMx registers block.*/                             \
+  Flexcom                  *flexcom;                                        \
+  /* Receive DMA stream.*/                                                  \
+  sama_dma_channel_t       *dmarx;                                          \
+  /* Transmit DMA stream.*/                                                 \
+  sama_dma_channel_t       *dmatx;                                          \
+  /* RX DMA mode bit mask.*/                                                \
+  uint32_t                 rxdmamode;                                       \
+  /* TX DMA mode bit mask.*/                                                \
+  uint32_t                 txdmamode;                                       \
+  /* Pointer to the TX buffer location.*/                                   \
+  const uint8_t            *txbuf;                                          \
+  /* Pointer to the RX buffer location.*/                                   \
+  uint8_t                  *rxbuf;                                          \
+  /* Number of bytes in RX phase.*/                                         \
+  size_t                   rxbytes;
 
 /**
- * @brief   SPI notification callback type.
- *
- * @param[in] spip      pointer to the @p SPIDriver object triggering the
- *                      callback
- */
-typedef void (*spicallback_t)(SPIDriver *spip);
-
-/**
- * @brief   Driver configuration structure.
- */
-typedef struct {
-#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
-  /**
-   * @brief   Enables the circular buffer mode.
-   */
-  bool                      circular;
-#endif
-  /**
-   * @brief Operation complete callback or @p NULL.
-   */
-  spicallback_t             end_cb;
-  /* End of the mandatory fields.*/
-  /**
-   * @brief The chip select line number.
-   */
-  uint16_t                  npcs;
-  /**
-   * @brief SPI MR register initialization data.
-   */
-  uint32_t                  mr;
-  /**
-   * @brief SPI CSR register initialization data.
-   */
+ * @brief   Low level fields of the SPI configuration structure.
+ */
+#define spi_lld_config_fields                                               \
+  /* The chip select line number.*/                                         \
+  uint8_t                  npcs;                                            \
+  /* SPI MR register initialization data.*/                                 \
+  uint32_t                  mr;                                             \
+  /* SPI CSR register initialization data.*/                                \
   uint32_t                  csr;
-} SPIConfig;
-
-/**
- * @brief   Structure representing an SPI driver.
- * @note    Implementations may extend this structure to contain more,
- *          architecture dependent, fields.
- */
-struct SPIDriver {
-  /**
-   * @brief Driver state.
-   */
-  spistate_t                state;
-  /**
-   * @brief Current configuration data.
-   */
-  const SPIConfig           *config;
-#if SPI_USE_WAIT || defined(__DOXYGEN__)
-  /**
-   * @brief Waiting thread.
-   */
-  thread_reference_t        thread;
-#endif /* SPI_USE_WAIT */
-#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
-  /**
-   * @brief Mutex protecting the bus.
-   */
-  mutex_t                   mutex;
-#endif /* SPI_USE_MUTUAL_EXCLUSION */
-#if defined(SPI_DRIVER_EXT_FIELDS)
-  SPI_DRIVER_EXT_FIELDS
-#endif
-  /* End of the mandatory fields.*/
-  /**
-   * @brief Pointer to the SPIx registers block.
-   */
-  Spi                      *spi;
-#if SAMA_SPI_USE_FLEXCOM
-  /**
-   * @brief Pointer to the FLEXCOMx registers block.
-   */
-  Flexcom                  *flexcom;
-#endif
-  /**
-   * @brief   Receive DMA stream.
-   */
-  sama_dma_channel_t       *dmarx;
-   /**
-    * @brief   Transmit DMA stream.
-    */
-  sama_dma_channel_t       *dmatx;
-  /**
-    * @brief   RX DMA mode bit mask.
-    */
-  uint32_t                 rxdmamode;
-  /**
-    * @brief   TX DMA mode bit mask.
-    */
-  uint32_t                 txdmamode;
-};
-
 
 /*===========================================================================*/
 /* Driver macros.                                                            */
@@ -371,7 +470,7 @@ extern SPIDriver FSPID4;
 #ifdef __cplusplus
 extern "C" {
 #endif
-void spi_lld_init(void);
+  void spi_lld_init(void);
   void spi_lld_start(SPIDriver *spip);
   void spi_lld_stop(SPIDriver *spip);
   void spi_lld_select(SPIDriver *spip);
@@ -381,6 +480,7 @@ void spi_lld_init(void);
                         const void *txbuf, void *rxbuf);
   void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
   void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
+  uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
 
 #ifdef __cplusplus
 }
diff --git a/os/hal/ports/SAMA/LLD/USARTv1/hal_serial_lld.h b/os/hal/ports/SAMA/LLD/USARTv1/hal_serial_lld.h
index 552d54b1a..5a028e522 100644
--- a/os/hal/ports/SAMA/LLD/USARTv1/hal_serial_lld.h
+++ b/os/hal/ports/SAMA/LLD/USARTv1/hal_serial_lld.h
@@ -25,7 +25,7 @@
 #ifndef HAL_SERIAL_LLD_H
 #define HAL_SERIAL_LLD_H
 
-#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
 
 /*===========================================================================*/
 /* Driver constants.                                                         */
diff --git a/os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.c b/os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.c
index 8415366a7..eaa53d928 100644
--- a/os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.c
+++ b/os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.c
@@ -29,7 +29,12 @@
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
 /*===========================================================================*/
-
+/*
+ * @brief    NO CACHE attribute
+ */
+#if !defined(NO_CACHE)
+#define NO_CACHE                        __attribute__((section (".nocache")))
+#endif
 /*===========================================================================*/
 /* Driver local macros.                                                      */
 /*===========================================================================*/
@@ -140,9 +145,11 @@ UARTDriver FUARTD4;
 /* Driver local variables and types.                                         */
 /*===========================================================================*/
 /**
- * @brief Linked List view0 word aligned
+ * @brief    Linked List view0 word aligned
+ * @note The descriptor is word-aligned and the two least significant
+ *       register bits 1:0 are ignored.
  */
-  ALIGNED_VAR(4) static lld_view0 descriptor0;
+NO_CACHE ALIGNED_VAR(4) static lld_view0 descriptor0;
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
@@ -173,7 +180,10 @@ static uartflags_t translate_errors(uint32_t isr) {
  * @param[in] uartp     pointer to the @p UARTDriver object
  */
 static void uart_enter_rx_idle_loop(UARTDriver *uartp) {
-  
+
+  /* In this zone driver always cleans cache */
+  cacheCleanRegion((uint32_t *) &uartp->rxbuf, sizeof(uartp->rxbuf));
+
   /* Disabling BIE interrupt if rx callback is null */
   if (uartp->config->rxchar_cb == NULL)
     uartp->dmarx->xdmac->XDMAC_CHID[uartp->dmarx->chid].XDMAC_CID =  XDMAC_CID_BID;
@@ -365,11 +375,17 @@ static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) {
 #endif
 
   if (uartp->rxstate == UART_RX_IDLE) {
+#if (SAMA_UART_CACHE_USER_MANAGED == FALSE)
+    cacheInvalidateRegion((uint32_t *)&uartp->rxbuf, sizeof(uartp->rxbuf));
+#endif
     /* Receiver in idle state, a callback is generated, if enabled, for each
        received character and then the driver stays in the same state.*/
     _uart_rx_idle_code(uartp);
   }
   else {
+#if (SAMA_UART_CACHE_USER_MANAGED == FALSE)
+    cacheInvalidateRegion(uartp->rxbufp, uartp->rxbytes);
+#endif
     /* Receiver in active state, a callback is generated, if enabled, after
        a completed transfer.*/
     dmaChannelDisable(uartp->dmarx);
@@ -1328,6 +1344,9 @@ void uart_lld_stop(UARTDriver *uartp) {
     }
 #endif
   }
+  uartp->txbufp = NULL;
+  uartp->rxbufp = NULL;
+  uartp->rxbytes = 0;
 }
 
 /**
@@ -1343,6 +1362,19 @@ void uart_lld_stop(UARTDriver *uartp) {
  */
 void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) {
 
+  uartp->txbufp = txbuf;
+
+#if (SAMA_UART_CACHE_USER_MANAGED == FALSE)
+
+  osalDbgAssert(!((uint32_t) txbuf & (L1_CACHE_BYTES - 1)), "address not cache aligned");
+
+#if 0
+  osalDbgAssert(!(n & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+#endif
+  /* Cache is enabled */
+  cacheCleanRegion((uint8_t *) txbuf, n);
+#endif /* SAMA_UART_CACHE_USER_MANAGED */
+
   /* TX DMA channel preparation.*/
   dmaChannelSetSource(uartp->dmatx, txbuf);
   dmaChannelSetTransactionSize(uartp->dmatx, n);
@@ -1377,6 +1409,8 @@ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) {
  */
 size_t uart_lld_stop_send(UARTDriver *uartp) {
 
+  uartp->txbufp = NULL;
+
   dmaChannelDisable(uartp->dmatx);
 
   return dmaChannelGetTransactionSize(uartp->dmatx);
@@ -1395,6 +1429,26 @@ size_t uart_lld_stop_send(UARTDriver *uartp) {
  */
 void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
 
+  uartp->rxbufp = rxbuf;
+  uartp->rxbytes = n;
+
+#if (SAMA_UART_CACHE_USER_MANAGED == FALSE)
+
+  osalDbgAssert(!((uint32_t) rxbuf & (L1_CACHE_BYTES - 1)), "address not cache aligned");
+
+#if 0
+  osalDbgAssert(!(n & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+#endif
+
+  /*
+   * If size is not multiple of cache line, clean cache region is required.
+   * TODO: remove when size assert works
+   */
+  if (n & (L1_CACHE_BYTES - 1)) {
+    cacheCleanRegion((uint8_t *) rxbuf, n);
+  }
+#endif /* SAMA_UART_CACHE_USER_MANAGED */
+
   /* Stopping previous activity (idle state).*/
   dmaChannelDisable(uartp->dmarx);
 
@@ -1437,8 +1491,12 @@ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
  * @notapi
  */
 size_t uart_lld_stop_receive(UARTDriver *uartp) {
+
   size_t n;
 
+  uartp->rxbufp = NULL;
+  uartp->rxbytes = 0;
+
   dmaChannelDisable(uartp->dmarx);
   n = dmaChannelGetTransactionSize(uartp->dmarx);
   uart_enter_rx_idle_loop(uartp);
diff --git a/os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.h b/os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.h
index 6c20da1c4..1f299e650 100644
--- a/os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.h
+++ b/os/hal/ports/SAMA/LLD/USARTv1/hal_uart_lld.h
@@ -277,6 +277,13 @@
 #if !defined(SAMA_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
 #define SAMA_UART_DMA_ERROR_HOOK(uartp)    osalSysHalt("DMA failure")
 #endif
+
+/**
+ * @brief   UART cache managing.
+ */
+#if !defined(SAMA_UART_CACHE_USER_MANAGED) || defined(__DOXYGEN__)
+#define SAMA_UART_CACHE_USER_MANAGED       FALSE
+#endif
 /** @} */
 
 /*===========================================================================*/
@@ -564,7 +571,20 @@ struct UARTDriver {
   /**
    * @brief   Default receive buffer while into @p UART_RX_IDLE state.
    */
+  CACHE_ALIGNED
   volatile uint16_t         rxbuf;
+  /**
+   * @brief     Pointer to the TX buffer location.
+   */
+  const uint8_t            *txbufp;
+  /**
+   * @brief     Pointer to the RX buffer location.
+   */
+  uint8_t                  *rxbufp;
+  /**
+   * @brief     Number of bytes in RX phase.
+   */
+  size_t                   rxbytes;
 };
 
 /*===========================================================================*/
diff --git a/os/hal/ports/SAMA/LLD/xWDGv1/driver.mk b/os/hal/ports/SAMA/LLD/xWDGv1/driver.mk
new file mode 100644
index 000000000..797b95112
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/xWDGv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_WDG TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/xWDGv1
diff --git a/os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.c b/os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.c
new file mode 100644
index 000000000..e7c274e8c
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.c
@@ -0,0 +1,165 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    WDGv1/hal_wdg_lld.c
+ * @brief   WDG Driver subsystem low level driver source.
+ *
+ * @addtogroup WDG
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+/**
+ * @brief WDG driver identifier.
+ */
+WDGDriver WDGD0;
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+/**
+ * @brief   Local function that computes the period
+ *          for WDT_MR_WDV and WDT_MR_VDD registers.
+ *
+ * @param[in] period    period to be computed.
+ *
+ * @notapi
+ */
+static uint32_t wdt_compute_period(uint32_t period) {
+
+  uint32_t value;
+  value = period * (SAMA_SLOW_CLK >> 7) / 1000;
+  if (value > 0xfff)
+    value = 0xfff;
+
+  return value;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+/**
+ * @brief   WDG IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(SAMA_WDG_HANDLER) {
+
+  OSAL_IRQ_PROLOGUE();
+
+  /* Read status register. */
+  uint32_t sr = WDT->WDT_SR;
+
+  if (WDGD0.config->callback != NULL) {
+    if (sr & WDT_SR_WDERR) {
+      WDGD0.config->callback(&WDGD0, WDG_ERROR);
+    }
+
+    else
+      WDGD0.config->callback(&WDGD0, WDG_UNDERFLOW);
+  }
+
+  aicAckInt();
+  OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+/**
+ * @brief   Low level WDG driver initialization.
+ *
+ * @notapi
+ */
+void wdg_lld_init(void) {
+
+#if SAMA_HAL_IS_SECURE
+  mtxConfigPeriphSecurity(MATRIX1, ID_WDT, SECURE_PER);
+#endif
+
+  WDGD0.state = WDG_STOP;
+  WDGD0.wdg   = WDT;
+}
+
+/**
+ * @brief   Configures and activates the WDT peripheral.
+ *
+ * @param[in] wdgp      pointer to the @p WDGDriver object
+ *
+ * @notapi
+ */
+void wdg_lld_start(WDGDriver *wdgp) {
+
+  (void) wdgp;
+
+  /* Read status register. */
+  WDT->WDT_SR;
+
+  /* Write configuration */
+  WDT->WDT_MR = (wdgp->config->mode & ~(WDT_MR_WDDIS | WDT_MR_WDD_Msk | WDT_MR_WDV_Msk)) |
+                WDT_MR_WDV(wdt_compute_period(wdgp->config->counter)) |
+                WDT_MR_WDD(wdt_compute_period(wdgp->config->delta));
+
+  aicSetSourcePriority(ID_WDT, SAMA_WDG_IRQ_PRIORITY);
+  aicSetSourceHandler(ID_WDT, SAMA_WDG_HANDLER);
+  aicEnableInt(ID_WDT);
+}
+
+/**
+ * @brief   Deactivates the WDG peripheral.
+ *
+ * @param[in] wdgp      pointer to the @p WDGDriver object
+ *
+ * @notapi
+ */
+void wdg_lld_stop(WDGDriver *wdgp) {
+
+  (void) wdgp;
+  WDT->WDT_MR = WDT_MR_WDDIS;
+}
+
+/**
+ * @brief   Reloads the WDG counter.
+ *
+ * @param[in] wdgp      pointer to the @p WDGDriver object
+ *
+ * @notapi
+ */
+void wdg_lld_reset(WDGDriver * wdgp) {
+
+  (void) wdgp;
+  WDT->WDT_CR = WDT_CR_KEY_PASSWD | WDT_CR_WDRSTT;
+}
+
+#endif /* HAL_USE_WDG == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.h b/os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.h
new file mode 100644
index 000000000..0904c55fb
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/xWDGv1/hal_wdg_lld.h
@@ -0,0 +1,141 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    WDGv1/hal_wdg_lld.h
+ * @brief   WDG Driver subsystem low level driver header.
+ *
+ * @addtogroup WDG
+ * @{
+ */
+
+#ifndef HAL_WDG_LLD_H
+#define HAL_WDG_LLD_H
+
+#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings.                                         */
+/*===========================================================================*/
+/**
+ * @name    Configuration options
+ * @{
+ */
+/*
+ * WDG driver system settings.
+ */
+#define SAMA_WDG_IRQ_PRIORITY       4
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks.                                       */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+/**
+  * @brief   Type of an WDG event.
+  */
+typedef enum {
+  WDG_ERROR = 0,                          /** Watchdog fault error.          */
+  WDG_UNDERFLOW = 1                       /** Watchdog underflow error.      */
+} wdgevent_t;
+
+/**
+ * @brief   Type of a structure representing an WDG driver.
+ */
+typedef struct WDGDriver WDGDriver;
+
+/**
+  * @brief   Type of a generic WDG callback.
+  */
+typedef void (*wdgcb_t)(WDGDriver *wdgp, wdgevent_t event);
+
+/**
+ * @brief   Driver configuration structure.
+ * @note    It could be empty on some architectures.
+ */
+typedef struct {
+  /**
+   * @brief   Callback pointer.
+   */
+  wdgcb_t                   callback;
+  /**
+   * @brief   Configuration of the WDT modes.
+   */
+  uint32_t                  mode;
+  /**
+   * @brief   Configuration of the WDT counter.
+   */
+  uint32_t                  counter;
+  /**
+   * @brief   Configuration of the WDT delta.
+   */
+  uint32_t                  delta;
+} WDGConfig;
+
+/**
+ * @brief   Structure representing an WDG driver.
+ */
+struct WDGDriver {
+  /**
+   * @brief   Driver state.
+   */
+  wdgstate_t                state;
+  /**
+   * @brief   Current configuration data.
+   */
+  const WDGConfig           *config;
+  /* End of the mandatory fields.*/
+  /**
+   * @brief   Pointer to the WDT registers block.
+   */
+  Wdt                       *wdg;
+};
+
+/*===========================================================================*/
+/* Driver macros.                                                            */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations.                                                    */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern WDGDriver WDGD0;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void wdg_lld_init(void);
+  void wdg_lld_start(WDGDriver *wdgp);
+  void wdg_lld_stop(WDGDriver *wdgp);
+  void wdg_lld_reset(WDGDriver *wdgp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_WDG == TRUE */
+
+#endif /* HAL_WDG_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/aic.c b/os/hal/ports/SAMA/SAMA5D2x/aic.c
deleted file mode 100644
index d961c58fd..000000000
--- a/os/hal/ports/SAMA/SAMA5D2x/aic.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
-    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-*/
-
-/**
- * @file    SAMA5D2x/aic.c
- * @brief   SAMA AIC support code.
- *
- * @addtogroup SAMA5D2x_AIC
- * @{
- */
-
-#include "hal.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported variables.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local types.                                                       */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local macros.                                                      */
-/*===========================================================================*/
-
-/**
- * @brief   Enable write protection on AIC registers block.
- *
- * @param[in] aicp    pointer to a AIC register block
- *
- * @notapi
- */
-#define aicEnableWP(aicp) {                                                  \
-  aicp->AIC_WPMR = AIC_WPMR_WPKEY_PASSWD | AIC_WPMR_WPEN;                    \
-}
-
-/**
- * @brief   Disable write protection on AIC registers block.
- *
- * @param[in] aicp    pointer to a AIC register block
- *
- * @notapi
- */
-#define aicDisableWP(aicp) {                                                 \
-  aicp->AIC_WPMR = AIC_WPMR_WPKEY_PASSWD;                                    \
-}
-
-/**
- * @brief   Checks if a IRQ priority is within the valid range.
- * @param[in] prio      IRQ priority
- *
- * @retval              The check result.
- * @retval FALSE        invalid IRQ priority.
- * @retval TRUE         correct IRQ priority.
- */
-#define SAMA_IRQ_IS_VALID_PRIORITY(prio) ((prio) <= 7U)
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-static OSAL_IRQ_HANDLER(aicSpuriousHandler) {
-  OSAL_IRQ_PROLOGUE();
-  osalSysHalt("Spurious interrupt");
-  OSAL_IRQ_EPILOGUE();
-}
-
-static OSAL_IRQ_HANDLER(aicUnexpectedHandler) {
-  OSAL_IRQ_PROLOGUE();
-  osalSysHalt("Unexpected interrupt");
-  OSAL_IRQ_EPILOGUE();
-}
-
-/**
- * @brief   AIC Initialization.
- * @note    Better reset everything in the AIC.
- *
- * @notapi
- */
-void aicInit(void) {
-
-#if SAMA_HAL_IS_SECURE
-  Aic *aic = SAIC;
-#else
-  Aic *aic = AIC;
-#endif
-
-  aicDisableWP(aic);
-
-  aic->AIC_SPU = (uint32_t)aicSpuriousHandler;
-  aic->AIC_SSR = 0;
-  aic->AIC_SVR = (uint32_t)aicUnexpectedHandler;
-
-  unsigned i;
-  /* Disable all interrupts */
-  for (i = 1; i < ID_PERIPH_COUNT; i++) {
-    aic->AIC_SSR = i;
-    aic->AIC_IDCR = AIC_IDCR_INTD;
-
-    /* Changes type */
-    aic->AIC_SMR = AIC_SMR_SRCTYPE(EXT_NEGATIVE_EDGE);
-
-    /* Clear pending interrupt */
-    aic->AIC_ICCR = AIC_ICCR_INTCLR;
-
-    /* Changes type */
-    aic->AIC_SMR = AIC_SMR_SRCTYPE(INT_LEVEL_SENSITIVE);
-
-    /* Default handler */
-    aic->AIC_SVR = (uint32_t)aicUnexpectedHandler;
-  }
-  aicEnableWP(aic);
-}
-
-/**
- * @brief   Configures an interrupt in the AIC.
- * @note    Source cannot be ID_SAIC_FIQ (0).
- *
- * @param[in] source    interrupt source to configure
- * @param[in] priority  priority level of the selected source.
- */
-void aicSetSourcePriority(uint32_t source, uint8_t priority) {
-
-#if SAMA_HAL_IS_SECURE
-  Aic *aic = SAIC;
-#else
-  Aic *aic = AIC;
-#endif
-
-  osalDbgCheck(source != ID_SAIC_FIQ);
-  osalDbgAssert(SAMA_IRQ_IS_VALID_PRIORITY(priority), "invalid irq priority");
-  /* Disable write protection */
-  aicDisableWP(aic);
-  /* Set source id */
-  aic->AIC_SSR = source;
-  /* Disable the interrupt first */
-  aic->AIC_IDCR = AIC_IDCR_INTD;
-  /* Configure priority */
-  aic->AIC_SMR = AIC_SMR_PRIOR(priority);
-  /* Clear interrupt */
-  aic->AIC_ICCR = AIC_ICCR_INTCLR;
-  /* Enable write protection */
-  aicEnableWP(aic);
-}
-
-/**
- * @brief   Configures type of interrupt in the AIC.
- *
- * @param[in] source    interrupt source to configure
- * @param[in] type      type interrupt of the selected source.
- */
-void aicSetIntSourceType(uint32_t source, uint8_t type) {
-
-#if SAMA_HAL_IS_SECURE
-  Aic *aic = SAIC;
-#else
-  Aic *aic = AIC;
-#endif
-  /* Disable write protection */
-  aicDisableWP(aic);
-  /* Set source id */
-  aic->AIC_SSR = source;
-  /* Disable the interrupt first */
-  aic->AIC_IDCR = AIC_IDCR_INTD;
-  /* Configure priority */
-  aic->AIC_SMR = AIC_SMR_SRCTYPE(type);
-  /* Clear interrupt */
-  aic->AIC_ICCR = AIC_ICCR_INTCLR;
-  /* Enable write protection */
-  aicEnableWP(aic);
-}
-
-/**
- * @brief   Sets the source handler of an interrupt.
- *
- * @param[in] source    interrupt source to configure
- * @param[in] handler   handler for the interrupt source selected
- */
-void aicSetSourceHandler(uint32_t source, bool (*handler)(void)) {
-
-#if SAMA_HAL_IS_SECURE
-  Aic *aic = SAIC;
-#else
-  Aic *aic = AIC;
-#endif
-
-  /* Disable write protection */
-  aicDisableWP(aic);
-  /* Select source and assign handler */
-  aic->AIC_SSR = AIC_SSR_INTSEL(source);
-  aic->AIC_SVR = (uint32_t)handler;
-  /* Enable write protection */
-  aicEnableWP(aic);
-}
-
-/**
- * @brief   Sets the spurious handler of an interrupt.
- *
- * @param[in] handler   handler for the interrupt
- */
-void aicSetSpuriousHandler(bool (*handler)(void)) {
-
-#if SAMA_HAL_IS_SECURE
-  Aic *aic = SAIC;
-#else
-  Aic *aic = AIC;
-#endif
-
-  /* Disable write protection */
-  aicDisableWP(aic);
-  /* Assign handler */
-  aic->AIC_SPU = (uint32_t)handler;
-  /* Enable write protection */
-  aicEnableWP(aic);
-}
-
-/**
- * @brief   Enables interrupts coming from the source.
- *
- * @param[in] source    interrupt source to enable
- */
-void aicEnableInt(uint32_t source) {
-
-#if SAMA_HAL_IS_SECURE
-  Aic *aic = SAIC;
-#else
-  Aic *aic = AIC;
-#endif
-
-  aic->AIC_SSR = AIC_SSR_INTSEL(source);
-  aic->AIC_IECR = AIC_IECR_INTEN;
-}
-
-/**
- * @brief   Disables interrupts coming from the selected source.
- *
- * @param[in] source    interrupt source to disable
- */
-void aicDisableInt(uint32_t source) {
-
-#if SAMA_HAL_IS_SECURE
-  Aic *aic = SAIC;
-#else
-  Aic *aic = AIC;
-#endif
-
-  aic->AIC_SSR = AIC_SSR_INTSEL(source);
-  aic->AIC_IDCR = AIC_IDCR_INTD;
-}
-
-/**
- * @brief   Clears interrupts coming from the selected source.
- *
- * @param[in] source    interrupt source to Clear
- */
-void aicClearInt(uint32_t source) {
-
-#if SAMA_HAL_IS_SECURE
-  Aic *aic = SAIC;
-#else
-  Aic *aic = AIC;
-#endif
-
-  aic->AIC_SSR = AIC_SSR_INTSEL(source);
-  aic->AIC_ICCR = AIC_ICCR_INTCLR;
-}
-
-/**
- * @brief   Sets interrupts coming from the selected source.
- *
- * @param[in] source    interrupt source to Set
- */
-void aicSetInt(uint32_t source) {
-
-#if SAMA_HAL_IS_SECURE
-  Aic *aic = SAIC;
-#else
-  Aic *aic = AIC;
-#endif
-
-  aic->AIC_SSR = AIC_SSR_INTSEL(source);
-  aic->AIC_ISCR = AIC_ISCR_INTSET;
-}
-
-/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/aic.h b/os/hal/ports/SAMA/SAMA5D2x/aic.h
deleted file mode 100644
index a4f220754..000000000
--- a/os/hal/ports/SAMA/SAMA5D2x/aic.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-*/
-
-/**
- * @file    SAMA5D2x/aic.h
- * @brief   SAMA AIC support macros and structures.
- *
- * @addtogroup SAMA5D2x_AIC
- * @{
- */
-
-#ifndef AIC_H
-#define AIC_H
-
-/*===========================================================================*/
-/* Driver constants.                                                         */
-/*===========================================================================*/
-/**
- * @name    INTERRUPT SOURCE TYPE mode macros
- * @{
- */
-/**
- * @brief   High-level sensitive for internal source.
- *          Low-level sensitive for external source.
- */
-#define INT_LEVEL_SENSITIVE                     0x0U
-
-/**
- * @brief   Negative-edge triggered for external source.
- */
-#define EXT_NEGATIVE_EDGE                       0x1U
-
-/**
- * @brief   High-level sensitive for internal source.
- *          High-level sensitive for external source.
- */
-#define EXT_HIGH_LEVEL                          0x2U
-
-/**
- * @brief   Positive-edge triggered for external source.
- */
-#define EXT_POSITIVE_EDGE                       0x3U
-/** @} */
-
-/**
- * @brief   AIC unique redirect key.
- */
-#define AIC_REDIR_KEY                       0x5B6C0E26U
-
-/*===========================================================================*/
-/* Driver pre-compile time settings.                                         */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Derived constants and error checks.                                       */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver data structures and types.                                         */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver macros.                                                            */
-/*===========================================================================*/
-
-/**
- * @brief   Acknowledge the current interrupt.
- */
-#if SAMA_HAL_IS_SECURE
-#define aicAckInt() {                                                     \
-  SAIC->AIC_EOICR = AIC_EOICR_ENDIT;                                      \
-}
-#else
-#define aicAckInt() {                                                     \
-  AIC->AIC_EOICR = AIC_EOICR_ENDIT;                                       \
-}
-#endif
-
-/*===========================================================================*/
-/* External declarations.                                                    */
-/*===========================================================================*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-  void aicInit(void);
-  void aicSetSourcePriority(uint32_t source, uint8_t priority);
-  void aicSetIntSourceType(uint32_t source, uint8_t type);
-  void aicSetSourceHandler(uint32_t source, bool (*handler)(void));
-  void aicSetSpuriousHandler(bool (*handler)(void));
-  void aicEnableInt(uint32_t source);
-  void aicDisableInt(uint32_t source);
-  void aicClearInt(uint32_t source);
-  void aicSetInt(uint32_t source);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AIC_H */
-
-/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c b/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c
index b62e4654c..ad422f265 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c
+++ b/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c
@@ -1528,7 +1528,7 @@ cryerror_t cry_lld_HMACSHA256_update(CRYDriver *cryp,
                                      const uint8_t *in) {
   uint8_t i;
   cryerror_t res;
-  uint32_t buffer[16];
+  CACHE_ALIGNED uint32_t buffer[16];
 
   if (hmacsha256ctxp->kipad == 0)
   {
@@ -1576,8 +1576,8 @@ cryerror_t cry_lld_HMACSHA256_final(CRYDriver *cryp,
 
   uint8_t i;
   cryerror_t res;
-  uint32_t buffer[16]; //max block size for sha256
-  uint8_t digest[32];
+  CACHE_ALIGNED uint32_t buffer[16]; //max block size for sha256
+  CACHE_ALIGNED uint8_t digest[32];
 
   //H( k1pad || m )
 
@@ -1668,7 +1668,7 @@ cryerror_t cry_lld_HMACSHA512_update(CRYDriver *cryp,
 
   cryerror_t res;
   uint8_t i;
-  uint32_t buffer[32];
+CACHE_ALIGNED uint32_t buffer[32];
 
   if (hmacsha512ctxp->kipad == 0)
   {
@@ -1714,8 +1714,8 @@ cryerror_t cry_lld_HMACSHA512_final(CRYDriver *cryp,
 
   uint8_t i;
   cryerror_t res;
-  uint32_t buffer[32]; //max block size for sha256
-  uint8_t digest[64];
+  CACHE_ALIGNED uint32_t buffer[32]; //max block size for sha256
+  CACHE_ALIGNED uint8_t digest[64];
 
   //H( k1pad || m )
 
diff --git a/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.h b/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.h
index 1bacbc80b..5e5ce362d 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.h
+++ b/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.h
@@ -123,10 +123,10 @@ typedef enum  {
 	CRY_SHA_512,
 
 	CRY_HMACSHA_1,
-    CRY_HMACSHA_224,
-    CRY_HMACSHA_256,
-    CRY_HMACSHA_384,
-    CRY_HMACSHA_512,
+  CRY_HMACSHA_224,
+  CRY_HMACSHA_256,
+  CRY_HMACSHA_384,
+  CRY_HMACSHA_512,
 
 }shadalgo_t;
 
@@ -211,6 +211,18 @@ struct CRYDriver {
    * @brief   Size of transient key.
    */
   size_t                    key0_size;
+  /**
+   * @brief     Pointer to the in buffer location.
+   */
+  const uint8_t             *in;
+  /**
+   * @brief     Pointer to the out buffer location.
+   */
+  uint8_t                   *out;
+  /**
+   * @brief     Number of bytes.
+   */
+  size_t                    len;
 #if (HAL_CRY_USE_FALLBACK == TRUE) || defined(__DOXYGEN__)
   /**
    * @brief   Key buffer for the fall-back implementation.
diff --git a/os/hal/ports/SAMA/SAMA5D2x/hal_lld.c b/os/hal/ports/SAMA/SAMA5D2x/hal_lld.c
index f45928b56..623d20b7a 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/hal_lld.c
+++ b/os/hal/ports/SAMA/SAMA5D2x/hal_lld.c
@@ -76,12 +76,16 @@ void hal_lld_init(void) {
 
   /* Configures PMC and RTC as secure */
   //mtxConfigPeriphSecurity(MATRIX1, ID_SYSC, SECURE_PER);
-  //mtxConfigPeriphSecurity(MATRIX0, ID_PMC, SECURE_PER);
+  mtxConfigPeriphSecurity(MATRIX0, ID_PMC, SECURE_PER);
   mtxConfigPeriphSecurity(MATRIX1, ID_SFC, SECURE_PER);
   mtxConfigPeriphSecurity(MATRIX1, ID_SFR, SECURE_PER);
-  mtxConfigPeriphSecurity(MATRIX0, ID_L2CC, SECURE_PER);
+
+  /* It isn't necessary to make L2CC secure. L2C-310 cache
+   * controller is secure mode aware.*/
+  /*mtxConfigPeriphSecurity(MATRIX0, ID_L2CC, SECURE_PER);*/
+
   mtxConfigPeriphSecurity(MATRIX1, ID_SFRBU, SECURE_PER);
-  mtxConfigPeriphSecurity(MATRIX1, ID_CHIPID, SECURE_PER);
+  /*mtxConfigPeriphSecurity(MATRIX1, ID_CHIPID, SECURE_PER);*/
 
   /* Enabling matrix clock */
   pmcEnableH32MX();
diff --git a/os/hal/ports/SAMA/SAMA5D2x/hal_lld.h b/os/hal/ports/SAMA/SAMA5D2x/hal_lld.h
index 0f0a4fec5..5c5669ecd 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/hal_lld.h
+++ b/os/hal/ports/SAMA/SAMA5D2x/hal_lld.h
@@ -175,6 +175,17 @@
 
 #define SAMA_MCK_PLLADIV2       (1 << 12)   /**< PLLA is divided by 2.     */
 
+/**
+ * @name    PCM_PCR register bits definitions
+ * @{
+ */
+#define   SAMA_GCLK_SLOW_CLK    (0x0u << 8) /**< GCLK Slow clock is selected      */
+#define   SAMA_GCLK_MAIN_CLK    (0x1u << 8) /**< GCLK GMain clock is selected     */
+#define   SAMA_GCLK_PLLA_CLK    (0x2u << 8) /**< GCLK  PLLACK is selected         */
+#define   SAMA_GCLKUPLL_CLK     (0x3u << 8) /**< GCLK UPLL Clock is selected      */
+#define   SAMA_GCLK_MCK_CLK     (0x4u << 8) /**< GCLK Master Clock is selected    */
+#define   SAMA_GCLK_AUDIO_CLK   (0x5u << 8) /**< GCLK Audio PLL clock is selected */
+
 /** @} */
 
 /*===========================================================================*/
@@ -458,6 +469,7 @@
 
 /**
  * @brief   UARTx clock.
+ * TODO: Work only with PERIPH CLOCK
  */
 #define SAMA_UART0CLK                       (SAMA_MCK / SAMA_H64MX_H32MX_RATIO)
 #define SAMA_UART1CLK                       (SAMA_MCK / SAMA_H64MX_H32MX_RATIO)
@@ -467,6 +479,7 @@
 
 /**
  * @brief   FLEXCOMx clock.
+ * TODO: Work only with PERIPH CLOCK
  */
 #define SAMA_FLEXCOM0CLK                    (SAMA_MCK / SAMA_H64MX_H32MX_RATIO)
 #define SAMA_FLEXCOM1CLK                    (SAMA_MCK / SAMA_H64MX_H32MX_RATIO)
@@ -476,15 +489,23 @@
 
 /**
  * @brief   TCx clock.
+ * TODO: Work only with PERIPH CLOCK
  */
 #define SAMA_TC0CLK                         (SAMA_MCK / SAMA_H64MX_H32MX_RATIO)
 #define SAMA_TC1CLK                         (SAMA_MCK / SAMA_H64MX_H32MX_RATIO)
 
 /**
  * @brief   GMAC0 clock.
+ * TODO: Work only with PERIPH CLOCK
  */
 #define SAMA_GMAC0CLK                       (SAMA_MCK / SAMA_H64MX_H32MX_RATIO)
 
+/**
+ * @brief   TWIHSx clock.
+ * TODO: Work only with PERIPH CLOCK
+ */
+#define SAMA_TWIHSxCLK                      (SAMA_MCK / SAMA_H64MX_H32MX_RATIO)
+
 /*===========================================================================*/
 /* Driver data structures and types.                                         */
 /*===========================================================================*/
@@ -499,13 +520,16 @@
 
 /* Various helpers.*/
 #include "sama_pmc.h"
-#include "aic.h"
+#include "sama_aic.h"
 #include "sama_matrix.h"
 #include "sama_xdmac.h" 
 #include "sama_cache.h"
-#include "hal_tc_lld.h"
+#include "sama_tc_lld.h"
+#include "sama_lcdc.h"
 #include "sama_secumod.h"
-#include "sama_trng.h"
+#include "sama_onewire.h"
+#include "sama_classd.h"
+#include "sama_rstc.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/os/hal/ports/SAMA/SAMA5D2x/platform.mk b/os/hal/ports/SAMA/SAMA5D2x/platform.mk
index 026f8c445..67f8976da 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/platform.mk
+++ b/os/hal/ports/SAMA/SAMA5D2x/platform.mk
@@ -2,12 +2,14 @@
 
 PLATFORMSRC := $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/hal_lld.c        \
                $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/hal_st_lld.c     \
-               $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/aic.c            \
+               $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_aic.c       \
                $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_matrix.c    \
                $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c   \
-               $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_trng.c      \
+               $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_onewire.c   \
+               $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_classd.c    \
+               $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.c      \
                $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_cache.c     \
-               $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/hal_tc_lld.c     \
+               $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.c    \
                $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c
                
 # Required include directories.
@@ -28,13 +30,17 @@ endif
 
 # Drivers compatible with the platform.
 include $(CHIBIOS)/os/hal/ports/SAMA/LLD/DMAv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/SAMA/LLD/I2Cv1/driver.mk
 include $(CHIBIOS)/os/hal/ports/SAMA/LLD/MACv1/driver.mk
 include $(CHIBIOS)/os/hal/ports/SAMA/LLD/PIOv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/SAMA/LLD/QUADSPIv1/driver.mk
 include $(CHIBIOS)/os/hal/ports/SAMA/LLD/SPIv1/driver.mk
 include $(CHIBIOS)/os/hal/ports/SAMA/LLD/RTCv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/SAMA/LLD/xWDGv1/driver.mk
 include $(CHIBIOS)/os/hal/ports/SAMA/LLD/USARTv1/driver.mk
 include $(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/driver.mk
 include $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk 
+include $(CHIBIOS)/os/hal/ports/SAMA/LLD/RNGv1/driver.mk 
 
 # Shared variables
 ALLCSRC += $(PLATFORMSRC)
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_aic.c b/os/hal/ports/SAMA/SAMA5D2x/sama_aic.c
new file mode 100644
index 000000000..e47336bb5
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_aic.c
@@ -0,0 +1,310 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/aic.c
+ * @brief   SAMA AIC support code.
+ *
+ * @addtogroup SAMA5D2x_AIC
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local types.                                                       */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local macros.                                                      */
+/*===========================================================================*/
+
+/**
+ * @brief   Enable write protection on AIC registers block.
+ *
+ * @param[in] aicp    pointer to a AIC register block
+ *
+ * @notapi
+ */
+#define aicEnableWP(aicp) {                                                  \
+  aicp->AIC_WPMR = AIC_WPMR_WPKEY_PASSWD | AIC_WPMR_WPEN;                    \
+}
+
+/**
+ * @brief   Disable write protection on AIC registers block.
+ *
+ * @param[in] aicp    pointer to a AIC register block
+ *
+ * @notapi
+ */
+#define aicDisableWP(aicp) {                                                 \
+  aicp->AIC_WPMR = AIC_WPMR_WPKEY_PASSWD;                                    \
+}
+
+/**
+ * @brief   Checks if a IRQ priority is within the valid range.
+ * @param[in] prio      IRQ priority
+ *
+ * @retval              The check result.
+ * @retval FALSE        invalid IRQ priority.
+ * @retval TRUE         correct IRQ priority.
+ */
+#define SAMA_IRQ_IS_VALID_PRIORITY(prio) ((prio) <= 7U)
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+static OSAL_IRQ_HANDLER(aicSpuriousHandler) {
+  OSAL_IRQ_PROLOGUE();
+  osalSysHalt("Spurious interrupt");
+  OSAL_IRQ_EPILOGUE();
+}
+
+static OSAL_IRQ_HANDLER(aicUnexpectedHandler) {
+  OSAL_IRQ_PROLOGUE();
+  osalSysHalt("Unexpected interrupt");
+  OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief   AIC Initialization.
+ * @note    Better reset everything in the AIC.
+ *
+ * @notapi
+ */
+void aicInit(void) {
+
+#if SAMA_HAL_IS_SECURE
+  Aic *aic = SAIC;
+#else
+  Aic *aic = AIC;
+#endif
+
+  aicDisableWP(aic);
+
+  aic->AIC_SPU = (uint32_t)aicSpuriousHandler;
+  aic->AIC_SSR = 0;
+  aic->AIC_SVR = (uint32_t)aicUnexpectedHandler;
+
+  unsigned i;
+  /* Disable all interrupts */
+  for (i = 1; i < ID_PERIPH_COUNT; i++) {
+    aic->AIC_SSR = i;
+    aic->AIC_IDCR = AIC_IDCR_INTD;
+
+    /* Changes type */
+    aic->AIC_SMR = AIC_SMR_SRCTYPE(EXT_NEGATIVE_EDGE);
+
+    /* Clear pending interrupt */
+    aic->AIC_ICCR = AIC_ICCR_INTCLR;
+
+    /* Changes type */
+    aic->AIC_SMR = AIC_SMR_SRCTYPE(INT_LEVEL_SENSITIVE);
+
+    /* Default handler */
+    aic->AIC_SVR = (uint32_t)aicUnexpectedHandler;
+  }
+  aicEnableWP(aic);
+}
+
+/**
+ * @brief   Configures an interrupt in the AIC.
+ * @note    Source cannot be ID_SAIC_FIQ (0).
+ *
+ * @param[in] source    interrupt source to configure
+ * @param[in] priority  priority level of the selected source.
+ */
+void aicSetSourcePriority(uint32_t source, uint8_t priority) {
+
+#if SAMA_HAL_IS_SECURE
+  Aic *aic = SAIC;
+#else
+  Aic *aic = AIC;
+#endif
+
+  osalDbgCheck(source != ID_SAIC_FIQ);
+  osalDbgAssert(SAMA_IRQ_IS_VALID_PRIORITY(priority), "invalid irq priority");
+  /* Disable write protection */
+  aicDisableWP(aic);
+  /* Set source id */
+  aic->AIC_SSR = source;
+  /* Disable the interrupt first */
+  aic->AIC_IDCR = AIC_IDCR_INTD;
+  /* Configure priority */
+  aic->AIC_SMR |= AIC_SMR_PRIOR(priority);
+  /* Clear interrupt */
+  aic->AIC_ICCR = AIC_ICCR_INTCLR;
+  /* Enable write protection */
+  aicEnableWP(aic);
+}
+
+/**
+ * @brief   Configures type of interrupt in the AIC.
+ *
+ * @param[in] source    interrupt source to configure
+ * @param[in] type      type interrupt of the selected source.
+ */
+void aicSetIntSourceType(uint32_t source, uint8_t type) {
+
+#if SAMA_HAL_IS_SECURE
+  Aic *aic = SAIC;
+#else
+  Aic *aic = AIC;
+#endif
+  /* Disable write protection */
+  aicDisableWP(aic);
+  /* Set source id */
+  aic->AIC_SSR = source;
+  /* Disable the interrupt first */
+  aic->AIC_IDCR = AIC_IDCR_INTD;
+  /* Configure priority */
+  aic->AIC_SMR |= AIC_SMR_SRCTYPE(type);
+  /* Clear interrupt */
+  aic->AIC_ICCR = AIC_ICCR_INTCLR;
+  /* Enable write protection */
+  aicEnableWP(aic);
+}
+
+/**
+ * @brief   Sets the source handler of an interrupt.
+ *
+ * @param[in] source    interrupt source to configure
+ * @param[in] handler   handler for the interrupt source selected
+ */
+void aicSetSourceHandler(uint32_t source, bool (*handler)(void)) {
+
+#if SAMA_HAL_IS_SECURE
+  Aic *aic = SAIC;
+#else
+  Aic *aic = AIC;
+#endif
+
+  /* Disable write protection */
+  aicDisableWP(aic);
+  /* Select source and assign handler */
+  aic->AIC_SSR = AIC_SSR_INTSEL(source);
+  aic->AIC_SVR = (uint32_t)handler;
+  /* Enable write protection */
+  aicEnableWP(aic);
+}
+
+/**
+ * @brief   Sets the spurious handler of an interrupt.
+ *
+ * @param[in] handler   handler for the interrupt
+ */
+void aicSetSpuriousHandler(bool (*handler)(void)) {
+
+#if SAMA_HAL_IS_SECURE
+  Aic *aic = SAIC;
+#else
+  Aic *aic = AIC;
+#endif
+
+  /* Disable write protection */
+  aicDisableWP(aic);
+  /* Assign handler */
+  aic->AIC_SPU = (uint32_t)handler;
+  /* Enable write protection */
+  aicEnableWP(aic);
+}
+
+/**
+ * @brief   Enables interrupts coming from the source.
+ *
+ * @param[in] source    interrupt source to enable
+ */
+void aicEnableInt(uint32_t source) {
+
+#if SAMA_HAL_IS_SECURE
+  Aic *aic = SAIC;
+#else
+  Aic *aic = AIC;
+#endif
+
+  aic->AIC_SSR = AIC_SSR_INTSEL(source);
+  aic->AIC_IECR = AIC_IECR_INTEN;
+}
+
+/**
+ * @brief   Disables interrupts coming from the selected source.
+ *
+ * @param[in] source    interrupt source to disable
+ */
+void aicDisableInt(uint32_t source) {
+
+#if SAMA_HAL_IS_SECURE
+  Aic *aic = SAIC;
+#else
+  Aic *aic = AIC;
+#endif
+
+  aic->AIC_SSR = AIC_SSR_INTSEL(source);
+  aic->AIC_IDCR = AIC_IDCR_INTD;
+}
+
+/**
+ * @brief   Clears interrupts coming from the selected source.
+ *
+ * @param[in] source    interrupt source to Clear
+ */
+void aicClearInt(uint32_t source) {
+
+#if SAMA_HAL_IS_SECURE
+  Aic *aic = SAIC;
+#else
+  Aic *aic = AIC;
+#endif
+
+  aic->AIC_SSR = AIC_SSR_INTSEL(source);
+  aic->AIC_ICCR = AIC_ICCR_INTCLR;
+}
+
+/**
+ * @brief   Sets interrupts coming from the selected source.
+ *
+ * @param[in] source    interrupt source to Set
+ */
+void aicSetInt(uint32_t source) {
+
+#if SAMA_HAL_IS_SECURE
+  Aic *aic = SAIC;
+#else
+  Aic *aic = AIC;
+#endif
+
+  aic->AIC_SSR = AIC_SSR_INTSEL(source);
+  aic->AIC_ISCR = AIC_ISCR_INTSET;
+}
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_aic.h b/os/hal/ports/SAMA/SAMA5D2x/sama_aic.h
new file mode 100644
index 000000000..a4f220754
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_aic.h
@@ -0,0 +1,114 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/aic.h
+ * @brief   SAMA AIC support macros and structures.
+ *
+ * @addtogroup SAMA5D2x_AIC
+ * @{
+ */
+
+#ifndef AIC_H
+#define AIC_H
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+/**
+ * @name    INTERRUPT SOURCE TYPE mode macros
+ * @{
+ */
+/**
+ * @brief   High-level sensitive for internal source.
+ *          Low-level sensitive for external source.
+ */
+#define INT_LEVEL_SENSITIVE                     0x0U
+
+/**
+ * @brief   Negative-edge triggered for external source.
+ */
+#define EXT_NEGATIVE_EDGE                       0x1U
+
+/**
+ * @brief   High-level sensitive for internal source.
+ *          High-level sensitive for external source.
+ */
+#define EXT_HIGH_LEVEL                          0x2U
+
+/**
+ * @brief   Positive-edge triggered for external source.
+ */
+#define EXT_POSITIVE_EDGE                       0x3U
+/** @} */
+
+/**
+ * @brief   AIC unique redirect key.
+ */
+#define AIC_REDIR_KEY                       0x5B6C0E26U
+
+/*===========================================================================*/
+/* Driver pre-compile time settings.                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks.                                       */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros.                                                            */
+/*===========================================================================*/
+
+/**
+ * @brief   Acknowledge the current interrupt.
+ */
+#if SAMA_HAL_IS_SECURE
+#define aicAckInt() {                                                     \
+  SAIC->AIC_EOICR = AIC_EOICR_ENDIT;                                      \
+}
+#else
+#define aicAckInt() {                                                     \
+  AIC->AIC_EOICR = AIC_EOICR_ENDIT;                                       \
+}
+#endif
+
+/*===========================================================================*/
+/* External declarations.                                                    */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void aicInit(void);
+  void aicSetSourcePriority(uint32_t source, uint8_t priority);
+  void aicSetIntSourceType(uint32_t source, uint8_t type);
+  void aicSetSourceHandler(uint32_t source, bool (*handler)(void));
+  void aicSetSpuriousHandler(bool (*handler)(void));
+  void aicEnableInt(uint32_t source);
+  void aicDisableInt(uint32_t source);
+  void aicClearInt(uint32_t source);
+  void aicSetInt(uint32_t source);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AIC_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_cache.c b/os/hal/ports/SAMA/SAMA5D2x/sama_cache.c
index ac08363ce..0ed58a887 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/sama_cache.c
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_cache.c
@@ -45,13 +45,13 @@ void cacheInvalidateRegion(void *start, uint32_t length) {
   uint32_t mva;
 
   /* Invalidate L1 D-Cache */
-  for (mva = start_addr & ~L1_CACHE_BYTES; mva < end_addr; mva += L1_CACHE_BYTES) {
+  for (mva = start_addr & ~(L1_CACHE_BYTES-1); mva < end_addr; mva += L1_CACHE_BYTES) {
     L1C_InvalidateDCacheMVA((uint32_t *)mva);
   }
 #if ARM_SUPPORTS_L2CC
 #if SAMA_L2CC_ASSUME_ENABLED || SAMA_L2CC_ENABLE
   /* Invalidate L2 Cache */
-  for (mva = start_addr & ~L2_CACHE_BYTES; mva < end_addr; mva += L2_CACHE_BYTES) {
+  for (mva = start_addr & ~(L2_CACHE_BYTES-1); mva < end_addr; mva += L2_CACHE_BYTES) {
     L2C_InvPa((uint32_t *)mva);
   }
 #endif
@@ -71,17 +71,43 @@ void cacheCleanRegion(void *start, uint32_t length) {
   uint32_t mva;
 
   /* Clean L1 D-Cache */
-  for (mva = start_addr & ~L1_CACHE_BYTES; mva < end_addr; mva += L1_CACHE_BYTES) {
+  for (mva = start_addr & ~(L1_CACHE_BYTES-1); mva < end_addr; mva += L1_CACHE_BYTES) {
     L1C_CleanDCacheMVA((uint32_t *)mva);
   }
 #if ARM_SUPPORTS_L2CC
 #if SAMA_L2CC_ASSUME_ENABLED || SAMA_L2CC_ENABLE
   /* Invalidate L2 Cache */
-  for (mva = start_addr & ~L2_CACHE_BYTES; mva < end_addr; mva += L2_CACHE_BYTES) {
+  for (mva = start_addr & ~(L2_CACHE_BYTES-1); mva < end_addr; mva += L2_CACHE_BYTES) {
     L2C_CleanPa((uint32_t *)mva);
   }
 #endif
 #endif
 }
 
+/**
+ * @brief   Clean and Invalidate D-Cache Region
+ *
+ * @param[in] start      Pointer to beginning of memory region.
+ * @param[in] length     Length of the memory location.
+ */
+void cacheCleanInvalidateRegion(void *start, uint32_t length) {
+
+  uint32_t start_addr = (uint32_t)start;
+  uint32_t end_addr = start_addr + length;
+  uint32_t mva;
+
+  /* Clean L1 D-Cache */
+  for (mva = start_addr & ~(L1_CACHE_BYTES-1); mva < end_addr; mva += L1_CACHE_BYTES) {
+    L1C_CleanInvalidateDCacheMVA((uint32_t *)mva);
+  }
+#if ARM_SUPPORTS_L2CC
+#if SAMA_L2CC_ASSUME_ENABLED || SAMA_L2CC_ENABLE
+  /* Invalidate L2 Cache */
+  for (mva = start_addr & ~(L2_CACHE_BYTES-1); mva < end_addr; mva += L2_CACHE_BYTES) {
+    L2C_CleanInvPa((uint32_t *)mva);
+  }
+#endif
+#endif
+}
+
 /** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_cache.h b/os/hal/ports/SAMA/SAMA5D2x/sama_cache.h
index 1608a023c..25be583ff 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/sama_cache.h
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_cache.h
@@ -30,11 +30,16 @@
 #define L1_CACHE_BYTES  32u
 #define L2_CACHE_BYTES  32u
 
+#define CACHE_ALIGNED   ALIGNED_VAR(L1_CACHE_BYTES)
+#define NO_CACHE        __attribute__((section (".nocache")))
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
   extern void cacheInvalidateRegion(void *start, uint32_t length);
   extern void cacheCleanRegion(void *start, uint32_t length);
+  extern void cacheCleanInvalidateRegion(void *start, uint32_t length);
 #ifdef __cplusplus
 }
 #endif
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_classd.c b/os/hal/ports/SAMA/SAMA5D2x/sama_classd.c
new file mode 100644
index 000000000..37a3ce689
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_classd.c
@@ -0,0 +1,526 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/sama_classd.c
+ * @brief   SAMA CLASSD support code.
+ *
+ * @addtogroup SAMA5D2x_CLASSD
+ * @{
+ */
+
+#include "hal.h"
+
+#if SAMA_USE_CLASSD || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local macros.                                                      */
+/*===========================================================================*/
+
+/**
+ * @brief   Enable write protection on CLASSD Mode Register
+ *          and Interpolator Mode Register.
+ *
+ * @param[in] classdp   pointer to a CLASSD register block
+ *
+ * @notapi
+ */
+#define classdEnableWP(classdp) {                                              \
+  classdp->CLASSD_WPMR = CLASSD_WPMR_WPKEY_PASSWD | CLASSD_WPMR_WPEN;          \
+}
+
+/**
+ * @brief   Disable write protection on CLASSD Mode Register
+ *          and Interpolator Mode Register.
+ *
+ * @param[in] classdp   pointer to a CLASSD register block
+ *
+ * @notapi
+ */
+#define classdDisableWP(classdp) {                                             \
+  classdp->CLASSD_WPMR = CLASSD_WPMR_WPKEY_PASSWD;                             \
+}
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+/**
+ * @brief   CLASSD driver identifier.
+ */
+CLASSDDriver CLASSDD0;
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+/**
+ * @brief   Type of a structure representing PMC Audio configuration.
+ */
+typedef struct {
+  /**
+   * @brief   Loop Divider Ratio.
+   */
+  uint32_t nd;
+
+  /**
+   * @brief   Fractional Loop Divider Setting.
+   */
+  uint32_t fracr;
+
+  /**
+   * @brief   Output Divider Ratio for PMC Clock.
+   */
+  uint32_t qdpmc;
+
+  /**
+   * @brief   Divider Value.
+   */
+  uint32_t div;
+
+  /**
+   * @brief   Output Divider Ratio for Pad Clock.
+   */
+  uint32_t qdaudio;
+} pmcAudioConf;
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+/**
+ * @brief   Configure DSPClock.
+ *
+ * @param[in] dsp_clk   DSP clock type (12.288 MHz or 11.2896 MHz).
+ */
+static void dspclkConfigure(uint32_t dsp_clk) {
+  pmcAudioConf cfg;
+
+  /* Pad Clock: not used */
+  cfg.div = 0;
+  cfg.qdaudio = 0;
+
+  /* PMC Clock: */
+  /* 12Mhz * (ND + 1 + FRACR/2^22) / (QDPMC + 1) = 8 * DSPCLK */
+  switch (dsp_clk) {
+    case CLASSD_INTPMR_DSPCLKFREQ_12M288:
+#if SAMA_MOSCXTCLK == 12000000
+      /* 12Mhz * (56 + 1 + 1442841/2^22) / (6 + 1) = 8 * 12.288Mhz */
+      cfg.nd = 56;
+      cfg.fracr = 1442841;
+      cfg.qdpmc = 6;
+#elif SAMA_MOSCXTCLK == 24000000
+      /* 24Mhz * (56 + 1 + 1442841/2^22) / (6 + 1) = 8 * 12.288Mhz */
+      cfg.nd = 27;
+      cfg.fracr = 2796203;
+      cfg.qdpmc = 6;
+#else
+      #error "FREQUENCY NOT SUPPORTED BY CLASSD"
+#endif
+    break;
+
+    case CLASSD_INTPMR_DSPCLKFREQ_11M2896:
+#if SAMA_MOSCXTCLK == 12000000
+      /* 12Mhz * (59 + 1 + 885837/2^22) / (7 + 1) = 8 * 11.2896Mhz */
+      cfg.nd = 59;
+      cfg.fracr = 885837;
+      cfg.qdpmc = 7;
+#elif SAMA_MOSCXTCLK == 24000000
+      /* 24Mhz * (59 + 1 + 885837/2^22) / (7 + 1) = 8 * 11.2896Mhz */
+      cfg.nd = 28;
+      cfg.fracr = 699050;
+      cfg.qdpmc = 7;
+#else
+      #error "FREQUENCY NOT SUPPORTED BY CLASSD"
+#endif
+    break;
+
+    default:
+      osalDbgAssert(NULL, "errore mask configuration");
+   }
+
+  /* Configure and enable the generic clock. */
+  pmcConfigAudio(cfg.nd, cfg.qdpmc, cfg.fracr, cfg.div, cfg.qdaudio);
+  pmcEnableAudio(true, false);
+}
+
+/**
+ * @brief   Shared end-of-tx service routine.
+ *
+ * @param[in] classdp   pointer to the @p CLASSDDriver object
+ * @param[in] flags     pre-shifted content of the ISR register
+ */
+static void classd_lld_serve_tx_interrupt(CLASSDDriver *classdp, uint32_t flags) {
+
+  /* DMA errors handling.*/
+#if defined(SAMA_CLASSD_DMA_ERROR_HOOK)
+  (void)classdp;
+  if ((flags & (XDMAC_CIS_WBEIS | XDMAC_CIS_ROIS)) != 0) {
+    SAMA_CLASSD_DMA_ERROR_HOOK(classdp);
+  }
+#else
+  (void)flags;
+#endif
+
+  if(classdp->config->callback != NULL) {
+    classdp->config->callback(classdp);
+  }
+  classdMuteChannel(classdp, false, false);
+  classdp->state = CLASSD_READY;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+/**
+ * @brief   Low level CLASSD driver initialization.
+ *
+ * @notapi
+ */
+void classd_lld_init(void) {
+#if SAMA_HAL_IS_SECURE
+  mtxConfigPeriphSecurity(MATRIX1, ID_CLASSD, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+  /* Driver initialization. */
+  classdObjectInit(&CLASSDD0);
+  CLASSDD0.classd = CLASSD;
+  CLASSDD0.dmatx     = NULL;
+  CLASSDD0.txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+                       XDMAC_CC_MBSIZE_SINGLE |
+                       XDMAC_CC_DSYNC_MEM2PER |
+                       XDMAC_CC_PROT_SEC |
+                       XDMAC_CC_CSIZE_CHK_1 |
+                       XDMAC_CC_DWIDTH_WORD |
+                       XDMAC_CC_SIF_AHB_IF0 |
+                       XDMAC_CC_DIF_AHB_IF1 |
+                       XDMAC_CC_SAM_INCREMENTED_AM |
+                       XDMAC_CC_DAM_FIXED_AM |
+                       XDMAC_CC_PERID(PERID_CLASSD_TX);
+}
+
+/**
+ * @brief   Configures and activates the CLASSD peripheral.
+ *
+ * @param[in] classdp   pointer to the @p CLASSDDriver object
+ *
+ * @notapi
+ */
+void classd_lld_start(CLASSDDriver *classdp) {
+
+  uint8_t i;
+  uint32_t dsp_clk_set, frame_set;
+
+ /* Configures the peripheral.*/
+  if (classdp->state == CLASSD_STOP) {
+
+    if (&CLASSDD0 == classdp) {
+      classdp->dmatx = dmaChannelAllocate(SAMA_CLASSD_DMA_IRQ_PRIORITY,
+                                       (sama_dmaisr_t)classd_lld_serve_tx_interrupt,
+                                       (void *)classdp);
+      osalDbgAssert(classdp->dmatx != NULL, "no channel allocated");
+    }
+  }
+
+ /* Set DMA channel mode. */
+  dmaChannelSetMode(classdp->dmatx, classdp->txdmamode);
+
+  /* Set CLASSD DSP clock and Sample rate. */
+  for(i = 0; i < 8; i++) {
+    if ((audio_info[i].rate) == (classdp->config->frame)) {
+      dsp_clk_set  = audio_info[i].dsp_clk;
+      frame_set = audio_info[i].sample_rate;
+      break;
+    }
+  }
+
+  /* Enable the CLASSD0 clock. */
+  pmcEnableCLASSD0();
+
+  /* Configure PMC Audio structure. */
+  dspclkConfigure(dsp_clk_set);
+
+  /* Disable the CLASSD generic clock for now. */
+  pmcDisableGclkCLASSD0();
+
+  /* Configure the CLASSD generic clock */
+  pmcConfigGclk(ID_CLASSD, PMC_PCR_GCKCSS_AUDIO_CLK, 1);
+
+  /* Disable write protection. */
+  classdDisableWP(classdp->classd);
+
+  /* Perform soft reset. */
+  CLASSD->CLASSD_CR  = CLASSD_CR_SWRST;
+  CLASSD->CLASSD_IDR = CLASSD_IDR_DATRDY;
+
+  /* Clean CLASSD Registers. */
+  classdp->classd->CLASSD_MR = 0;
+  classdp->classd->CLASSD_INTPMR = 0;
+
+  /* CLASSD configuration. */
+  classdp->classd->CLASSD_MR = classdp->config->left |
+                               classdp->config->right |
+                               classdp->config->left_mute |
+                               classdp->config->right_mute |
+                               classdp->config->pwm_mode |
+                               classdp->config->non_overlap |
+                               classdp->config->novrval;
+
+  classdp->classd->CLASSD_INTPMR = classdp->config->attl |
+                                   classdp->config->attr |
+                                   classdp->config->deemp |
+                                   classdp->config->swap |
+                                   classdp->config->eqcfg |
+                                   classdp->config->mono |
+                                   classdp->config->mono_mode |
+                                   dsp_clk_set | frame_set;
+
+  /* Enable CLASSD generic clock. */
+  pmcEnableGclkCLASSD0();
+
+  /* Enable write protection. */
+  classdEnableWP(classdp->classd);
+}
+
+/**
+ * @brief   Deactivates the CLASSD peripheral.
+ *
+ * @param[in] classdp   pointer to the @p CLASSDDriver object
+ *
+ * @notapi
+ */
+void classd_lld_stop(CLASSDDriver *classdp) {
+
+  /* Disable clocks. */
+  pmcDisableAudio();
+  pmcDisableGclkCLASSD0();
+  pmcDisableCLASSD0();
+
+  /* Disable write protection. */
+  classdDisableWP(classdp->classd);
+
+  /* Reset CLASSD. */
+  classdp->classd->CLASSD_INTPMR = 0;
+  classdp->classd->CLASSD_MR = 0;
+
+  /* Enable write protection. */
+  classdEnableWP(classdp->classd);
+
+  /* Release and disable DMA channel. */
+  dmaChannelRelease(classdp->dmatx);
+}
+
+/**
+ *
+ * @brief   Starts a CLASSD playback.
+ *
+ * @param[in] classdp   pointer to the @p CLASSDDriver
+ * @param[in] txbuf     the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void classd_lld_send_audio(CLASSDDriver *classdp, const void *txbuf) {
+
+  /* Get DMA transfert size. */
+  size_t n = ((struct wav_header *)txbuf)->subchunk2_size / 4;
+
+  osalDbgAssert(!((uint32_t) txbuf & (L1_CACHE_BYTES - 1)), "address not cache aligned");
+
+#if 0
+  osalDbgAssert(!(n & (L1_CACHE_BYTES - 1)), "size not multiple of cache line");
+#endif
+
+  /* L1 is enabled */
+  cacheCleanRegion((uint8_t *) txbuf, n);
+
+  /* Get source address. */
+  uint32_t addrSource = sizeof(struct wav_header);
+
+  /* Unmute left and right channel */
+  classdMuteChannel(classdp, false, false);
+
+  /* Writing channel */
+  dmaChannelSetSource(classdp->dmatx, txbuf + addrSource);
+  dmaChannelSetDestination(classdp->dmatx, &classdp->classd->CLASSD_THR);
+  dmaChannelSetTransactionSize(classdp->dmatx, n);
+
+  /* DMA start transfer. */
+  dmaChannelEnable(classdp->dmatx);
+}
+
+/**
+ * @brief   CLASSD mute/unmute channels.
+ *
+ * @param[in] classdp   pointer to the @p CLASSDDriver object
+ *
+ * @iclass
+ */
+void classd_mute_channel(CLASSDDriver *classdp, bool left, bool right) {
+
+  /* Disable write protection. */
+  classdDisableWP(classdp->classd);
+
+  /* Mute or unmute left channel. */
+  if (left)
+    classdp->classd->CLASSD_MR |= CLASSD_MR_LMUTE;
+  else
+    classdp->classd->CLASSD_MR &= ~CLASSD_MR_LMUTE;
+
+  /* Mute or unmute right channel. */
+  if (right)
+    classdp->classd->CLASSD_MR |= CLASSD_MR_RMUTE;
+  else
+    classdp->classd->CLASSD_MR &= ~CLASSD_MR_RMUTE;
+
+  /* Enable write protection. */
+  classdEnableWP(classdp->classd);
+}
+
+/**
+ *
+ * @brief   CLASSD Driver initialization.
+ *
+ * @init
+ */
+void classdInit(void) {
+
+  classd_lld_init();
+}
+
+/**
+ *
+ * @brief   Initializes the standard part of a @p CLASSDDriver structure.
+ *
+ * @param[out] classdp  pointer to a @p CLASSDDriver object
+ *
+ * @init
+ */
+void classdObjectInit(CLASSDDriver *classdp) {
+  classdp->state = CLASSD_STOP;
+  classdp->config = NULL;
+}
+
+/**
+ * @brief   Configures and activates the CLASSD peripheral.
+ *
+ * @param[in] classdp  pointer to a @p CLASSDDriver object
+ * @param[in] config   pointer to a @p CLASSDConfig object
+ *
+ * @api
+ */
+void classdStart(CLASSDDriver *classdp, const CLASSDConfig *config) {
+
+  osalDbgCheck((classdp != NULL) && (config != NULL));
+
+  osalSysLock();
+  osalDbgAssert((classdp->state == CLASSD_STOP) || (classdp->state == CLASSD_READY),
+                "invalid state");
+  classdp->config = config;
+  classd_lld_start(classdp);
+  classdp->state = CLASSD_READY;
+  osalSysUnlock();
+}
+
+/**
+ * @brief   Deactivates the CLASSD peripheral.
+ *
+ * @param[in] classdp   pointer to the @p CLASSDDriver object
+ *
+ * @api
+ */
+void classdStop(CLASSDDriver *classdp) {
+
+  osalDbgCheck(classdp != NULL);
+
+  osalSysLock();
+
+  osalDbgAssert((classdp->state == CLASSD_STOP) || (classdp->state == CLASSD_READY || (classdp->state == CLASSD_ACTIVE)),
+                "invalid state");
+
+  classd_lld_stop(classdp);
+  classdp->config = NULL;
+  classdp->state  = CLASSD_STOP;
+
+  osalSysUnlock();
+}
+
+/**
+ *
+ * @brief  Starts a CLASSD playback.
+ *
+ * @param[in] classdp   pointer to the @p CLASSDDriver
+ * @param[in] txbuf     the pointer to the transmit buffer
+ *
+ * @note    This function can be used only in syslock state. todo: control comment!
+ *
+ * @notapi
+ */
+void classdSendAudioI(CLASSDDriver *classdp, const void *txbuf) {
+
+  (classdp)->state = CLASSD_ACTIVE;
+  classd_lld_send_audio(classdp, txbuf);
+}
+
+/**
+ *
+ * @brief  Starts a CLASSD playback.
+ *
+ * @param[in] classdp   pointer to the @p CLASSDDriver
+ * @param[in] txbuf     the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void classdSendAudio(CLASSDDriver *classdp, const void *txbuf) {
+
+  osalSysLock();
+  osalDbgAssert(classdp->state == CLASSD_READY, "not ready");
+  classdSendAudioI(classdp, txbuf);
+  osalSysUnlock();
+}
+
+/**
+ *
+ * @brief  Set the sample frame from the structure of a wav file.
+ *
+ * @param[in] classdconfigp  pointer to the @p CLASSDConfig
+ * @param[in] music_file     pointer to the wav file
+ *
+ * @notapi
+ */
+void classdSetSampleFrame(CLASSDConfig *classdconfigp, uint8_t *music_file) {
+  classdconfigp->frame = ((struct wav_header*)music_file)->sample_rate;
+}
+
+/**
+ * @brief   Mute/unmute CLASSD channel.
+ *
+ * @param[in] classdp  pointer to the @p CLASSDDriver object
+ *
+ * @iclass
+ */
+void classdMuteChannel(CLASSDDriver *classdp, bool left, bool right) {
+  classd_mute_channel(classdp, left, right);
+}
+
+#endif /* SAMA_USE_CLASSD */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_classd.h b/os/hal/ports/SAMA/SAMA5D2x/sama_classd.h
new file mode 100644
index 000000000..212e4fab6
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_classd.h
@@ -0,0 +1,301 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/sama_classd.h
+ * @brief   SAMA CLASSD support macros and structures.
+ *
+ * @addtogroup SAMA5D2x_CLASSD
+ * @{
+ */
+
+#ifndef SAMA_CLASSD_LLD_H
+#define SAMA_CLASSD_LLD_H
+
+/**
+ * @brief   Using the CLASSD driver.
+ */
+#if !defined(SAMA_USE_CLASSD) || defined(__DOXYGEN__)
+#define SAMA_USE_CLASSD                          FALSE
+#endif
+
+#if SAMA_USE_CLASSD || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings.                                         */
+/*===========================================================================*/
+
+/**
+ * @name    Configuration options
+ * @{
+ */
+
+/**
+ * @brief   CLASSD DMA interrupt priority level setting.
+ */
+#if !defined(SAMA_CLASSD_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SAMA_CLASSD_DMA_IRQ_PRIORITY               4
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks.                                       */
+/*===========================================================================*/
+
+#if !defined(SAMA_DMA_REQUIRED)
+#define SAMA_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+
+/**
+ * @brief   Driver state machine possible states.
+ */
+typedef enum {
+  CLASSD_UNINIT = 0,                /**< Not initialized.                   */
+  CLASSD_STOP = 1,                  /**< Stopped.                           */
+  CLASSD_READY = 2,                 /**< Ready.                             */
+  CLASSD_ACTIVE = 3,                /**< Exchanging data.                   */
+} classdstate_t;
+
+/**
+ * @brief   Structure representing audio info.
+ */
+static const struct {
+  /**
+   * @brief   Contains the value of the Sample Rate.
+   */
+  uint32_t rate;
+  /**
+   * @brief   Contains a mask of the Sample Rate.
+   */
+  uint32_t sample_rate;
+  /**
+   * @brief   Contains a mask of the DSP Clock.
+   */
+  uint32_t dsp_clk;
+} audio_info[] = {
+    {8000,  CLASSD_INTPMR_FRAME_FRAME_8K, CLASSD_INTPMR_DSPCLKFREQ_12M288},
+    {16000, CLASSD_INTPMR_FRAME_FRAME_16K, CLASSD_INTPMR_DSPCLKFREQ_12M288},
+    {32000, CLASSD_INTPMR_FRAME_FRAME_32K, CLASSD_INTPMR_DSPCLKFREQ_12M288},
+    {48000, CLASSD_INTPMR_FRAME_FRAME_48K, CLASSD_INTPMR_DSPCLKFREQ_12M288},
+    {96000, CLASSD_INTPMR_FRAME_FRAME_96K, CLASSD_INTPMR_DSPCLKFREQ_12M288},
+    {22050, CLASSD_INTPMR_FRAME_FRAME_22K, CLASSD_INTPMR_DSPCLKFREQ_11M2896},
+    {44100, CLASSD_INTPMR_FRAME_FRAME_44K, CLASSD_INTPMR_DSPCLKFREQ_11M2896},
+    {88200, CLASSD_INTPMR_FRAME_FRAME_88K, CLASSD_INTPMR_DSPCLKFREQ_11M2896},
+};
+
+/**
+ * @brief   Type of a structure representing Standard WAV file header information.
+ */
+struct wav_header {
+  /**
+   * @brief   Contains the letters "RIFF" in ASCII form.
+   */
+  uint32_t                  chunk_id;
+  /**
+   * @brief   Size of the rest of the chunk following this number.
+   */
+  uint32_t                  chunk_size;
+  /**
+   * @brief   Contains the letters "WAVE".
+   */
+  uint32_t                  format;
+  /**
+   * @brief   Contains the letters "fmt ".
+   */
+  uint32_t                  subchunk1_id;
+  /**
+   * @brief   16 for PCM.  This is the size of the rest of the Subchunk which follows this number.
+   */
+  uint32_t                  subchunk1_size;
+  /**
+   * @brief   PCM = 1 (i.e. Linear quantization). Values other than 1 indicate some form of compression.
+   */
+  uint16_t                  audio_format;
+  /**
+   * @brief   Mono = 1, Stereo = 2, etc.
+   */
+  uint16_t                  num_channels;
+  /**
+   * @brief   8000, 44100, etc.
+   */
+  uint32_t                  sample_rate;
+  /**
+   * @brief   SampleRate * NumChannels * BitsPerSample/8
+   */
+  uint32_t                  byte_rate;
+  /**
+   * @brief   NumChannels * BitsPerSample/8
+   */
+  uint16_t                  block_align;
+  /**
+   * @brief   8 bits = 8, 16 bits = 16, etc.
+   */
+  uint16_t                  bits_per_sample;
+  /**
+   * @brief   Contains the letters "data".
+   */
+  uint32_t                  subchunk2_id;
+  /**
+   * @brief   Number of bytes in the data.
+   */
+  uint32_t                  subchunk2_size;
+};
+
+/**
+ * @brief   Type of a structure representing an CLASSD driver.
+ */
+typedef struct CLASSDDriver CLASSDDriver;
+
+/**
+  * @brief   Type of a generic CLASSD callback.
+  */
+typedef void (*classdcb_t)(CLASSDDriver *classdp);
+
+/**
+ * @brief   Driver configuration structure.
+ * @note    It could be empty on some architectures.
+ */
+typedef struct {
+  /**
+   * @brief   Callback pointer.
+   */
+  classdcb_t                callback;
+  /**
+   * @brief   Configuration of the CLASSD left channel.
+   */
+  uint32_t                  left;
+  /**
+   * @brief   Configuration of the CLASSD right channel.
+   */
+  uint32_t                  right;
+  /**
+   * @brief   Configuration of the CLASSD left channel mute.
+   */
+  uint32_t                  left_mute;
+  /**
+   * @brief   Configuration of the CLASSD right channel mute.
+   */
+  uint32_t                  right_mute;
+  /**
+   * @brief   Configuration of the CLASSD PWM modulation type.
+   */
+  uint32_t                  pwm_mode;
+  /**
+   * @brief   Configuration of the CLASSD Non-Overlapping.
+   */
+  uint32_t                  non_overlap;
+  /**
+   * @brief   Configuration of the CLASSD Non-Overlapping value.
+   */
+  uint32_t                  novrval;
+  /**
+   * @brief   Configuration of the CLASSD left channel attenuation.
+   */
+  uint32_t                  attl;
+  /**
+   * @brief   Configuration of the CLASSD right channel attenuation.
+   */
+  uint32_t                  attr;
+  /**
+   * @brief   Configuration of the CLASSD de-emphasis filter.
+   */
+  uint32_t                  deemp;
+  /**
+   * @brief   Configuration of the CLASSD swap left right channel.
+   */
+  uint32_t                  swap;
+  /**
+   * @brief   Configuration of the CLASSD sample frequency.
+   */
+  uint32_t                  frame;
+  /**
+   * @brief   Configuration of the CLASSD EQ config.
+   */
+  uint32_t                  eqcfg;
+  /**
+   * @brief   Configuration of the CLASSD mono signal.
+   */
+  uint32_t                  mono;
+  /**
+   * @brief   Configuration of the CLASSD mono mode.
+   */
+  uint32_t                  mono_mode;
+} CLASSDConfig;
+
+/**
+ * @brief   Structure representing an CLASSD driver.
+ */
+struct CLASSDDriver {
+  /**
+   * @brief   Driver state.
+   */
+  classdstate_t             state;
+  /**
+   * @brief   Current configuration data.
+   */
+  const CLASSDConfig        *config;
+  /**
+   * @brief   Pointer to the WDT registers block.
+   */
+  Classd                    *classd;
+  /**
+   * @brief   Transmit DMA stream.
+   */
+  sama_dma_channel_t        *dmatx;
+  /**
+   * @brief   TX DMA mode bit mask.
+   */
+  uint32_t                  txdmamode;
+};
+
+/*===========================================================================*/
+/* Driver macros.                                                            */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations.                                                    */
+/*===========================================================================*/
+extern CLASSDDriver CLASSDD0;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void classdInit(void);
+  void classdObjectInit(CLASSDDriver *classdp);
+  void classdStart(CLASSDDriver *classdp, const CLASSDConfig *config);
+  void classdStop(CLASSDDriver *classdp);
+  void classdSetSampleFrame(CLASSDConfig *classdconfigp, uint8_t *music_file);
+  void classdSendAudioI(CLASSDDriver *classdp, const void *txbuf);
+  void classdSendAudio(CLASSDDriver *classdp, const void *txbuf);
+  void classdMuteChannel(CLASSDDriver *classdp, bool left, bool right);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SAMA_USE_CLASSD */
+
+#endif /* SAMA_CLASSD_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.c b/os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.c
new file mode 100644
index 000000000..761c5b66b
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.c
@@ -0,0 +1,955 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/sama_lcdc.c
+ * @brief   SAMA LCDC support code.
+ *
+ * @addtogroup SAMA5D2x_LCDC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (SAMA_USE_LCDC) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+/*
+ * @brief    NO CACHE attribute
+ */
+#if !defined(NO_CACHE)
+#define NO_CACHE                        __attribute__((section (".nocache")))
+#endif
+/*===========================================================================*/
+/* Driver local macros.                                                      */
+/*===========================================================================*/
+/*
+ * @name    Configuration Macros
+ * @{
+ */
+/*
+ * @brief    Transfer Descriptor Fetch Enable
+ */
+#define LCDC_CTRL_DFETCH                (0x1u << 0)
+/*
+ * @brief    Channel Enable Register
+ */
+#define LCDC_CHER_CHEN                  (0x1u << 0)
+/*
+ * @brief    Channel Disable Register
+ */
+#define LCDC_CHDR_CHDIS                 (0x1u << 0)
+/*
+ * @brief    Update Overlay Attributes Enable Register
+ */
+#define LCDC_CHER_UPDATEEN              (0x1u << 1)
+/*
+ * @brief    Blender DMA Layer Enable
+ */
+#define LCDC_CFG_DMA                    (0x1u << 8)
+/*
+ * @brief    Blender Overlay Layer Enable
+ */
+#define LCDC_CFG_OVR                    (0x1u << 7)
+/*
+ * @brief    Pixel Stride
+ */
+#define LCDC_CFG_PSTRIDE_Pos            0
+#define LCDC_CFG_PSTRIDE_Msk            (0xffffffffu << LCDC_CFG_PSTRIDE_Pos)
+#define LCDC_CFG_PSTRIDE(value)         ((LCDC_CFG_PSTRIDE_Msk & ((value) << \
+                                                      LCDC_CFG_PSTRIDE_Pos)))
+/*
+ * @brief    Horizontal Stride
+ */
+#define LCDC_CFG_XSTRIDE_Pos            0
+#define LCDC_CFG_XSTRIDE_Msk            (0xffffffffu << LCDC_CFG_XSTRIDE_Pos)
+#define LCDC_CFG_XSTRIDE(value)         ((LCDC_CFG_XSTRIDE_Msk & ((value) << \
+                                                      LCDC_CFG_XSTRIDE_Pos)))
+/*
+ * @brief    Hardware Rotation Optimization Disable
+ */
+#define LCDC_CFG_ROTDIS                 (0x1u << 12)
+
+/*
+ * @brief    Horizontal Window Position
+ */
+#define LCDC_CFG_XPOS_Pos 0
+#define LCDC_CFG_XPOS_Msk (0x7ffu << LCDC_CFG_XPOS_Pos)
+#define LCDC_CFG_XPOS(value) ((LCDC_CFG_XPOS_Msk & ((value) << LCDC_CFG_XPOS_Pos)))
+
+/*
+ * @brief    Vertical Window Position
+ */
+#define LCDC_CFG_YPOS_Pos 16
+#define LCDC_CFG_YPOS_Msk (0x7ffu << LCDC_CFG_YPOS_Pos)
+#define LCDC_CFG_YPOS(value) ((LCDC_CFG_YPOS_Msk & ((value) << LCDC_CFG_YPOS_Pos)))
+
+/*
+ * @brief    Horizontal Window Size
+ */
+#define LCDC_CFG_XSIZE_Pos 0
+#define LCDC_CFG_XSIZE_Msk (0x7ffu << LCDC_CFG_XSIZE_Pos)
+#define LCDC_CFG_XSIZE(value) ((LCDC_CFG_XSIZE_Msk & ((value) << LCDC_CFG_XSIZE_Pos)))
+
+/*
+ * @brief    Vertical Window Size
+ */
+#define LCDC_CFG_YSIZE_Pos 16
+#define LCDC_CFG_YSIZE_Msk (0x7ffu << LCDC_CFG_YSIZE_Pos)
+#define LCDC_CFG_YSIZE(value) ((LCDC_CFG_YSIZE_Msk & ((value) << LCDC_CFG_YSIZE_Pos)))
+
+/*
+ * @brief    Horizontal image Size in Memory
+ */
+#define LCDC_CFG_XMEMSIZE_Pos 0
+#define LCDC_CFG_XMEMSIZE_Msk (0x7ffu << LCDC_CFG_XMEMSIZE_Pos)
+#define LCDC_CFG_XMEMSIZE(value) ((LCDC_CFG_XMEMSIZE_Msk & ((value) << LCDC_CFG_XMEMSIZE_Pos)))
+
+/*
+ * @brief    Vertical image Size in Memory
+ */
+#define LCDC_CFG_YMEMSIZE_Pos 16
+#define LCDC_CFG_YMEMSIZE_Msk (0x7ffu << LCDC_CFG_YMEMSIZE_Pos)
+#define LCDC_CFG_YMEMSIZE(value) ((LCDC_CFG_YMEMSIZE_Msk & ((value) << LCDC_CFG_YMEMSIZE_Pos)))
+
+/** @} */
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+LCDCDriver LCDCD0;
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+/**
+ * @brief   DMA Channel Descriptor.
+ */
+typedef struct {
+  /**
+   * @brief   Frame Buffer base address register.
+   */
+  uint32_t                  addr;
+  /**
+   * @brief   Transfer Control register.
+   */
+  uint32_t                  ctrl;
+  /**
+   * @brief   Next Descriptor Address register.
+   */
+  uint32_t                  next;
+} lcdc_dma_descriptor_t;
+
+/* Variable layer data */
+typedef struct {
+  lcdc_dma_descriptor_t *dma_desc;
+  lcdc_dma_descriptor_t *dma_u_desc;
+  lcdc_dma_descriptor_t *dma_v_desc;
+  void                  *buffer;
+  uint8_t                bpp;
+  uint8_t                num_colors;
+} layerdata_t;
+
+/*
+ * @brief  Hardware info about the layers
+ */
+typedef struct {
+  layerdata_t        *data;
+  bool                stride_supported;
+  /* regs: _ER, _DR, _SR, _IER, _IDR, _IMR, _ISR */
+  volatile uint32_t  *reg_enable;
+  /* regs: blender */
+  volatile uint32_t  *reg_blender;
+  /* _HEAD, _ADDRESS, _CONTROL, _NEXT */
+  volatile uint32_t  *reg_dma_head;
+  /* _HEAD, _ADDRESS, _CONTROL, _NEXT */
+  volatile uint32_t  *reg_dma_u_head;
+  /* _HEAD, _ADDRESS, _CONTROL, _NEXT */
+  volatile uint32_t  *reg_dma_v_head;
+  /* regs: _CFG0, _CFG1 (RGB mode...) */
+  volatile uint32_t  *reg_cfg;
+  /* X Y register, W H register */
+  volatile uint32_t  *reg_win;
+  /* regs: stride */
+  volatile uint32_t  *reg_stride;
+  /* regs: RGB Default, RGB Key, RGB Mask */
+  volatile uint32_t  *reg_color;
+  /* regs: scale */
+  volatile uint32_t  *reg_scale;
+  /* regs: CLUT */
+  volatile uint32_t  *reg_clut;
+} layerinfo_t;
+
+/* Base Layer */
+static layerdata_t lcdd_base;
+/* OVR1 Layer */
+static layerdata_t lcdd_ovr1;
+/* OVR2 Layer */
+static layerdata_t lcdd_ovr2;
+/* HEO Layer */
+static layerdata_t lcdd_heo;
+/* HCC Layer */
+static layerdata_t lcdd_hcc;
+
+/*
+ * @brief    DMA descriptor
+ * @note The DMA Channel Descriptor (DSCR) must be aligned on a 64-bit boundary.
+ */
+ALIGNED_VAR(8)
+/* DMA descriptor for Base Layer */
+NO_CACHE static lcdc_dma_descriptor_t base_dma_desc;
+
+ALIGNED_VAR(8)
+/* DMA descriptor for OVR1 Layer */
+NO_CACHE static lcdc_dma_descriptor_t ovr1_dma_desc;
+
+ALIGNED_VAR(8)
+/* DMA descriptor for OVR2 Layer */
+NO_CACHE static lcdc_dma_descriptor_t ovr2_dma_desc;
+
+ALIGNED_VAR(8)
+/* DMA descriptor for HEO Layer */
+NO_CACHE static lcdc_dma_descriptor_t heo_dma_desc;
+ALIGNED_VAR(8)
+/* DMA descriptor for HEO U-UV Layer */
+NO_CACHE static lcdc_dma_descriptor_t heo_dma_u_desc;
+ALIGNED_VAR(8)
+/* DMA descriptor for HEO V Layer */
+NO_CACHE static lcdc_dma_descriptor_t heo_dma_v_desc;
+
+ALIGNED_VAR(8)
+/* DMA descriptor for HCC Layer */
+NO_CACHE static lcdc_dma_descriptor_t hcc_dma_desc;
+
+/**
+ * @brief  Information about layers
+ */
+static const layerinfo_t lcdd_layers[] = {
+  /* 0: LCDD_CONTROLLER */
+  {
+    .stride_supported = false,
+    .reg_enable = &LCDC->LCDC_LCDEN,
+  },
+
+  /* 1: LCDD_BASE */
+  {
+    .data = &lcdd_base,
+    .stride_supported = false,
+    .reg_enable = &LCDC->LCDC_BASECHER,
+    .reg_blender = &LCDC->LCDC_BASECFG4,
+    .reg_dma_head = &LCDC->LCDC_BASEHEAD,
+    .reg_cfg = &LCDC->LCDC_BASECFG0,
+    .reg_stride = &LCDC->LCDC_BASECFG2,
+    .reg_color = &LCDC->LCDC_BASECFG3,
+    .reg_clut = &LCDC->LCDC_BASECLUT[0]
+  },
+
+  /* 2: LCDD_OVR1 */
+  {
+    .data = &lcdd_ovr1,
+    .stride_supported = true,
+    .reg_enable = &LCDC->LCDC_OVR1CHER,
+    .reg_blender = &LCDC->LCDC_OVR1CFG9,
+    .reg_dma_head = &LCDC->LCDC_OVR1HEAD,
+    .reg_cfg = &LCDC->LCDC_OVR1CFG0,
+    .reg_win = &LCDC->LCDC_OVR1CFG2,
+    .reg_stride = &LCDC->LCDC_OVR1CFG4,
+    .reg_color = &LCDC->LCDC_OVR1CFG6,
+    .reg_clut = &LCDC->LCDC_OVR1CLUT[0],
+  },
+
+  /* 3: LCDD_HEO */
+  {
+    .data = &lcdd_heo,
+    .stride_supported = true,
+    .reg_enable = &LCDC->LCDC_HEOCHER,
+    .reg_blender = &LCDC->LCDC_HEOCFG12,
+    .reg_dma_head = &LCDC->LCDC_HEOHEAD,
+    .reg_dma_u_head = &LCDC->LCDC_HEOUHEAD,
+    .reg_dma_v_head = &LCDC->LCDC_HEOVHEAD,
+    .reg_cfg = &LCDC->LCDC_HEOCFG0,
+    .reg_win = &LCDC->LCDC_HEOCFG2,
+    .reg_stride = &LCDC->LCDC_HEOCFG5,
+    .reg_color = &LCDC->LCDC_HEOCFG9,
+    .reg_scale = &LCDC->LCDC_HEOCFG13,
+    .reg_clut = &LCDC->LCDC_HEOCLUT[0],
+  },
+
+  /* 4: LCDD_OVR2 */
+  {
+    .data = &lcdd_ovr2,
+    .stride_supported = true,
+    .reg_enable = &LCDC->LCDC_OVR2CHER,
+    .reg_blender = &LCDC->LCDC_OVR2CFG9,
+    .reg_dma_head = &LCDC->LCDC_OVR2HEAD,
+    .reg_cfg = &LCDC->LCDC_OVR2CFG0,
+    .reg_win = &LCDC->LCDC_OVR2CFG2,
+    .reg_stride = &LCDC->LCDC_OVR2CFG4,
+    .reg_color = &LCDC->LCDC_OVR2CFG6,
+    .reg_clut = &LCDC->LCDC_OVR2CLUT[0],
+  }
+  ,
+  /* 5: N/A */
+  {
+    .data = NULL,
+  },
+
+  /* 6: LCDD_CUR */
+  {
+    .data = &lcdd_hcc,
+    .stride_supported = false,
+  },
+};
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+/*
+ * @brief    Clear DMA channel descriptor
+ *
+ * @param[in] descp    pointer to lcdc_dma_descriptor
+ * @param[in] dma_regp pointer to LCDC leyer register
+ *
+ * @notapi
+ */
+static void clear_dma_desc(lcdc_dma_descriptor_t *descp, volatile uint32_t *dma_regp) {
+  /* Modify descriptor */
+  if (descp) {
+    descp->ctrl &= ~LCDC_CTRL_DFETCH;
+    descp->next = (uint32_t)descp;
+    //cacheCleanRegion(descp, sizeof(lcdc_dma_descriptor_t));
+  }
+
+  /* Modify registers */
+  dma_regp[2] &= ~LCDC_CTRL_DFETCH;
+  dma_regp[3] = (uint32_t)descp;
+}
+
+/**
+ * @brief   Computing scaling factor.
+ *
+ * @param[in] layerp      pointer to a layerinfo_t struct
+ * @param[out] xfactorp   pointer to xfactor scaling factor
+ * @param[out] yfactorp   pointer to yfactor scaling factor
+ *
+ * @notapi
+ */
+static void compute_scaling_factors(const layerinfo_t *layerp,
+    uint16_t* xfactorp, uint16_t* yfactorp)
+{
+  uint16_t xmemsize, ymemsize;
+  uint16_t xsize, ysize;
+
+#ifdef LCDC_HEOCFG41_XPHIDEF
+  uint16_t xfactor_1st, yfactor_1st;
+#endif
+
+  xmemsize = (layerp->reg_win[2] & LCDC_CFG_XMEMSIZE_Msk) >> LCDC_CFG_XMEMSIZE_Pos;
+  ymemsize = (layerp->reg_win[2] & LCDC_CFG_YMEMSIZE_Msk) >> LCDC_CFG_YMEMSIZE_Pos;
+  xsize = (layerp->reg_win[1] & LCDC_CFG_XSIZE_Msk) >> LCDC_CFG_XSIZE_Pos;
+  ysize = (layerp->reg_win[1] & LCDC_CFG_YSIZE_Msk) >> LCDC_CFG_YSIZE_Pos;
+
+#ifdef LCDC_HEOCFG41_XPHIDEF
+  /* we assume that XPHIDEF & YPHIDEF are 0 */
+  xfactor_1st = (2048 * xmemsize / xsize) + 1;
+  yfactor_1st = (2048 * ymemsize / ysize) + 1;
+
+  if ((xfactor_1st * xsize / 2048) > xmemsize)
+    *xfactorp = xfactor_1st - 1;
+  else
+    *xfactorp = xfactor_1st;
+
+  if ((yfactor_1st * ysize / 2048) > ymemsize)
+    *yfactorp = yfactor_1st - 1;
+  else
+    *yfactorp = yfactor_1st;
+#else
+  *xfactorp = 1024 * (xmemsize + 1) / (xsize + 1);
+  *yfactorp = 1024 * (ymemsize + 1) / (ysize + 1);
+#endif
+}
+
+/**
+ * @brief   Configures LCDC layers according to configuration struct.
+ *
+ * @param[in] listp     pointer to a LCDCLayerConfig array
+ * @param[in] length    length of array
+ *
+ * @notapi
+ */
+void layer_config(LCDCLayerConfig *listp, size_t length) {
+  uint8_t i;
+  uint8_t bpp_bit;
+  uint8_t bpp;
+  uint32_t index;
+
+  uint32_t padding = 0;
+  uint32_t src_w, src_h, img_w, img_h;
+  uint32_t bits_per_row, bytes_per_row;
+
+  LCDCLayerConfig *layerp;
+
+  for (i = 0; i < length; i++) {
+    index = listp[i].layer_id;
+
+    osalDbgAssert((index != LCDD_CONTROLLER) || (index != LCDD_CUR), "This is not a real layer");
+
+    layerp = &listp[i];
+    uint16_t w, h, x, y;
+
+    bpp = layerp->bpp;
+    w = layerp->width;
+    h = layerp->height;
+    x = layerp->x_pos;
+    y = layerp->y_pos;
+    img_w = layerp->w_img;
+    img_h = layerp->h_img;
+
+    /* Bpp settings */
+    lcdd_layers[index].reg_cfg[1] = layerp->bpp;
+    bpp = bpp >> 4;
+
+    if (bpp == 1 || bpp < 5) {
+      bpp_bit = 16;
+    }
+    else if (bpp == 5 || bpp == 6) {
+      bpp_bit = 18;
+    }
+    else if (bpp == 7 || bpp == 8) {
+      bpp_bit = 19;
+    }
+    else if (bpp == 9 || bpp == 10) {
+      bpp_bit = 24;
+    }
+    else if (bpp == 11) {
+      bpp_bit = 25;
+    }
+    else if (bpp == 12 || bpp == 13) {
+      bpp_bit = 32;
+    }
+    else {
+      bpp_bit = 12;
+    }
+
+    /* Set display buffer & mode */
+    bits_per_row = img_w * bpp_bit;
+    bytes_per_row = bits_per_row >> 3;
+
+    if (bits_per_row & 0x7) {
+      bytes_per_row++;
+    }
+    if (bytes_per_row & 0x3) {
+      padding = 4 - (bytes_per_row & 0x3);
+    }
+    /* No rotation optimization */
+    lcdd_layers[index].reg_cfg[0] |= LCDC_CFG_ROTDIS;
+
+    /* Configure PSTRIDE if supported */
+    if (lcdd_layers[index].stride_supported)
+      lcdd_layers[index].reg_stride[1] = LCDC_CFG_PSTRIDE(0);
+    /* Configure XSTRIDE if supported */
+    lcdd_layers[index].reg_stride[0] = LCDC_CFG_XSTRIDE(padding);
+
+    /* Set window & position */
+    if (lcdd_layers[index].reg_win) {
+
+      /* Re - calculate to eliminate hardware overflow */
+      if (x + w > LCDCD0.config->width) {
+        w = LCDCD0.config->width - x;
+      }
+      if (y + h > LCDCD0.config->height) {
+        h = LCDCD0.config->height - y;
+      }
+
+      if (w == 0)
+        w++;
+
+      if (h == 0)
+        h++;
+
+      lcdd_layers[index].reg_win[0] = LCDC_CFG_XPOS(x) | LCDC_CFG_YPOS(y);
+      lcdd_layers[index].reg_win[1] = LCDC_CFG_XSIZE(w - 1) | LCDC_CFG_YSIZE(h - 1);
+    }
+
+    /* Scaling setup, only HEO layer has scaling register */
+    if (lcdd_layers[index].reg_win && lcdd_layers[index].reg_scale) {
+      src_w = img_w;
+      src_h = img_h;
+
+      lcdd_layers[index].reg_win[2] = LCDC_CFG_XMEMSIZE(src_w - 1) |
+                                       LCDC_CFG_YMEMSIZE(src_h - 1);
+      /* Scaled */
+      if (w != src_w || h != src_h) {
+        uint16_t scale_w, scale_h;
+        compute_scaling_factors(&lcdd_layers[index], &scale_w, &scale_h);
+        lcdd_layers[index].reg_scale[0] = LCDC_HEOCFG13_YFACTOR(scale_h) |
+                                           LCDC_HEOCFG13_XFACTOR(scale_w) |
+                                           LCDC_HEOCFG13_SCALEN;
+      }
+      /* Disable scaling */
+      else {
+        lcdd_layers[index].reg_scale[0] = 0;
+      }
+    }
+
+    /* Configure Descriptor */
+    lcdd_layers[index].data->dma_desc->addr = (uint32_t)layerp->buffer;
+    lcdd_layers[index].data->dma_desc->ctrl = LCDC_CTRL_DFETCH;
+    lcdd_layers[index].data->dma_desc->next = (uint32_t)lcdd_layers[index].data->dma_desc;
+
+    lcdd_layers[index].reg_dma_head[1] = (uint32_t)lcdd_layers[index].data->dma_desc->addr;
+    lcdd_layers[index].reg_dma_head[2] = LCDC_CTRL_DFETCH;
+    lcdd_layers[index].reg_dma_head[3] = (uint32_t)lcdd_layers[index].data->dma_desc;
+
+    /* Configure layer */
+    lcdd_layers[index].reg_enable[0] = LCDC_CHER_UPDATEEN;
+    lcdd_layers[index].reg_blender[0] |= LCDC_CFG_DMA | LCDC_CFG_OVR;
+  }
+}
+
+/**
+ * @brief   Enable Display.
+ *
+ * @param[in] lcdcp     pointer to the @p LCDCDriver object
+ */
+static void lcdc_on(LCDCDriver *lcdcp) {
+
+  uint32_t pixel_clock = lcdcp->config->framerate;
+  pixel_clock *= lcdcp->config->timing_hpw + lcdcp->config->timing_hbp +
+                 lcdcp->config->width + lcdcp->config->timing_hfp;
+  pixel_clock *= lcdcp->config->timing_vpw + lcdcp->config->timing_vbp +
+                 lcdcp->config->height + lcdcp->config->timing_vfp;
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+  /* Configure LCD timing parameters, signal polarity and clock period. */
+  if( LCDC->LCDC_LCDCFG0 & LCDC_LCDCFG0_CLKSEL) {
+    LCDC->LCDC_LCDCFG0 = LCDC_LCDCFG0_CLKDIV((SAMA_MCK * 2) / pixel_clock - 2) |
+                         LCDC_LCDCFG0_CGDISHEO | LCDC_LCDCFG0_CGDISOVR1 |
+                         LCDC_LCDCFG0_CGDISOVR2 | LCDC_LCDCFG0_CGDISBASE |
+                         LCDC_LCDCFG0_CLKPWMSEL | LCDC_LCDCFG0_CLKSEL;
+  }
+  else {
+    LCDC->LCDC_LCDCFG0 = LCDC_LCDCFG0_CLKDIV(SAMA_MCK / pixel_clock - 2) |
+                         LCDC_LCDCFG0_CGDISBASE | LCDC_LCDCFG0_CGDISHEO |
+                         LCDC_LCDCFG0_CLKPWMSEL;
+  }
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+  LCDC->LCDC_LCDCFG1 = LCDC_LCDCFG1_VSPW(lcdcp->config->timing_vpw - 1) |
+                       LCDC_LCDCFG1_HSPW(lcdcp->config->timing_hpw - 1);
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+  LCDC->LCDC_LCDCFG2 = LCDC_LCDCFG2_VBPW(lcdcp->config->timing_vbp) |
+                       LCDC_LCDCFG2_VFPW(lcdcp->config->timing_vfp - 1);
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+  LCDC->LCDC_LCDCFG3 = LCDC_LCDCFG3_HBPW(lcdcp->config->timing_hbp - 1) |
+                       LCDC_LCDCFG3_HFPW(lcdcp->config->timing_hfp - 1);
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+  LCDC->LCDC_LCDCFG4 = LCDC_LCDCFG4_RPF(lcdcp->config->height - 1) |
+                       LCDC_LCDCFG4_PPL(lcdcp->config->width - 1);
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+  LCDC->LCDC_LCDCFG5 = LCDC_LCDCFG5_GUARDTIME(30) | LCDC_LCDCFG5_MODE_OUTPUT_24BPP |
+                       LCDC_LCDCFG5_DISPDLY | LCDC_LCDCFG5_VSPDLYS | LCDC_LCDCFG5_VSPOL |
+                       LCDC_LCDCFG5_HSPOL;
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+  LCDC->LCDC_LCDCFG6 = LCDC_LCDCFG6_PWMCVAL(0xF0) | LCDC_LCDCFG6_PWMPOL |
+                       LCDC_LCDCFG6_PWMPS(6);
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+
+  /* Enable the Pixel Clock. */
+  LCDC->LCDC_LCDEN = LCDC_LCDEN_CLKEN;
+
+  /* Poll to check that clock is running. */
+  while (!(LCDC->LCDC_LCDSR & LCDC_LCDSR_CLKSTS));
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+  /* Enable Horizontal and Vertical Synchronization. */
+  LCDC->LCDC_LCDEN = LCDC_LCDEN_SYNCEN;
+  /* Poll to check that the synchronization is up. */
+  while (!(LCDC->LCDC_LCDSR & LCDC_LCDSR_LCDSTS));
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+  /* Enable the display power signal. */
+  LCDC->LCDC_LCDEN = LCDC_LCDEN_DISPEN;
+  /* Poll to check that the power signal is activated. */
+  while (!(LCDC->LCDC_LCDSR & LCDC_LCDSR_DISPSTS));
+
+  /* Wait for clock domain synchronization to be complete. */
+  while ((LCDC->LCDC_LCDSR & LCDC_LCDSR_SIPSTS));
+
+  /* Enable backlight */
+  LCDC->LCDC_LCDEN = LCDC_LCDEN_PWMEN;
+}
+
+/**
+ * @brief   Disable Display.
+ *
+ * @param[in] lcdcp     pointer to the @p LCDCDriver object
+ */
+static void lcdc_off(void) {
+
+  /* Disable all DMA channel descriptors */
+  clear_dma_desc(&base_dma_desc, &LCDC->LCDC_BASEADDR);
+  clear_dma_desc(&ovr1_dma_desc, &LCDC->LCDC_OVR1ADDR);
+  clear_dma_desc(&ovr2_dma_desc, &LCDC->LCDC_OVR2ADDR);
+  clear_dma_desc(&heo_dma_desc, &LCDC->LCDC_HEOADDR);
+  clear_dma_desc(&heo_dma_u_desc, &LCDC->LCDC_HEOUADDR);
+  clear_dma_desc(&heo_dma_v_desc, &LCDC->LCDC_HEOVADDR);
+
+  /* Disable DMA channels */
+  LCDC->LCDC_BASECHDR = LCDC_BASECHDR_CHDIS;
+  LCDC->LCDC_OVR1CHDR = LCDC_OVR1CHDR_CHDIS;
+  LCDC->LCDC_OVR2CHDR = LCDC_OVR2CHDR_CHDIS;
+  LCDC->LCDC_HEOCHDR = LCDC_HEOCHDR_CHDIS;
+  LCDC->LCDC_BASECFG4 = 0;
+
+  /* Poll CHSR until the channel is successfully disabled. */
+  while (LCDC->LCDC_BASECHSR & LCDC_BASECHSR_CHSR);
+  while (LCDC->LCDC_OVR1CHSR & LCDC_OVR1CHSR_CHSR);
+  while (LCDC->LCDC_OVR2CHSR & LCDC_OVR1CHSR_CHSR);
+  while (LCDC->LCDC_HEOCHSR & LCDC_HEOCHSR_CHSR);
+
+  /* Disable backlight */
+  LCDC->LCDC_LCDDIS = LCDC_LCDDIS_PWMDIS;
+  /* Poll PWMSTS: field of the LCDC_LCDSR register to verify that the PWM
+     is no activated. */
+  while (LCDC->LCDC_LCDSR & LCDC_LCDSR_PWMSTS);
+
+  /* Disable the DISP signal. */
+  LCDC->LCDC_LCDDIS = LCDC_LCDDIS_DISPDIS;
+  /* Poll DISPSTS field of the LCDC_LCDSR register to verify that the DISP
+     is no longer activated. */
+  while (LCDC->LCDC_LCDSR & LCDC_LCDSR_DISPSTS);
+
+  /* Disable the hsync and vsync signals. */
+  LCDC->LCDC_LCDDIS = LCDC_LCDDIS_SYNCDIS;
+  /* Poll LCDSTS field of the LCDC_LCDSR register to check that the
+     synchronization is off. */
+  while (LCDC->LCDC_LCDSR & LCDC_LCDSR_LCDSTS);
+
+  /* Disable the Pixel clock. */
+  LCDC->LCDC_LCDDIS = LCDC_LCDDIS_CLKDIS;
+  /* Poll CLKSTS field of the LCDC_LCDSR register to check that Pixel Clock
+     is disabled. */
+  while (LCDC->LCDC_LCDSR & LCDC_LCDSR_CLKSTS);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+/**
+ * @brief   Low level LCDC driver initialization.
+ *
+ * @notapi
+ */
+void lcdc_lld_init(void) {
+#if SAMA_HAL_IS_SECURE
+  mtxConfigPeriphSecurity(MATRIX0, ID_LCDC, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+
+  /* Driver initialization.*/
+  lcdcObjectInit(&LCDCD0);
+  LCDCD0.lcdc = LCDC;
+
+  /* Reset layer information */
+  lcdd_base.bpp = 0;
+  lcdd_base.buffer = NULL;
+  lcdd_base.dma_desc = &base_dma_desc;
+
+  lcdd_ovr1.bpp = 0;
+  lcdd_ovr1.buffer = NULL;
+  lcdd_ovr1.dma_desc = &ovr1_dma_desc;
+
+  lcdd_ovr2.bpp = 0;
+  lcdd_ovr2.buffer = NULL;
+  lcdd_ovr2.dma_desc = &ovr2_dma_desc;
+
+  lcdd_heo.bpp = 0;
+  lcdd_heo.buffer = NULL;
+  lcdd_heo.dma_desc = &heo_dma_desc;
+  lcdd_heo.dma_u_desc = &heo_dma_u_desc;
+  lcdd_heo.dma_v_desc = &heo_dma_v_desc;
+
+  lcdd_hcc.bpp = 0;
+  lcdd_base.buffer = NULL;
+  lcdd_hcc.dma_desc = &hcc_dma_desc;
+
+  /* Disable LCD controller */
+  lcdc_off();
+
+  /* Timing Engine Configuration */
+
+  /* Disable interrupt */
+  LCDC->LCDC_LCDIDR = 0xFFFFFFFF;
+
+  /* Base */
+  LCDC->LCDC_BASECFG0 = LCDC_BASECFG0_DLBO | LCDC_BASECFG0_BLEN_AHB_INCR16;
+
+  /* Overlay 1, GA 0xFF */
+  LCDC->LCDC_OVR1CFG0 = LCDC_OVR1CFG0_DLBO | LCDC_OVR1CFG0_BLEN_AHB_BLEN_INCR16 |
+                               LCDC_OVR1CFG0_ROTDIS;
+
+  LCDC->LCDC_OVR1CFG9 = LCDC_OVR1CFG9_GA(0xFF) | LCDC_OVR1CFG9_GAEN;
+
+  /* Overlay 2, GA 0xFF */
+  LCDC->LCDC_OVR2CFG0 = LCDC_OVR2CFG0_DLBO | LCDC_OVR2CFG0_BLEN_AHB_INCR16 |
+                               LCDC_OVR2CFG0_ROTDIS;
+  LCDC->LCDC_OVR2CFG9 = LCDC_OVR2CFG9_GA(0xFF) | LCDC_OVR2CFG9_GAEN;
+
+  /* High End Overlay, GA 0xFF */
+  LCDC->LCDC_HEOCFG0 =  LCDC_HEOCFG0_DLBO | LCDC_HEOCFG0_BLEN_AHB_BLEN_INCR16 |
+                               LCDC_HEOCFG0_ROTDIS;
+  LCDC->LCDC_HEOCFG12 = LCDC_HEOCFG12_GA(0xFF) | LCDC_HEOCFG12_GAEN;
+  LCDC->LCDC_HEOCFG14 = LCDC_HEOCFG14_CSCRY(0x94) | LCDC_HEOCFG14_CSCRU(0xCC) |
+                               LCDC_HEOCFG14_CSCRV(0) | LCDC_HEOCFG14_CSCYOFF;
+  LCDC->LCDC_HEOCFG15 = LCDC_HEOCFG15_CSCGY(0x94) | LCDC_HEOCFG15_CSCGU(0x387) |
+                               LCDC_HEOCFG15_CSCGV(0x3CD) | LCDC_HEOCFG15_CSCUOFF;
+  LCDC->LCDC_HEOCFG16 = LCDC_HEOCFG16_CSCBY(0x94)| LCDC_HEOCFG16_CSCBU(0) |
+                               LCDC_HEOCFG16_CSCBV(0x102) | LCDC_HEOCFG16_CSCVOFF;
+}
+
+/**
+ * @brief   Configures and activates the LCDC peripheral.
+ *
+ * @param[in] lcdcp     pointer to the @p LCDCDriver object
+ *
+ * @notapi
+ */
+void lcdc_lld_start(LCDCDriver *lcdcp) {
+
+  /* Enable the LCDC peripheral clock. */
+  pmcEnableLCDC();
+
+  /* Configure overlays */
+  layer_config(lcdcp->config->listp, lcdcp->config->length);
+
+}
+
+/**
+ * @brief   Deactivates the LCDC peripheral.
+ *
+ * @param[in] lcdcp     pointer to the @p LCDCDriver object
+ *
+ * @notapi
+ */
+void lcdc_lld_stop(LCDCDriver *lcdcp) {
+
+  if (lcdcp->state == LCDC_READY) {
+
+    /* Disable display. */
+    lcdc_off();
+
+    /* Disable the LCDC clock. */
+    pmcDisableLCDC();
+  }
+}
+
+/**
+ *
+ * @brief   Initializes the standard part of a @p LCDCDriver structure.
+ *
+ * @param[out] lcdcp  pointer to a @p LCDCDriver object
+ *
+ * @init
+ */
+void lcdcObjectInit(LCDCDriver *lcdcp) {
+  lcdcp->state = LCDC_STOP;
+  lcdcp->config = NULL;
+}
+
+/**
+ * @brief   LCDC driver initialization.
+ *
+ * @notapi
+ */
+void lcdcInit(void) {
+
+  lcdc_lld_init();
+}
+
+/**
+ * @brief   Configures and activates the LCDC peripheral.
+ *
+ * @param[in] lcdcp     pointer to the @p LCDCDriver object
+ * @param[in] configp     pointer to the LCDCConfig struct
+ *
+ * @api
+ */
+void lcdcStart(LCDCDriver *lcdcp, const LCDCConfig *configp) {
+
+ osalDbgCheck(lcdcp != NULL);
+
+  osalSysLock();
+  osalDbgAssert((lcdcp->state == LCDC_STOP) , "invalid state");
+  lcdcp->config = configp;
+  lcdc_lld_start(lcdcp);
+  lcdcp->state = LCDC_READY;
+  osalSysUnlock();
+
+  /* Enable display. */
+  lcdc_on(lcdcp);
+}
+
+/**
+ * @brief   Deactivates the LCDC peripheral.
+ *
+ * @param[in] lcdcp    pointer to the @p LCDCDriver object
+ *
+ * @api
+ */
+void lcdcStop(LCDCDriver *lcdcp) {
+
+  osalDbgCheck(lcdcp != NULL);
+
+  osalSysLock();
+  osalDbgAssert((lcdcp->state == LCDC_READY), "invalid state");
+
+  lcdc_lld_stop(lcdcp);
+  lcdcp->state = LCDC_STOP;
+  osalSysUnlock();
+}
+
+void lcdcShowLayer(LCDCDriver *lcdcp, uint8_t id, bool enable) {
+  (void)lcdcp;
+
+  if(enable) {
+    lcdd_layers[id].reg_enable[0] = LCDC_CHER_CHEN;
+  }
+  else {
+    lcdd_layers[id].reg_enable[1] = LCDC_CHDR_CHDIS;
+  }
+}
+
+/*
+ * @brief    brief Set the backlight of the LCD.
+ *
+ * param[in] level   Backlight brightness level [1..255],
+ *                   255 means maximum brightness.
+ *
+ * @api
+ */
+void lcdcSetBacklight(uint32_t level) {
+  uint32_t cfg = LCDC->LCDC_LCDCFG6 & ~LCDC_LCDCFG6_PWMCVAL_Msk;
+  LCDC->LCDC_LCDCFG6 = cfg | LCDC_LCDCFG6_PWMCVAL(level);
+}
+
+#if (TRUE == LCDC_USE_MUTUAL_EXCLUSION)
+
+/**
+ * @brief   Gains exclusive access to the LCDC module.
+ * @details This function tries to gain ownership to the LCDC module, if the
+ *          module is already being used then the invoking thread is queued.
+ * @pre     In order to use this function the option
+ *          @p LCDC_USE_MUTUAL_EXCLUSION must be enabled.
+ *
+ * @param[in] lcdcp     pointer to the @p LCDCDriver object
+ *
+ * @sclass
+ */
+void lcdcAcquireBusS(LCDCDriver *lcdcp) {
+
+  osalDbgCheckClassS();
+  osalDbgCheck(lcdcp == &LCDCD0);
+
+#if (TRUE == CH_CFG_USE_MUTEXES)
+  chMtxLockS(&lcdcp->lock);
+#else
+  chSemWaitS(&lcdcp->lock);
+#endif
+}
+
+/**
+ * @brief   Gains exclusive access to the LCDC module.
+ * @details This function tries to gain ownership to the LTDC module, if the
+ *          module is already being used then the invoking thread is queued.
+ * @pre     In order to use this function the option
+ *          @p LCDC_USE_MUTUAL_EXCLUSION must be enabled.
+ *
+ * @param[in] lcdcp     pointer to the @p LCDCDriver object
+ *
+ * @api
+ */
+void lcdcAcquireBus(LCDCDriver *lcdcp) {
+
+  osalSysLock();
+  lcdcAcquireBusS(lcdcp);
+  osalSysUnlock();
+}
+
+/**
+ * @brief   Releases exclusive access to the LCDC module.
+ * @pre     In order to use this function the option
+ *          @p LCDC_USE_MUTUAL_EXCLUSION must be enabled.
+ *
+ * @param[in] lcdcp     pointer to the @p LCDCDriver object
+ *
+ * @sclass
+ */
+void lcdcReleaseBusS(LCDCDriver *lcdcp) {
+
+  osalDbgCheckClassS();
+  osalDbgCheck(lcdcp == &LCDCD0);
+
+#if (TRUE == CH_CFG_USE_MUTEXES)
+  chMtxUnlockS(&lcdcp->lock);
+#else
+  chSemSignalI(&lcdcp->lock);
+#endif
+}
+
+/**
+ * @brief   Releases exclusive access to the LCDC module.
+ * @pre     In order to use this function the option
+ *          @p LCDC_USE_MUTUAL_EXCLUSION must be enabled.
+ *
+ * @param[in] lcdcp     pointer to the @p LCDCDriver object
+ *
+ * @api
+ */
+void lcdcReleaseBus(LCDCDriver *lcdcp) {
+
+  osalSysLock();
+  lcdcReleaseBusS(lcdcp);
+  osalSysUnlock();
+}
+
+#endif  /* LCDC_USE_MUTUAL_EXCLUSION */
+
+#endif /* SAMA_USE_LCDC == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.h b/os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.h
new file mode 100644
index 000000000..4a9237024
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_lcdc.h
@@ -0,0 +1,280 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/sama_lcdc.h
+ * @brief   SAMA LCDC support macros and structures.
+ *
+ * @addtogroup SAMA5D2x_LCDC
+ * @{
+ */
+
+#ifndef SAMA_LCDC_LLD_H
+#define SAMA_LCDC_LLD_H
+
+/**
+ * @brief   Using the LCDC driver.
+ */
+#if !defined(SAMA_USE_LCDC) || defined(__DOXYGEN__)
+#define SAMA_USE_LCDC                          FALSE
+#endif
+
+#if (SAMA_USE_LCDC) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+
+/**
+ * @name    LCDC ID LAYERS
+ * @{
+ */
+/* LCD controller ID, no display, configuration ONLY */
+#define LCDD_CONTROLLER     0
+
+/* LCD base layer, display fixed size image */
+#define LCDD_BASE           1
+
+/* LCD Overlay 1 */
+#define LCDD_OVR1           2
+
+/* LCD Overlay 2 */
+#define LCDD_OVR2           4
+
+/* LCD HighEndOverlay, support resize */
+#define LCDD_HEO            3
+
+/* LCD Cursor, max size 128x128 */
+#define LCDD_CUR            6
+/** @} */
+
+/**
+ * @name    BPP MODE
+ * @{
+ */
+#define   LCDC_CFG_RGBMODE_12BPP_RGB_444          (0x0u << 4)
+#define   LCDC_CFG_RGBMODE_16BPP_ARGB_4444        (0x1u << 4)
+#define   LCDC_CFG_RGBMODE_16BPP_RGBA_4444        (0x2u << 4)
+#define   LCDC_CFG_RGBMODE_16BPP_RGB_565          (0x3u << 4)
+#define   LCDC_CFG_RGBMODE_16BPP_TRGB_1555        (0x4u << 4)
+#define   LCDC_CFG_RGBMODE_18BPP_RGB_666          (0x5u << 4)
+#define   LCDC_CFG_RGBMODE_18BPP_RGB_666PACKED    (0x6u << 4)
+#define   LCDC_CFG_RGBMODE_19BPP_TRGB_1666        (0x7u << 4)
+#define   LCDC_CFG_RGBMODE_19BPP_TRGB_PACKED      (0x8u << 4)
+#define   LCDC_CFG_RGBMODE_24BPP_RGB_888          (0x9u << 4)
+#define   LCDC_CFG_RGBMODE_24BPP_RGB_888_PACKED   (0xAu << 4)
+#define   LCDC_CFG_RGBMODE_25BPP_TRGB_1888        (0xBu << 4)
+#define   LCDC_CFG_RGBMODE_32BPP_ARGB_8888        (0xCu << 4)
+#define   LCDC_CFG_RGBMODE_32BPP_RGBA_8888        (0xDu << 4)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings.                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks.                                       */
+/*===========================================================================*/
+/**
+ * @brief   LCDC_USE_WAIT.
+ */
+#if !defined(LCDC_USE_WAIT) || defined(__DOXYGEN__)
+#define LCDC_USE_WAIT                         FALSE
+#endif
+
+/**
+ * @brief   LCDC_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LCDC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define LCDC_USE_MUTUAL_EXCLUSION             FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+
+/**
+ * @brief   Driver state machine possible states.
+ */
+typedef enum {
+  LCDC_UNINIT   = 0,                /**< Not initialized.*/
+  LCDC_STOP     = 1,                /**< Stopped.*/
+  LCDC_READY    = 2,                /**< Ready.*/
+  LCDC_ACTIVE   = 3,                /**< Executing commands.*/
+} lcdcstate_t;
+
+/**
+ * @brief   Type of a structure representing an LCDC driver.
+ */
+typedef struct LCDCDriver LCDCDriver;
+
+/**
+ * @brief   LCD display layer information.
+ */
+typedef struct {
+  /**
+   * @brief   Display image buffer.
+   */
+  void                      *buffer;
+  /**
+   * @brief   Display image width.
+   */
+  uint16_t                  width;
+  /**
+   * @brief   Display image height.
+   */
+  uint16_t                  height;
+  /**
+   * @brief   Display image x position.
+   */
+  uint16_t                  x_pos;
+  /**
+   * @brief   Display image y_pos.
+   */
+  uint16_t                  y_pos;
+  /**
+   * @brief   Horizontal image Size in Memory.
+   */
+  uint16_t                  w_img;
+  /**
+   * @brief   Vertical image Size in Memory.
+   */
+  uint16_t                  h_img;
+  /**
+   * @brief   BPP mode.
+   */
+  uint8_t                   bpp;
+  /**
+   * @brief   Layer ID.
+   */
+  uint8_t                   layer_id;
+} LCDCLayerConfig;
+
+/**
+ * @brief   Driver LCD configuration structure.
+ */
+typedef struct {
+  /**
+   * @brief   Display image width.
+   */
+  uint16_t                  width;
+  /**
+   * @brief   Display image height.
+   */
+  uint16_t                  height;
+  /**
+   * @brief   Frame rate in Hz.
+   */
+  uint8_t                   framerate;
+  /**
+   * @brief   Vertical front porch in number of lines.
+   */
+  uint8_t                   timing_vfp;
+  /**
+   * @brief   Vertical back porch in number of lines.
+   */
+  uint8_t                   timing_vbp;
+  /**
+   * @brief   Vertical pulse width in number of lines.
+   */
+  uint8_t                   timing_vpw;
+  /**
+   * @brief   Horizontal front porch in LCDDOTCLK cycles.
+   */
+  uint8_t                   timing_hfp;
+  /**
+   * @brief   Horizontal back porch in LCDDOTCLK cycles.
+   */
+  uint8_t                   timing_hbp;
+  /**
+   * @brief   Horizontal pulse width in LCDDOTCLK cycles.
+   */
+  uint8_t                   timing_hpw;
+  /**
+   * @brief lenght of LCDCLayerConfig array
+   * @note  Number of layers to configure
+   */
+  size_t                    length;
+  /**
+   * @brief pointer to LCDCLayerConfig array
+   */
+  LCDCLayerConfig           *listp;
+} LCDCConfig;
+
+/**
+ * @brief   Structure representing an LCDC driver.
+ */
+struct LCDCDriver {
+  /**
+   * @brief   Driver state.
+   */
+  lcdcstate_t               state;
+  /**
+   * @brief   Current configuration lcd data.
+   */
+  const LCDCConfig          *config;
+  /**
+   * @brief   Pointer to the LCDC registers block.
+   */
+  Lcdc                      *lcdc;
+  /* Multithreading stuff.*/
+#if (LCDC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+  thread_t          *thread;
+#endif  /* LCDC_USE_WAIT */
+#if (LCDC_USE_MUTUAL_EXCLUSION == TRUE)
+#if (CH_CFG_USE_MUTEXES == TRUE)
+  mutex_t           lock;
+#elif (CH_CFG_USE_SEMAPHORES == TRUE)
+  semaphore_t       lock;
+#endif
+#endif  /* LCDC_USE_MUTUAL_EXCLUSION */
+};
+
+/*===========================================================================*/
+/* Driver macros.                                                            */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations.                                                    */
+/*===========================================================================*/
+
+extern LCDCDriver LCDCD0;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void lcdcObjectInit(LCDCDriver *lcdcp);
+  void lcdcInit(void);
+  void lcdcStart(LCDCDriver *lcdcp, const LCDCConfig *configp);
+  void lcdcStop(LCDCDriver *lcdcp);
+  void lcdcShowLayer(LCDCDriver *lcdcp, uint8_t id, bool enable);
+  void lcdcSetBacklight(uint32_t level);
+#if (LCDC_USE_MUTUAL_EXCLUSION)
+  void lcdcAcquireBusS(LCDCDriver *lcdcp);
+  void lcdcAcquireBus(LCDCDriver *lcdcp);
+  void lcdcReleaseBusS(LCDCDriver *lcdcp);
+  void lcdcReleaseBus(LCDCDriver *lcdcp);
+#endif  /* LCDC_USE_MUTUAL_EXCLUSION */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SAMA_USE_LCDC */
+
+#endif /* SAMA_LCDC_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_onewire.c b/os/hal/ports/SAMA/SAMA5D2x/sama_onewire.c
new file mode 100644
index 000000000..97c0477da
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_onewire.c
@@ -0,0 +1,548 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/sama_onewire.c
+ * @brief   SAMA ONEWIRE support code.
+ *
+ * @addtogroup SAMA5D2x_ONEWIRE
+ * @{
+ */
+
+#include "hal.h"
+
+#if (SAMA_USE_ONEWIRE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+/**
+ * @name    Delays in standard speed mode.
+ * @{
+ */
+#define A                                      US2RTC(SAMA_PCK, 6)
+#define B                                      US2RTC(SAMA_PCK, 64)
+#define C                                      US2RTC(SAMA_PCK, 60)
+#define D                                      US2RTC(SAMA_PCK, 10)
+#define E                                      US2RTC(SAMA_PCK, 9)
+#define F                                      US2RTC(SAMA_PCK, 55)
+#define G                                      US2RTC(SAMA_PCK, 0)
+#define H                                      US2RTC(SAMA_PCK, 480)
+#define I                                      US2RTC(SAMA_PCK, 70)
+#define J                                      US2RTC(SAMA_PCK, 410)
+/** @} */
+
+#if SAMA_HAL_IS_SECURE
+#define PAD_INPUT_MODE                         PAL_SAMA_FUNC_GPIO |          \
+                                               PAL_SAMA_DIR_INPUT |          \
+                                               PAL_SAMA_OPD_OPENDRAIN |      \
+                                               PAL_SAMA_PUEN_PULLUP |        \
+                                               PAL_MODE_SECURE
+
+#define PAD_OUTPUT_MODE                        PAL_SAMA_FUNC_GPIO |          \
+                                               PAL_SAMA_DIR_OUTPUT |         \
+                                               PAL_SAMA_OPD_OPENDRAIN |      \
+                                               PAL_SAMA_PUEN_PULLUP |        \
+                                               PAL_MODE_SECURE
+#else
+#define PAD_INPUT_MODE                         PAL_SAMA_FUNC_GPIO |          \
+                                               PAL_SAMA_DIR_INPUT |          \
+                                               PAL_SAMA_OPD_OPENDRAIN |      \
+                                               PAL_SAMA_PUEN_PULLUP
+
+#define PAD_OUTPUT_MODE                        PAL_SAMA_FUNC_GPIO |          \
+                                               PAL_SAMA_DIR_OUTPUT |         \
+                                               PAL_SAMA_OPD_OPENDRAIN |      \
+                                               PAL_SAMA_PUEN_PULLUP
+#endif /* SAMA_HAL_IS_SECURE */
+
+/*===========================================================================*/
+/* Driver local macros.                                                      */
+/*===========================================================================*/
+
+/**
+ * @brief    Set ONEWIRE pin in output mode.
+ *
+ * @param[in] onewp    pointer to a ONEWIRE driver.
+ *
+ * @notapi
+ */
+#define onewireSetPinOutput(onewp) {                                         \
+  palSetLineMode(onewp->config->line, PAD_OUTPUT_MODE);                      \
+}
+
+/**
+ * @brief   Set ONEWIRE pin in input mode.
+ *
+ * @param[in] onewp    pointer to a ONEWIRE driver.
+ *
+ * @notapi
+ */
+#define onewireSetPinInput(onewp) {                                          \
+  palSetLineMode(onewp->config->line, PAD_INPUT_MODE);                       \
+}
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+ONEWIREDriver ONEWD0;
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+/**
+ * @brief   Low level ONEWIRE driver initialization.
+ *
+ * @notapi
+ */
+void onewire_lld_init(void) {
+
+  onewireObjectInit(&ONEWD0);
+}
+
+/**
+ * @brief   Configures and activates the ONEWIRE pin.
+ *
+ * @param[in] onewp  pointer to the @p ONEWIREDriver object
+ *
+ * @notapi
+ */
+void onewire_lld_start(ONEWIREDriver *onewp) {
+
+  /* Set the ONEWIRE pin in output mode. */
+  onewireSetPinOutput(onewp);
+
+}
+
+/**
+ * @brief   Deactivates the ONEWIRE driver.
+ *
+ * @param[in] onewp  pointer to the @p ONEWIREDriver object
+ *
+ * @notapi
+ */
+void onewire_lld_stop(ONEWIREDriver *onewp) {
+  (void) onewp;
+}
+
+/**
+ * @brief   Send a Reset on ONEWIRE pin.
+ *          The reset detect the slave presence on the pin
+ *          and ready it for a command.
+ *
+ * @param[in] onewp    pointer to the @p ONEWIREDriver object
+ * @return    result   result of the reset, if 0 a slave is detected
+ *
+ * @notapi
+ */
+bool onewire_lld_reset(ONEWIREDriver *onewp) {
+
+  bool result = TRUE;
+
+  /* At the beginning set the pin in output mode. */
+  onewireSetPinOutput(onewp);
+
+  /* Wait 0 microseconds. */
+  chSysPolledDelayX(G);
+  /* Drives pin low. */
+  palClearLine(onewp->config->line);
+  /* Wait 480 microseconds. */
+  chSysPolledDelayX(H);
+  /* Drives pin high. */
+  palSetLine(onewp->config->line);
+  /* Wait 70 microseconds. */
+  chSysPolledDelayX(I);
+  /* Set the pin in input mode. */
+  onewireSetPinInput(onewp);
+  /* Read the pin logic state. */
+  result = palReadLine(onewp->config->line);
+  /* Wait 410 microseconds. */
+  chSysPolledDelayX(J);
+
+  return result;
+}
+
+/**
+ * @brief   Write a bit through ONEWIRE pin.
+ *
+ * @param[in] onewp     pointer to the @p ONEWIREDriver object
+ * @param[in] value     bit value to write
+ *
+ * @notapi
+ */
+void onewire_lld_write_bit(ONEWIREDriver *onewp, uint8_t value) {
+
+  osalDbgAssert((value == 0u) || (value == 1u),
+                "invalid value");
+
+  /* Set the pin in output mode. */
+  onewireSetPinOutput(onewp);
+
+  if (value) {
+    /* Write '1' bit */
+    /* Drives pin low. */
+    palClearLine(onewp->config->line);
+    /* Wait 6 microsecond. */
+    chSysPolledDelayX(A);
+    /* Drives pin high. */
+    palSetLine(onewp->config->line);
+    /* Wait 64 microseconds to complete the time slot and recovery. */
+    chSysPolledDelayX(B);
+  }
+  else {
+    /* Write '0' bit */
+    /* Drives pin low. */
+    palClearLine(onewp->config->line);
+    /* Wait 60 microsecond. */
+    chSysPolledDelayX(C);
+    /* Drives pin high. */
+    palSetLine(onewp->config->line);
+    /* Wait 10 microseconds for recovery. */
+    chSysPolledDelayX(D);
+  }
+}
+
+/**
+ * @brief   Read a bit through ONEWIRE pin.
+ *
+ * @param[in] onewp    pointer to the @p ONEWIREDriver object
+ * @return    value    bit read
+ *
+ * @notapi
+ */
+uint8_t onewire_lld_read_bit(ONEWIREDriver *onewp) {
+
+  uint8_t value;
+
+  /* At the beginning set the pin in output mode. */
+  onewireSetPinOutput(onewp);
+
+  /* Drives pin low. */
+  palClearLine(onewp->config->line);
+  /* Wait 6 microsecond. */
+  chSysPolledDelayX(A);
+  /* Drives pin high. */
+  palSetLine(onewp->config->line);
+  /* Wait 9 microseconds. */
+  chSysPolledDelayX(E);
+  /* Set the pin in input mode. */
+  onewireSetPinInput(onewp);
+  /* Read the pin logic state. */
+  value = palReadLine(onewp->config->line);
+  /* Wait 55 microseconds. */
+  chSysPolledDelayX(F);
+
+  return value;
+}
+
+/**
+ * @brief   Write a byte through ONEWIRE pin.
+ *
+ * @param[in] onewp       pointer to the @p ONEWIREDriver object
+ * @param[in] byte        byte to write
+ *
+ * @notapi
+ */
+void onewire_lld_write_byte(ONEWIREDriver *onewp, uint8_t byte) {
+
+  uint8_t i;
+
+  /* Loop to write each bit in the byte, LS-bit first */
+  for (i = 0; i < 8; i++) {
+    onewire_lld_write_bit(onewp, (byte & 0x01));
+    /* Shift the data byte for the next bit */
+    byte >>= 1;
+  }
+}
+
+/**
+ * @brief   Read a byte through ONEWIRE pin.
+ *
+ * @param[in] onewp       pointer to the @p ONEWIREDriver object
+ * return     value       byte read
+ *
+ * @notapi
+ */
+uint8_t onewire_lld_read_byte(ONEWIREDriver *onewp) {
+
+  uint8_t i;
+  uint8_t value = 0;
+
+  for (i = 0; i < 8; i++) {
+    /* Shift the result to get it ready for the next bit */
+    value >>= 1;
+    /* If result is one, then set MS bit */
+    if (onewire_lld_read_bit(onewp))
+      value |= 0x80;
+  }
+  return value;
+}
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+/**
+ * @brief   ONEWIRE driver initialization.
+ *
+ * @api
+ */
+void onewireInit(void) {
+
+  onewire_lld_init();
+}
+
+/**
+ * @brief   Initializes the standard part of a @p ONEWIREDriver structure.
+ *
+ * @param[out] onewp     pointer to the @p ONEWIREDriver object
+ *
+ * @init
+ */
+void onewireObjectInit(ONEWIREDriver *onewp) {
+
+  onewp->state = ONEW_STOP;
+  onewp->config = NULL;
+
+  osalMutexObjectInit(&onewp->mutex);
+}
+
+/**
+ * @brief   Configures and activates the ONEWIRE pin.
+ *
+ * @param[in] onewp pointer to the @p ONEWIREDriver object
+ * @param[in] config    pointer to the @p ONEWIREConfig object
+ *
+ * @api
+ */
+void onewireStart(ONEWIREDriver *onewp, const ONEWIREConfig *config) {
+
+  osalDbgCheck((onewp != NULL) && (config != NULL));
+
+  osalSysLock();
+  osalDbgAssert((onewp->state == ONEW_STOP) || (onewp->state == ONEW_READY),
+                "invalid state");
+  onewp->config = config;
+  onewire_lld_start(onewp);
+  onewp->state = ONEW_READY;
+  osalSysUnlock();
+
+}
+
+/**
+ * @brief   Deactivates the ONEWIRE driver.
+ *
+ * @param[in] onewp    pointer to the @p ONEWIREDriver object
+ *
+ * @api
+ */
+void onewireStop(ONEWIREDriver *onewp) {
+
+  osalDbgCheck(onewp != NULL);
+
+  osalSysLock();
+
+  osalDbgAssert((onewp->state == ONEW_STOP) || (onewp->state == ONEW_READY),
+                "invalid state");
+
+  onewire_lld_stop(onewp);
+  onewp->config = NULL;
+  onewp->state  = ONEW_STOP;
+
+  osalSysUnlock();
+}
+
+/**
+ * @brief   Write a block of bytes through ONEWIRE pin.
+ *
+ * @param[in] onewp       pointer to the @p ONEWIREDriver object
+ * @param[in] txbuf       the pointer to the transmit buffer
+ * @param[in] n           number of bytes to write
+ *
+ * @api
+ */
+void onewireWriteBlockI(ONEWIREDriver *onewp, uint8_t *txbuf, size_t n) {
+
+  uint32_t i;
+  (onewp)->state = ONEW_ACTIVE;
+  for (i = 0; i < n; i++) {
+    onewire_lld_write_byte(onewp, txbuf[i]);
+  }
+}
+
+/**
+ * @brief   Write a block of bytes through ONEWIRE pin.
+ *
+ * @param[in] onewp       pointer to the @p ONEWIREDriver object
+ * @param[in] txbuf       the pointer to the transmit buffer
+ * @param[in] n           number of bytes to write
+ *
+ * @api
+ */
+void onewireWriteBlock(ONEWIREDriver *onewp, uint8_t *txbuf, size_t n) {
+
+  osalDbgCheck(onewp != NULL);
+
+  osalSysLock();
+  osalDbgAssert(onewp->state == ONEW_READY, "not ready");
+  onewireWriteBlockI(onewp, txbuf, n);
+
+  (onewp)->state = ONEW_READY;
+  osalSysUnlock();
+}
+
+/**
+ * @brief   Read a block of bytes through ONEWIRE pin.
+ *
+ * @param[in] onewp       pointer to the @p ONEWIREDriver object
+ * @param[out]rxbuf       pointer to the receive buffer
+ * @param[in] n           number of bytes to read
+ *
+ * @api
+ */
+void onewireReadBlockI(ONEWIREDriver *onewp, uint8_t *rxbuf, size_t n) {
+
+  uint32_t i;
+  (onewp)->state = ONEW_ACTIVE;
+  for (i = 0; i < n; i++) {
+    rxbuf[i] = onewire_lld_read_byte(onewp);
+  }
+}
+
+/**
+ * @brief   Read a block of bytes through ONEWIRE pin.
+ *
+ * @param[in] onewirep    pointer to the @p ONEWIREDriver object
+ * @param[out]rxbuf       pointer to the receive buffer
+ * @param[in] n           number of bytes to read
+ *
+ * @api
+ */
+void onewireReadBlock(ONEWIREDriver *onewp, uint8_t *rxbuf, size_t n) {
+
+  osalDbgCheck(onewp != NULL);
+
+//  osalSysLock();
+  osalDbgAssert(onewp->state == ONEW_READY, "not ready");
+  onewireReadBlockI(onewp, rxbuf, n);
+  (onewp)->state = ONEW_READY;
+//  osalSysUnlock();
+}
+
+/**
+ * @brief   Send a Reset on ONEWIRE pin.
+ *          The reset detect the slave presence on the pin
+ *          and ready it for a command.
+ *
+ * @param[in] onewp    pointer to the @p ONEWIREDriver object
+ * @return    result   result of the reset, if 0 a slave is detected
+ *
+ * @api
+ */
+bool onewireReset(ONEWIREDriver *onewp) {
+
+  bool detect = TRUE;
+
+  osalDbgCheck(onewp != NULL);
+
+  osalSysLock();
+  osalDbgAssert(onewp->state == ONEW_READY,
+                "invalid state");
+  detect = onewire_lld_reset(onewp);
+  osalSysUnlock();
+
+  return detect;
+}
+
+/*
+ * @brief   Sends a command.
+ *
+ * @param[in] onewp     pointer to the @p ONEWIREDriver object
+ * @param[in] cmdp      pointer command byte
+ *
+ * @api
+ */
+void onewireCommandI(ONEWIREDriver *onewp, uint8_t *cmdp, size_t n) {
+
+  uint32_t i;
+  (onewp)->state = ONEW_ACTIVE;
+  for (i = 0; i < n; i++) {
+    onewire_lld_write_byte(onewp, cmdp[i]);
+  }
+}
+
+/*
+ * @brief   Sends a command.
+ *
+ * @param[in] onewp     pointer to the @p ONEWIREDriver object
+ * @param[in] cmdp       pointer to command
+ *
+ * @api
+ */
+void onewireCommand(ONEWIREDriver *onewp, uint8_t *cmdp, size_t n) {
+
+ osalDbgCheck((onewp != NULL) && (cmdp != NULL));
+
+// osalSysLock();
+
+ osalDbgAssert(onewp->state == ONEW_READY, "not ready");
+
+ onewireCommandI(onewp, cmdp, n);
+ (onewp)->state = ONEW_READY;
+// osalSysUnlock();
+}
+
+
+/**
+ * @brief   Gains exclusive access to the ONEWIRE bus.
+ * @details This function tries to gain ownership to the ONEWIRE bus, if the bus
+ *          is already being used then the invoking thread is queued.
+ *
+ * @param[in] onewp      pointer to the @p ONEWIREDriver object
+ *
+ * @api
+ */
+void onewireAcquireBus(ONEWIREDriver *onewp) {
+
+  osalDbgCheck(onewp != NULL);
+
+  osalMutexLock(&onewp->mutex);
+}
+
+/**
+ * @brief   Releases exclusive access to the ONEWIRE bus.
+ *
+ * @param[in] onewp      pointer to the @p ONEWIREDriver object
+ *
+ * @api
+ */
+void onewireReleaseBus(ONEWIREDriver *onewp) {
+
+  osalDbgCheck(onewp != NULL);
+
+  osalMutexUnlock(&onewp->mutex);
+}
+
+#endif /* SAMA_USE_ONEWIRE == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_onewire.h b/os/hal/ports/SAMA/SAMA5D2x/sama_onewire.h
new file mode 100644
index 000000000..b8edb1185
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_onewire.h
@@ -0,0 +1,127 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/sama_onewire.h
+ * @brief   SAMA ONEWIRE support macros and structures.
+ *
+ * @addtogroup SAMA5D2x_ONEWIRE
+ * @{
+ */
+
+#ifndef SAMA_ONEWIRE_LLD_H
+#define SAMA_ONEWIRE_LLD_H
+
+/**
+ * @brief   Using the ONEWIRE driver.
+ */
+#if !defined(SAMA_USE_ONEWIRE) || defined(__DOXYGEN__)
+#define SAMA_USE_ONEWIRE                        FALSE
+#endif
+
+#if (SAMA_USE_ONEWIRE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings.                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks.                                       */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+/**
+ * @brief   Driver state machine possible states.
+ */
+typedef enum {
+  ONEW_UNINIT = 0,                   /**< Not initialized.                   */
+  ONEW_STOP = 1,                     /**< Stopped.                           */
+  ONEW_READY = 2,                     /**< Active.                            */
+  ONEW_ACTIVE = 3                    /**< Active.                            */
+} onewstate_t;
+
+/**
+ * @brief   Type of a structure representing a ONEWIRE driver.
+ */
+typedef struct ONEWIREDriver ONEWIREDriver;
+
+/**
+ * @brief   Driver configuration structure.
+ */
+typedef struct {
+  /**
+   * @brief   Line for the data IO
+   */
+  uint32_t                  line;
+} ONEWIREConfig;
+
+
+/**
+ * @brief   Structure representing an ONEWIRE driver.
+ */
+struct ONEWIREDriver {
+  /**
+   * @brief Driver state.
+   */
+  onewstate_t               state;
+  /**
+   * @brief   Current configuration data.
+   */
+  const ONEWIREConfig       *config;
+  /**
+   * @brief Mutex protecting the bus.
+   */
+  mutex_t                   mutex;
+};
+
+/*===========================================================================*/
+/* Driver macros.                                                            */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations.                                                    */
+/*===========================================================================*/
+
+extern ONEWIREDriver ONEWD0;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void onewireInit(void);
+  void onewireObjectInit(ONEWIREDriver *onewp);
+  void onewireStart(ONEWIREDriver *onewp, const ONEWIREConfig *config);
+  void onewireStop(ONEWIREDriver *onewp);
+  bool onewireReset(ONEWIREDriver *onewp);
+  void onewireCommand(ONEWIREDriver *onewp, uint8_t *cmdp, size_t n);
+  void onewireWriteBlock(ONEWIREDriver *onewp, uint8_t *txbuf, size_t n);
+  void onewireReadBlock(ONEWIREDriver *onewp, uint8_t *rxbuf, size_t n);
+  void onewireAcquireBus(ONEWIREDriver *onewp);
+  void onewireReleaseBus(ONEWIREDriver *onewp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SAMA_USE_ONEWIRE */
+
+#endif /* SAMA_ONEWIRE_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h b/os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h
index 8fc57b261..bf0fb7441 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h
@@ -49,6 +49,7 @@
  * @name    Generic PMC operations
  * @{
  */
+#if SAMA_HAL_IS_SECURE
 /**
  * @brief   Enable write protection on PMC registers block.
  *
@@ -122,6 +123,387 @@
   PMC->PMC_PCDR1 = (mask);                                                  \
   pmcEnableWP();                                                            \
 }
+
+/**
+ * @brief   Enables the generic clock of a peripheral.
+ *
+ * @param[in] mask      ID peripherals
+ *
+ * @api
+ */
+#define pmcEnableGclk(id) {                                                 \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  pmcDisableWP();                                                           \
+  PMC->PMC_PCR = PMC_PCR_PID(id);                                           \
+  uint32_t pcr = PMC->PMC_PCR;                                              \
+  PMC->PMC_PCR = pcr | PMC_PCR_CMD | PMC_PCR_GCKEN;                         \
+  while (!(PMC->PMC_SR & PMC_SR_GCKRDY));                                   \
+  pmcEnableWP();                                                            \
+}
+
+/**
+ * @brief   Disable the generic clock of a peripheral.
+ *
+ * @param[in] mask      ID peripherals
+ *
+ * @api
+ */
+#define pmcDisableGclk(id) {                                                \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  pmcDisableWP();                                                           \
+  PMC->PMC_PCR = PMC_PCR_PID(id);                                           \
+  uint32_t pcr = PMC->PMC_PCR;                                              \
+  PMC->PMC_PCR = PMC_PCR_CMD | (pcr & ~(PMC_PCR_GCKEN));                    \
+  pmcEnableWP();                                                            \
+}
+
+/**
+ * @brief   Configure the generic clock of a peripheral.
+ *
+ * @param[in] id           ID peripherals mask
+ * @param[in] clock_source Clock source
+ * @param[in] div          Divider
+ *
+ * @api
+ */
+
+#define pmcConfigGclk(id, clock_source, div) {                              \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  osalDbgCheck(!(clock_source & ~PMC_PCR_GCKCSS_Msk));                      \
+  osalDbgCheck((div > 0));                                                  \
+  osalDbgCheck(!(div << PMC_PCR_GCKDIV_Pos & ~PMC_PCR_GCKDIV_Msk));         \
+  pmcDisableGclk(id); 					                                            \
+  pmcDisableWP();                                                           \
+  PMC->PMC_PCR = PMC_PCR_PID(id);                                           \
+  uint32_t pcr = PMC->PMC_PCR & ~(PMC_PCR_GCKCSS_Msk | PMC_PCR_GCKDIV_Msk); \
+  PMC->PMC_PCR = pcr | clock_source | PMC_PCR_CMD | PMC_PCR_GCKDIV(div - 1);\
+  pmcEnableWP();                                                            \
+}
+
+/**
+ * @brief   Enable the peripheral clock of a peripheral.
+ *
+ * @param[in] id        ID peripherals mask
+ *
+ * @api
+ */
+#define pmcEnablePeripheral(id) {                                           \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  pmcDisableWP();                                                           \
+  PMC->PMC_PCR = PMC_PCR_PID(id);                                           \
+  uint32_t pcr = PMC->PMC_PCR;                                              \
+  PMC->PMC_PCR = pcr | PMC_PCR_CMD | PMC_PCR_EN;                            \
+  pmcEnableWP();                                                            \
+}
+
+/**
+ * @brief   Disable the peripheral clock of a peripheral.
+ *
+ * @param[in] id        ID peripherals mask
+ *
+ * @api
+ */
+#define pmcDisablePeripheral(id) {                                          \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  pmcDisableWP();                                                           \
+  PMC->PMC_PCR = PMC_PCR_PID(id);                                           \
+  PMC->PMC_PCR = (PMC->PMC_PCR & ~PMC_PCR_EN) | PMC_PCR_CMD;                \
+  pmcEnableWP();                                                            \
+}
+
+
+/**
+ * @brief   Configure the Audio clock.
+ *
+ * @param[in] nd        Loop Divider Ratio
+ * @param[in] qdpmc     Output Divider Ratio for PMC Clock
+ * @param[in] fracr     Fractional Loop Divider Setting
+ * @param[in] div       Divider Value
+ * @param[in] qaudio    Output Divider Ratio for Pad Clock
+ *
+ * @api
+ */
+#define pmcConfigAudio(nd,qdpmc,fracr,div,qdaudio) {                        \
+ /* Reset audio clock */                                                    \
+ pmcDisableWP();                                                            \
+ PMC->PMC_AUDIO_PLL0 &= ~PMC_AUDIO_PLL0_RESETN;                             \
+ PMC->PMC_AUDIO_PLL0 |= PMC_AUDIO_PLL0_RESETN;                              \
+ /* Configure values */                                                     \
+ PMC->PMC_AUDIO_PLL0 = (PMC->PMC_AUDIO_PLL0 &                               \
+                       ~PMC_AUDIO_PLL0_PLLFLT_Msk &                         \
+                       ~PMC_AUDIO_PLL0_ND_Msk &                             \
+                       ~PMC_AUDIO_PLL0_QDPMC_Msk) |                         \
+                       PMC_AUDIO_PLL0_PLLFLT_STD |                          \
+                       PMC_AUDIO_PLL0_ND(nd) |                              \
+                       PMC_AUDIO_PLL0_QDPMC(qdpmc);                         \
+ PMC->PMC_AUDIO_PLL1 = (PMC->PMC_AUDIO_PLL1 &                               \
+                       ~PMC_AUDIO_PLL1_FRACR_Msk &                          \
+                       ~PMC_AUDIO_PLL1_DIV_Msk &                            \
+                       ~PMC_AUDIO_PLL1_QDAUDIO_Msk) |                       \
+                       PMC_AUDIO_PLL1_FRACR(fracr) |                        \
+                       PMC_AUDIO_PLL1_DIV(div)|                             \
+                       PMC_AUDIO_PLL1_QDAUDIO(qdaudio);                     \
+ pmcEnableWP();                                                             \
+}
+
+/**
+ * @brief   Enable the audio clock of a audio peripheral.
+ *
+ * @param[in] pmcClock  If set TRUE enable the PMC clock
+ * @param[in] padClock  If set TRUE enable the PAD clock
+ *
+ * @api
+ */
+#define pmcEnableAudio(pmcClock, padClock) {                                \
+ pmcDisableWP();                                                            \
+ uint32_t bits = PMC_AUDIO_PLL0_PLLEN | PMC_AUDIO_PLL0_RESETN;              \
+ uint32_t nbits = 0;                                                        \
+ if(padClock)                                                               \
+   bits |= PMC_AUDIO_PLL0_PADEN;                                            \
+ else                                                                       \
+   nbits |= PMC_AUDIO_PLL0_PADEN;                                           \
+ if(pmcClock)                                                               \
+   bits |= PMC_AUDIO_PLL0_PMCEN;                                            \
+ else                                                                       \
+   nbits |= PMC_AUDIO_PLL0_PMCEN;                                           \
+ PMC->PMC_AUDIO_PLL0 = (PMC->PMC_AUDIO_PLL0 & ~nbits) | bits;               \
+ /* Wait for the Audio PLL Startup Time (tSTART = 100 usec) */              \
+ chSysPolledDelayX(US2RTC(SAMA_PCK, 100));                                  \
+ pmcEnableWP();                                                             \
+}
+
+/**
+ * @brief   Disable the audio clock of a audio peripheral.
+ *
+ * @api
+ */
+#define pmcDisableAudio(){                                                  \
+ pmcDisableWP();                                                            \
+ PMC->PMC_AUDIO_PLL0 &= ~(PMC_AUDIO_PLL0_PLLEN | PMC_AUDIO_PLL0_RESETN |    \
+                          PMC_AUDIO_PLL0_PADEN | PMC_AUDIO_PLL0_PMCEN);     \
+ pmcEnableWP();                                                             \
+}
+#else
+#include "tsclient.h"
+
+static inline uint32_t readPMCr(uint32_t regOffset)
+{
+  sec_reg_val_t secr;
+
+  secr.reg = regOffset;
+  secr.value = 0;
+  (void) tsInvoke0((ts_service_t)TS_FC_PMC_RD,
+      (ts_params_area_t)&secr, sizeof secr, TS_TIMEINT_1000_US);
+  return secr.value;
+}
+
+static inline void writePMCr(uint32_t regOffset, uint32_t v)
+{
+  sec_reg_val_t secr;
+
+  secr.reg = regOffset;
+  secr.value = v;
+  (void) tsInvoke0((ts_service_t)TS_FC_PMC_WR,
+      (ts_params_area_t)&secr, sizeof secr, TS_TIMEINT_1000_US);
+  return;
+}
+
+/**
+ * @brief   Enables the clock of one or more peripheral having ID from 2 to
+ *          31.
+ *
+ * @param[in] mask      PCER0 peripherals mask
+ *
+ * @api
+ */
+#define pmcEnablePidLow(mask) {                                             \
+  writePMCr(offsetof(Pmc, PMC_PCER0), (mask));                              \
+}
+
+/**
+ * @brief   Disables the clock of one or more peripheral having ID from 2 to
+ *          31.
+ *
+ * @param[in] mask      PCDR0 peripherals mask
+ *
+ * @api
+ */
+#define pmcDisablePidLow(mask) {                                            \
+  writePMCr(offsetof(Pmc, PMC_PCDR0), (mask));                              \
+}
+
+/**
+ * @brief   Enables the clock of one or more peripheral having ID from 32 to
+ *          63.
+ *
+ * @param[in] mask      PCER1 peripherals mask
+ *
+ * @api
+ */
+#define pmcEnablePidHigh(mask) {                                            \
+  writePMCr(offsetof(Pmc, PMC_PCER1), (mask));                              \
+}
+
+/**
+ * @brief   Disables the clock of one or more peripheral having ID from 32 to
+ *          63.
+ *
+ * @param[in] mask      PCDR1 peripherals mask
+ *
+ * @api
+ */
+#define pmcDisablePidHigh(mask) {                                           \
+  writePMCr(offsetof(Pmc, PMC_PCDR1), (mask));                              \
+}
+
+/**
+ * @brief   Enables the generic clock of a peripheral.
+ *
+ * @param[in] mask      ID peripherals
+ *
+ * @api
+ */
+#define pmcEnableGclk(id) {                                                 \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  writePMCr(offsetof(Pmc, PMC_PCR), PMC_PCR_PID(id));                       \
+  uint32_t pcr = readPMCr(offsetof(Pmc, PMC_PCR));                          \
+  writePMCr(offsetof(Pmc, PMC_PCR), pcr | PMC_PCR_CMD | PMC_PCR_GCKEN);     \
+  while (!(readPMCr(offsetof(Pmc, PMC_SR)) & PMC_SR_GCKRDY));               \
+}
+
+/**
+ * @brief   Disable the generic clock of a peripheral.
+ *
+ * @param[in] mask      ID peripherals
+ *
+ * @api
+ */
+#define pmcDisableGclk(id) {                                                \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  writePMCr(offsetof(Pmc, PMC_PCR), PMC_PCR_PID(id));                       \
+  uint32_t pcr = readPMCr(offsetof(Pmc, PMC_PCR));                          \
+  writePMCr(offsetof(Pmc, PMC_PCR), PMC_PCR_CMD | (pcr & ~(PMC_PCR_GCKEN)));\
+}
+
+/**
+ * @brief   Configure the generic clock of a peripheral.
+ *
+ * @param[in] id           ID peripherals mask
+ * @param[in] clock_source Clock source
+ * @param[in] div          Divider
+ *
+ * @api
+ */
+
+#define pmcConfigGclk(id, clock_source, div) {                              \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  osalDbgCheck(!(clock_source & ~PMC_PCR_GCKCSS_Msk));                      \
+  osalDbgCheck((div > 0));                                                  \
+  osalDbgCheck(!(div << PMC_PCR_GCKDIV_Pos & ~PMC_PCR_GCKDIV_Msk));         \
+  pmcDisableGclk(id);                                                       \
+  writePMCr(offsetof(Pmc, PMC_PCR), PMC_PCR_PID(id));                       \
+  uint32_t pcr = readPMCr(offsetof(Pmc, PMC_PCR) & ~(PMC_PCR_GCKCSS_Msk | PMC_PCR_GCKDIV_Msk); \
+  writePMCr(offsetof(Pmc, PMC_PCR), pcr | clock_source | PMC_PCR_CMD | PMC_PCR_GCKDIV(div - 1));\
+}
+
+/**
+ * @brief   Enable the peripheral clock of a peripheral.
+ *
+ * @param[in] id        ID peripherals mask
+ *
+ * @api
+ */
+#define pmcEnablePeripheral(id) {                                           \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  writePMCr(offsetof(Pmc, PMC_PCR), PMC_PCR_PID(id));                       \
+  uint32_t pcr = readPMCr(offsetof(Pmc, PMC_PCR));                          \
+  writePMCr(offsetof(Pmc, PMC_PCR), pcr | PMC_PCR_CMD | PMC_PCR_EN);        \
+}
+
+/**
+ * @brief   Disable the peripheral clock of a peripheral.
+ *
+ * @param[in] id        ID peripherals mask
+ *
+ * @api
+ */
+#define pmcDisablePeripheral(id) {                                          \
+  osalDbgCheck(id < ID_PERIPH_COUNT);                                       \
+  writePMCr(offsetof(Pmc, PMC_PCR), PMC_PCR_PID(id));                       \
+  uint32_t pcr = readPMCr(offsetof(Pmc, PMC_PCR));                          \
+  writePMCr(offsetof(Pmc, PMC_PCR), (pcr & ~PMC_PCR_EN) | PMC_PCR_CMD);     \
+}
+
+
+/**
+ * @brief   Configure the Audio clock.
+ *
+ * @param[in] nd        Loop Divider Ratio
+ * @param[in] qdpmc     Output Divider Ratio for PMC Clock
+ * @param[in] fracr     Fractional Loop Divider Setting
+ * @param[in] div       Divider Value
+ * @param[in] qaudio    Output Divider Ratio for Pad Clock
+ *
+ * @api
+ */
+#define pmcConfigAudio(nd,qdpmc,fracr,div,qdaudio) {                        \
+ /* Reset audio clock */                                                    \
+ writePMCr(offsetof(Pmc, PMC_AUDIO_PLL0), readPMCr(offsetof(Pmc, PMC_AUDIO_PLL0)) & ~PMC_AUDIO_PLL0_RESETN);\
+ writePMCr(offsetof(Pmc, PMC_AUDIO_PLL0), readPMCr(offsetof(Pmc, PMC_AUDIO_PLL0)) |  PMC_AUDIO_PLL0_RESETN);\
+ /* Configure values */                                                     \
+ writePMCr(offsetof(Pmc, PMC_AUDIO_PLL0), (readPMCr(offsetof(Pmc, PMC_AUDIO_PLL0)) &\
+                       ~PMC_AUDIO_PLL0_PLLFLT_Msk &                         \
+                       ~PMC_AUDIO_PLL0_ND_Msk &                             \
+                       ~PMC_AUDIO_PLL0_QDPMC_Msk) |                         \
+                       PMC_AUDIO_PLL0_PLLFLT_STD |                          \
+                       PMC_AUDIO_PLL0_ND(nd) |                              \
+                       PMC_AUDIO_PLL0_QDPMC(qdpmc));                        \
+ writePMCr(offsetof(Pmc, PMC_AUDIO_PLL1), (readPMCr(offsetof(Pmc, PMC_AUDIO_PLL1)) &\
+                       ~PMC_AUDIO_PLL1_FRACR_Msk &                          \
+                       ~PMC_AUDIO_PLL1_DIV_Msk &                            \
+                       ~PMC_AUDIO_PLL1_QDAUDIO_Msk) |                       \
+                       PMC_AUDIO_PLL1_FRACR(fracr) |                        \
+                       PMC_AUDIO_PLL1_DIV(div)|                             \
+                       PMC_AUDIO_PLL1_QDAUDIO(qdaudio));                    \
+}
+
+/**
+ * @brief   Enable the audio clock of a audio peripheral.
+ *
+ * @param[in] pmcClock  If set TRUE enable the PMC clock
+ * @param[in] padClock  If set TRUE enable the PAD clock
+ *
+ * @api
+ */
+#define pmcEnableAudio(pmcClock, padClock) {                                \
+ uint32_t bits = PMC_AUDIO_PLL0_PLLEN | PMC_AUDIO_PLL0_RESETN;              \
+ uint32_t nbits = 0;                                                        \
+ if(padClock)                                                               \
+   bits |= PMC_AUDIO_PLL0_PADEN;                                            \
+ else                                                                       \
+   nbits |= PMC_AUDIO_PLL0_PADEN;                                           \
+ if(pmcClock)                                                               \
+   bits |= PMC_AUDIO_PLL0_PMCEN;                                            \
+ else                                                                       \
+   nbits |= PMC_AUDIO_PLL0_PMCEN;                                           \
+ writePMCr(offsetof(Pmc, PMC_AUDIO_PLL0), (readPMCr(offsetof(Pmc, PMC_AUDIO_PLL0)) & ~nbits) | bits);\
+ /* Wait for the Audio PLL Startup Time (tSTART = 100 usec) */              \
+ chSysPolledDelayX(US2RTC(SAMA_PCK, 100));                                  \
+}
+
+/**
+ * @brief   Disable the audio clock of a audio peripheral.
+ *
+ * @api
+ */
+#define pmcDisableAudio(){                                                  \
+ writePMCr(offsetof(Pmc, PMC_AUDIO_PLL0), readPMCr(offsetof(Pmc, PMC_AUDIO_PLL0)) & \
+                        ~(PMC_AUDIO_PLL0_PLLEN | PMC_AUDIO_PLL0_RESETN |    \
+                          PMC_AUDIO_PLL0_PADEN | PMC_AUDIO_PLL0_PMCEN));     \
+}
+
+#endif
+
 /** @} */
 
 /**
@@ -518,6 +900,34 @@
  */
 #define pmcDisableSDMMC1() pmcDisablePidHigh(ID_SDMMC1_MSK)
 
+/**
+ * @brief   Enables the CLASSD peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableCLASSD0()   pmcEnablePidHigh(ID_CLASSD_MSK)
+
+/**
+ * @brief   Disables the CLASSD peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableCLASSD0() pmcDisablePidHigh(ID_CLASSD_MSK)
+
+/**
+ * @brief   Enables the CLASSD generic clock.
+ *
+ * @api
+ */
+#define pmcEnableGclkCLASSD0()   pmcEnableGclk(ID_CLASSD)
+
+/**
+ * @brief   Disables the CLASSD generic clock.
+ *
+ * @api
+ */
+#define pmcDisableGclkCLASSD0() pmcDisableGclk(ID_CLASSD)
+
 /**
  * @brief   Enables the TRNG peripheral clock.
  *
@@ -532,6 +942,76 @@
  */
 #define pmcDisableTRNG0() pmcDisablePidHigh(ID_TRNG_MSK)
 
+/**
+ * @brief   Enables the QSPI0 peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableQSPI0() pmcEnablePidHigh(ID_QSPI0_MSK)
+
+/**
+ * @brief   Disables the QSPI0 peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableQSPI0() pmcDisablePidHigh(ID_QSPI0_MSK)
+
+/**
+ * @brief   Enables the QSPI1 peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableQSPI1() pmcEnablePidHigh(ID_QSPI1_MSK)
+
+/**
+ * @brief   Disables the QSPI1 peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableQSPI1() pmcDisablePidHigh(ID_QSPI1_MSK)
+
+/**
+ * @brief   Enables the LCDC peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableLCDC() pmcEnablePidHigh(ID_LCDC_MSK)
+
+/**
+ * @brief   Disables the LCDC peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableLCDC() pmcDisablePidHigh(ID_LCDC_MSK)
+
+/**
+ * @brief   Enables the TWIHS0 peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableTWIHS0() pmcEnablePidLow(ID_TWIHS0_MSK)
+
+/**
+ * @brief   Disables the TWIHS0 peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableTWIHS0() pmcDisablePidLow(ID_TWIHS0_MSK)
+
+/**
+ * @brief   Enables the TWIHS1 peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableTWIHS1() pmcEnablePidLow(ID_TWIHS1_MSK)
+
+/**
+ * @brief   Disables the TWIHS1 peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableTWIHS1() pmcDisablePidLow(ID_TWIHS1_MSK)
+
 /** @} */
 
 /*===========================================================================*/
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_rstc.h b/os/hal/ports/SAMA/SAMA5D2x/sama_rstc.h
new file mode 100644
index 000000000..e390e5eb2
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_rstc.h
@@ -0,0 +1,179 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/sama_rstc.h
+ * @brief   SAMA RSTC helper driver header.
+ *
+ * @addtogroup SAMA5D2x_RSTC
+ * @{
+ */
+
+#ifndef _SAMA_RSTC_
+#define _SAMA_RSTC_
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+/**
+ * @name    RESET SOURCE MACROS
+ * @{
+ */
+/**
+ * @brief   No access allowed.
+ */
+#define RSTC_GENERAL                            0x0U
+
+/**
+ * @brief   Only write access allowed.
+ */
+#define RSTC_WKUP                               0x1U
+
+/**
+ * @brief   Only read access allowed.
+ */
+#define RSTC_WDT                                0x2U
+
+/**
+ * @brief   Read and Write access allowed.
+ */
+#define RSTC_SOFT                               0x3U
+
+/**
+ * @brief   Read and Write access allowed.
+ */
+#define RSTC_USER                               0x4U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings.                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks.                                       */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros.                                                            */
+/*===========================================================================*/
+/**
+ * @name    Generic RSTC operations
+ * @{
+ */
+/**
+ * @brief     Enable/Disable the detection of a low level on the pin NRST
+ *            as User Reset.
+ * @param[in] enable
+ */
+#define rstcSetUserResetEnable(enable) {                                    \
+  if (enable) {                                                             \
+    RSTC->RSTC_MR |= RSTC_MR_URSTEN | RSTC_MR_KEY_PASSWD;                   \
+  } else {                                                                  \
+    RSTC->RSTC_MR &= ~RSTC_MR_URSTEN;                                       \
+    RSTC->RSTC_MR |= RSTC_MR_KEY_PASSWD;                                    \
+  }                                                                         \
+}
+
+/**
+ * @brief     Enable/Disable the interrupt of a User Reset.
+ * @param[in] enable
+ */
+#define rstcSetUserResetInterruptEnable(enable) {                           \
+  if (enable) {                                                             \
+    RSTC->RSTC_MR |= RSTC_MR_URSTIEN | RSTC_MR_KEY_PASSWD;                  \
+  } else {                                                                  \
+    RSTC->RSTC_MR &= ~RSTC_MR_URSTIEN;                                      \
+    RSTC->RSTC_MR |= RSTC_MR_KEY_PASSWD;                                    \
+  }                                                                         \
+}
+
+/**
+ * @brief   Perform a processor and peripheral reset.
+ *
+ * @notapi
+ */
+#define rstcResetProcessorAndPeripheral() {                                 \
+  RSTC->RSTC_CR = RSTC_CR_PERRST | RSTC_CR_PROCRST | RSTC_MR_KEY_PASSWD;    \
+}
+
+/**
+ * @brief   Perform a processor reset.
+ *
+ * @notapi
+ */
+#define rstcResetProcessor() {                                              \
+  RSTC->RSTC_CR = RSTC_CR_PROCRST | RSTC_CR_KEY_PASSWD;                     \
+}
+
+/**
+ * @brief   Perform a peripheral reset.
+ *
+ * @notapi
+ */
+#define rstcResetPeripheral() {                                             \
+  RSTC->RSTC_CR = RSTC_CR_PERRST | RSTC_MR_KEY_PASSWD;                      \
+}
+
+/**
+ * @brief   Report the cause of the last processor reset.
+ *
+ * @param[out] status    Cause of the reset
+ *
+ * @notapi
+ */
+#define rstcGetStatus(status) {                                             \
+  uint32_t sr = RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk;                         \
+  switch (sr) {                                                             \
+  case RSTC_SR_RSTTYP_GENERAL_RST:                                          \
+    status = RSTC_GENERAL;                                                  \
+    break;                                                                  \
+  case RSTC_SR_RSTTYP_WKUP_RST:                                             \
+    status = RSTC_WKUP;                                                     \
+    break;                                                                  \
+  case RSTC_SR_RSTTYP_WDT_RST:                                              \
+    status = RSTC_WDT;                                                      \
+    break;                                                                  \
+  case RSTC_SR_RSTTYP_SOFT_RST:                                             \
+    status = RSTC_SOFT;                                                     \
+    break;                                                                  \
+  case RSTC_SR_RSTTYP_USER_RST:                                             \
+    status = RSTC_USER;                                                     \
+    break;                                                                  \
+  default:                                                                  \
+    break;                                                                  \
+  }                                                                         \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* External declarations.                                                    */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SAMA_RSTC_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c
index 4cf1d527a..35fbab578 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c
@@ -24,7 +24,7 @@
 
 #include "hal.h"
 
-#if HAL_USE_SECUMOD || defined(__DOXYGEN__)
+#if SAMA_USE_SECUMOD || defined(__DOXYGEN__)
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -274,9 +274,11 @@ void sec_lld_start(SECDriver *secp) {
     /*
      * Configure interrupts
      */
+    aicSetIntSourceType(ID_SECUMOD, INT_LEVEL_SENSITIVE);
     aicSetSourcePriority(ID_SECUMOD, SAMA_SECUMOD_IRQ_PRIORITY);
     aicSetSourceHandler(ID_SECUMOD, SAMA_SECUMOD_HANDLER);
 
+    aicSetIntSourceType(ID_SECURAM, INT_LEVEL_SENSITIVE);
     aicSetSourcePriority(ID_SECURAM, SAMA_SECURAM_IRQ_PRIORITY);
     aicSetSourceHandler(ID_SECURAM, SAMA_SECURAM_HANDLER);
 
@@ -592,6 +594,6 @@ uint32_t secumodWriteInternalMemory(uint8_t *data, uint32_t addr, uint32_t size)
   return i;
 }
 
-#endif /* HAL_USE_SECUMOD */
+#endif /* SAMA_USE_SECUMOD */
 
 /** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h
index 5ac8c3c11..c5247af89 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h
@@ -25,7 +25,14 @@
 #ifndef SAMA_SECUMOD_LLD_H
 #define SAMA_SECUMOD_LLD_H
 
-#if HAL_USE_SECUMOD || defined(__DOXYGEN__)
+/**
+ * @brief   Using the SECUMOD driver.
+ */
+#if !defined(SAMA_USE_SECUMOD) || defined(__DOXYGEN__)
+#define SAMA_USE_SECUMOD                         FALSE
+#endif
+
+#if SAMA_USE_SECUMOD || defined(__DOXYGEN__)
 
 #include <string.h>
 /*===========================================================================*/
@@ -558,7 +565,7 @@ extern "C" {
 }
 #endif
 
-#endif /* HAL_USE_SECUMOD */
+#endif /* SAMA_USE_SECUMOD */
 
 #endif /* SAMA_SECUMOD_LLD_H */
 
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.c b/os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.c
new file mode 100644
index 000000000..5251efd17
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.c
@@ -0,0 +1,575 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/sama_tc_lld.c
+ * @brief   SAMA TC support code.
+ *
+ * @addtogroup TC
+ * @{
+ */
+
+#include "hal.h"
+
+#if SAMA_USE_TC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local macros.                                                      */
+/*===========================================================================*/
+
+/**
+ * @brief   Enable write protection on TC registers block.
+ *
+ * @param[in] tcp    pointer to a TC register block
+ *
+ * @notapi
+ */
+#define tcEnableWP(tcp) {                                                     \
+  tcp->TC_WPMR = TC_WPMR_WPKEY_PASSWD | TC_WPMR_WPEN;                         \
+}
+
+/**
+ * @brief   Disable write protection on TC registers block.
+ *
+ * @param[in] tcp    pointer to a TC register block
+ *
+ * @notapi
+ */
+#define tcDisableWP(tcp) {                                                    \
+  tcp->TC_WPMR = TC_WPMR_WPKEY_PASSWD;                                        \
+}
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/**
+ * @brief   TCD0 driver identifier.
+ * @note    The driver TCD0 allocates the timer TC0 when enabled.
+ */
+#if SAMA_USE_TC0 || defined(__DOXYGEN__)
+TCDriver TCD0;
+#endif
+
+/**
+ * @brief   TCD1 driver identifier.
+ * @note    The driver TCD1 allocates the timer TC1 when enabled.
+ */
+#if SAMA_USE_TC1 || defined(__DOXYGEN__)
+TCDriver TCD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types.                                         */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+/**
+ * @brief   Common IRQ handler.
+ * @note    It is assumed that the various sources are only activated if the
+ *          associated callback pointer is not equal to @p NULL in order to not
+ *          perform an extra check in a potentially critical interrupt handler.
+ *
+ * @param[in] tcp      pointer to a @p TCDriver object
+ *
+ * @notapi
+ */
+void tc_lld_serve_interrupt(TCDriver *tcp) {
+  uint32_t sr, imr, i;
+
+  for (i = 0; i < TC_CHANNELS; i++) {
+    sr  = tcp->tim->TC_CHANNEL[i].TC_SR;
+    imr = tcp->tim->TC_CHANNEL[i].TC_IMR;
+    if (((sr & TC_SR_CPCS) != 0) && ((imr & TC_IMR_CPCS) != 0) &&
+       (tcp->config->channels[i].callback != NULL)) {
+      tcp->config->channels[i].callback(tcp);
+    }
+  }
+}
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+#if SAMA_USE_TC0 || defined(__DOXYGEN__)
+#if !defined(SAMA_TC0_SUPPRESS_ISR)
+/**
+ * @brief   TC0 interrupt handler.
+ * @note    It is assumed that this interrupt is only activated if the callback
+ *          pointer is not equal to @p NULL in order to not perform an extra
+ *          check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(SAMA_TC0_HANDLER) {
+
+  OSAL_IRQ_PROLOGUE();
+
+  tc_lld_serve_interrupt(&TCD0);
+  aicAckInt();
+  OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(SAMA_TC0_SUPPRESS_ISR) */
+#endif /* SAMA_USE_TC0 */
+
+#if SAMA_USE_TC1 || defined(__DOXYGEN__)
+#if !defined(SAMA_TC1_SUPPRESS_ISR)
+/**
+ * @brief   TC1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(SAMA_TC1_HANDLER) {
+
+  OSAL_IRQ_PROLOGUE();
+
+  tc_lld_serve_interrupt(&TCD1);
+  aicAckInt();
+  OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(SAMA_TC1_SUPPRESS_ISR) */
+#endif /* SAMA_USE_TC1 */
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+/**
+ * @brief   Low level TC driver initialization.
+ *
+ * @notapi
+ */
+void tc_lld_init(void) {
+
+#if SAMA_USE_TC0
+#if SAMA_HAL_IS_SECURE
+  mtxConfigPeriphSecurity(MATRIX1, ID_TC0, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+  /* Driver initialization.*/
+  tcObjectInit(&TCD0);
+  TCD0.channels = TC_CHANNELS;
+  TCD0.tim = TC0;
+  TCD0.clock = SAMA_TC0CLK;
+#endif
+
+#if SAMA_USE_TC1
+#if SAMA_HAL_IS_SECURE
+  mtxConfigPeriphSecurity(MATRIX1, ID_TC1, SECURE_PER);
+#endif /* SAMA_HAL_IS_SECURE */
+  /* Driver initialization.*/
+  tcObjectInit(&TCD1);
+  TCD1.channels = TC_CHANNELS;
+  TCD1.tim = TC1;
+  TCD1.clock = SAMA_TC1CLK;
+#endif
+
+}
+
+/**
+ * @brief   Configures and activates the TC peripheral.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ *
+ * @notapi
+ */
+void tc_lld_start(TCDriver *tcp) {
+  uint32_t rc = 0;
+
+  if (tcp->state == TC_STOP) {
+    /* Clock activation.*/
+#if SAMA_USE_TC0
+    if (&TCD0 == tcp) {
+      pmcEnableTC0();
+#if !defined(SAMA_TC0_SUPPRESS_ISR)
+      aicSetSourcePriority(ID_TC0, SAMA_TC0_IRQ_PRIORITY);
+      aicSetSourceHandler(ID_TC0, SAMA_TC0_HANDLER);
+      aicEnableInt(ID_TC0);
+#endif
+    }
+#endif
+
+#if SAMA_USE_TC1
+    if (&TCD1 == tcp) {
+      pmcEnableTC1();
+#if !defined(SAMA_TC1_SUPPRESS_ISR)
+      aicSetSourcePriority(ID_TC1, SAMA_TC1_IRQ_PRIORITY);
+      aicSetSourceHandler(ID_TC1, SAMA_TC1_HANDLER);
+      aicEnableInt(ID_TC1);
+#endif
+    }
+#endif
+  }
+  /* Disable Write Protection */
+  tcDisableWP(tcp->tim);
+  /* Output enables*/
+   switch (tcp->config->channels[0].mode & TC_OUTPUT_MASK) {
+   case TC_OUTPUT_ACTIVE:
+     rc = (tcp->clock) / (tcp->config->channels[0].frequency);
+     tcp->tim->TC_CHANNEL[0].TC_EMR = TC_EMR_NODIVCLK;
+     tcp->tim->TC_CHANNEL[0].TC_CMR = TC_CMR_WAVE | TC_CMR_ACPA_SET |
+                                      TC_CMR_ACPC_CLEAR | TC_CMR_WAVSEL_UP_RC;
+
+     tcp->tim->TC_CHANNEL[0].TC_RC = TC_RC_RC(rc);
+     tcp->tim->TC_CHANNEL[0].TC_SR;          /* Clear pending IRQs.          */
+   default:
+     ;
+   }
+   switch (tcp->config->channels[1].mode & TC_OUTPUT_MASK) {
+   case TC_OUTPUT_ACTIVE:
+     rc = (tcp->clock) / (tcp->config->channels[1].frequency);
+     tcp->tim->TC_CHANNEL[1].TC_EMR = TC_EMR_NODIVCLK;
+     tcp->tim->TC_CHANNEL[1].TC_CMR = TC_CMR_WAVE | TC_CMR_ACPA_SET |
+                                      TC_CMR_ACPC_CLEAR | TC_CMR_WAVSEL_UP_RC;
+
+     tcp->tim->TC_CHANNEL[1].TC_RC = TC_RC_RC(rc);
+     tcp->tim->TC_CHANNEL[1].TC_SR;          /* Clear pending IRQs.          */
+   default:
+     ;
+   }
+   switch (tcp->config->channels[2].mode & TC_OUTPUT_MASK) {
+   case TC_OUTPUT_ACTIVE:
+     rc = (tcp->clock) / (tcp->config->channels[2].frequency);
+     tcp->tim->TC_CHANNEL[2].TC_EMR = TC_EMR_NODIVCLK;
+     tcp->tim->TC_CHANNEL[2].TC_CMR = TC_CMR_WAVE | TC_CMR_ACPA_SET |
+                                      TC_CMR_ACPC_CLEAR | TC_CMR_WAVSEL_UP_RC;
+
+     tcp->tim->TC_CHANNEL[2].TC_RC = TC_RC_RC(rc);
+     tcp->tim->TC_CHANNEL[2].TC_SR;                       /* Clear pending IRQs.          */
+   default:
+     ;
+   }
+   /* Enable Write Protection */
+   tcEnableWP(tcp->tim);
+}
+
+/**
+ * @brief   Deactivates the TC peripheral.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ *
+ * @notapi
+ */
+void tc_lld_stop(TCDriver *tcp) {
+
+  /* If in ready state then disables the TC clock.*/
+  if (tcp->state == TC_READY) {
+#if SAMA_USE_TC0
+    if (&TCD0 == tcp) {
+      aicDisableInt(ID_TC0);
+      pmcDisableTC0();
+    }
+#endif
+
+#if SAMA_USE_TC1
+    if (&TCD1 == tcp) {
+      aicDisableInt(ID_TC1);
+      pmcDisableTC1();
+    }
+#endif
+  }
+}
+
+/**
+ * @brief   Enables a TC channel.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @post    The channel is active using the specified configuration.
+ * @note    The function has effect at the next cycle start.
+ * @note    Channel notification is not enabled.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ * @param[in] width     TC pulse width as clock pulses number
+ *
+ * @notapi
+ */
+void tc_lld_enable_channel(TCDriver *tcp,
+                           tcchannel_t channel,
+                           tccnt_t width) {
+  /* Disable Write Protection */
+  tcDisableWP(tcp->tim);
+
+  /* Changing channel duty cycle on the fly.*/
+  uint32_t rc = tcp->tim->TC_CHANNEL[channel].TC_RC;
+  tcp->tim->TC_CHANNEL[channel].TC_RA = TC_RA_RA((100 - width) * rc / 100);
+  tcp->tim->TC_CHANNEL[channel].TC_CCR = TC_CCR_CLKEN;
+  tcp->tim->TC_CHANNEL[channel].TC_CCR = TC_CCR_SWTRG;
+
+  /* Enable Write Protection */
+  tcEnableWP(tcp->tim);
+}
+
+/**
+ * @brief   Disables a TC channel and its notification.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @post    The channel is disabled and its output line returned to the
+ *          idle state.
+ * @note    The function has effect at the next cycle start.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @notapi
+ */
+void tc_lld_disable_channel(TCDriver *tcp, tcchannel_t channel) {
+
+  tcp->tim->TC_CHANNEL[channel].TC_CCR = TC_CCR_CLKDIS;
+}
+
+/**
+ * @brief   Enables a channel de-activation edge notification.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @pre     The channel must have been activated using @p tcEnableChannel().
+ * @note    If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @notapi
+ */
+void tc_lld_enable_channel_notification(TCDriver *tcp,
+                                        tcchannel_t channel) {
+  tcp->tim->TC_CHANNEL[channel].TC_IER |= TC_IER_CPCS;
+}
+
+/**
+ * @brief   Disables a channel de-activation edge notification.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @pre     The channel must have been activated using @p tcEnableChannel().
+ * @note    If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @notapi
+ */
+void tc_lld_disable_channel_notification(TCDriver *tcp,
+                                         tcchannel_t channel) {
+
+  tcp->tim->TC_CHANNEL[channel].TC_IDR |= TC_IDR_CPCS;
+}
+
+/**
+ * @brief   Changes TC channel's frequency.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @post    The channel must be enabled using @p tcEnableChannel().
+ * @note    Depending on the hardware implementation this function has
+ *          effect starting on the next cycle (recommended implementation)
+ *          or immediately (fallback implementation).
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ */
+
+void tcChangeChannelFrequency(TCDriver *tcp,
+                              tcchannel_t channel,uint32_t frequency) {
+  tcDisableWP(tcp->tim);
+  uint32_t rc =(tcp->clock) / (frequency);
+  tcp->tim->TC_CHANNEL[channel].TC_RC = TC_RC_RC(rc);
+  tcEnableWP(tcp->tim);
+}
+/**
+ * @brief   TC Driver initialization.
+ *
+ * @init
+ */
+void tcInit(void) {
+
+  tc_lld_init();
+}
+
+/**
+ * @brief   Initializes the standard part of a @p TCDriver structure.
+ *
+ * @param[out] tcp      pointer to a @p TCDriver object
+ *
+ * @init
+ */
+void tcObjectInit(TCDriver *tcp) {
+
+  tcp->state    = TC_STOP;
+  tcp->config   = NULL;
+  tcp->enabled  = 0;
+  tcp->channels = 0;
+}
+
+
+/**
+ * @brief   Configures and activates the TC peripheral.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] config    pointer to a @p TCConfig object
+ *
+ * @api
+ */
+void tcStart(TCDriver *tcp, const TCConfig *config) {
+
+  osalDbgCheck((tcp != NULL) && (config != NULL));
+
+  osalSysLock();
+  osalDbgAssert((tcp->state == TC_STOP) || (tcp->state == TC_READY),
+                "invalid state");
+  tcp->config = config;
+  tc_lld_start(tcp);
+  tcp->enabled = 0;
+  tcp->state = TC_READY;
+  osalSysUnlock();
+}
+
+/**
+ * @brief   Deactivates the TC peripheral.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ *
+ * @api
+ */
+void tcStop(TCDriver *tcp) {
+
+  osalDbgCheck(tcp != NULL);
+
+  osalSysLock();
+
+  osalDbgAssert((tcp->state == TC_STOP) || (tcp->state == TC_READY),
+                "invalid state");
+
+  tc_lld_stop(tcp);
+  tcp->enabled = 0;
+  tcp->config  = NULL;
+  tcp->state   = TC_STOP;
+
+  osalSysUnlock();
+}
+
+/**
+ * @brief   Enables a TC channel.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @post    The channel is active using the specified configuration.
+ * @note    Depending on the hardware implementation this function has
+ *          effect starting on the next cycle (recommended implementation)
+ *          or immediately (fallback implementation).
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ * @param[in] width     TC pulse width as clock pulses number
+ *
+ * @api
+ */
+void tcEnableChannel(TCDriver *tcp,
+                     tcchannel_t channel,
+                     tccnt_t width) {
+
+  osalDbgCheck((tcp != NULL) && (channel < tcp->channels));
+
+  osalSysLock();
+
+  osalDbgAssert(tcp->state == TC_READY, "not ready");
+
+  tcEnableChannelI(tcp, channel, width);
+
+  osalSysUnlock();
+}
+
+/**
+ * @brief   Disables a TC channel and its notification.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @post    The channel is disabled and its output line returned to the
+ *          idle state.
+ * @note    Depending on the hardware implementation this function has
+ *          effect starting on the next cycle (recommended implementation)
+ *          or immediately (fallback implementation).
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @api
+ */
+void tcDisableChannel(TCDriver *tcp, tcchannel_t channel) {
+
+  osalDbgCheck((tcp != NULL) && (channel < tcp->channels));
+
+  osalSysLock();
+
+  osalDbgAssert(tcp->state == TC_READY, "not ready");
+
+  tcDisableChannelI(tcp, channel);
+
+  osalSysUnlock();
+}
+
+/**
+ * @brief   Enables a channel de-activation edge notification.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @pre     The channel must have been activated using @p tcEnableChannel().
+ * @note    If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @api
+ */
+void tcEnableChannelNotification(TCDriver *tcp, tcchannel_t channel) {
+
+  osalDbgCheck((tcp != NULL) && (channel < tcp->channels));
+
+  osalSysLock();
+
+  osalDbgAssert(tcp->state == TC_READY, "not ready");
+  osalDbgAssert((tcp->enabled & ((tcchnmsk_t)1U << (tcchnmsk_t)channel)) != 0U,
+                "channel not enabled");
+  osalDbgAssert(tcp->config->channels[channel].callback != NULL,
+                "undefined channel callback");
+
+  tcEnableChannelNotificationI(tcp, channel);
+
+  osalSysUnlock();
+}
+
+/**
+ * @brief   Disables a channel de-activation edge notification.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @pre     The channel must have been activated using @p tcEnableChannel().
+ * @note    If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @api
+ */
+void tcDisableChannelNotification(TCDriver *tcp, tcchannel_t channel) {
+
+  osalDbgCheck((tcp != NULL) && (channel < tcp->channels));
+
+  osalSysLock();
+
+  osalDbgAssert(tcp->state == TC_READY, "not ready");
+  osalDbgAssert((tcp->enabled & ((tcchnmsk_t)1U << (tcchnmsk_t)channel)) != 0U,
+                "channel not enabled");
+  osalDbgAssert(tcp->config->channels[channel].callback != NULL,
+                "undefined channel callback");
+
+  tcDisableChannelNotificationI(tcp, channel);
+
+  osalSysUnlock();
+}
+
+#endif /* SAMA_USE_TC */
+
+/** @} */
+
+
+
+
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.h b/os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.h
new file mode 100644
index 000000000..8cf1a8e1a
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_tc_lld.h
@@ -0,0 +1,364 @@
+/*
+    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/**
+ * @file    SAMA5D2x/sama_tc_lld.h
+ * @brief   SAMA TC subsystem low level driver header.
+ *
+ * @addtogroup TC
+ * @{
+ */
+
+#ifndef SAMA_TC_LLD_H
+#define SAMA_TC_LLD_H
+
+/**
+ * @brief   Using the TC driver.
+ */
+#if !defined(SAMA_USE_TC) || defined(__DOXYGEN__)
+#define SAMA_USE_TC                              FALSE
+#endif
+
+#if SAMA_USE_TC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants.                                                         */
+/*===========================================================================*/
+
+/**
+ * @brief   Number of TC channels per TC driver.
+ */
+#define TC_CHANNELS                             TCCHANNEL_NUMBER
+
+/**
+ * @name    TC output mode macros
+ * @{
+ */
+/**
+ * @brief   Standard output modes mask.
+ */
+#define TC_OUTPUT_MASK                          0x0FU
+
+/**
+ * @brief   Output not driven, callback only.
+ */
+#define TC_OUTPUT_DISABLED                      0x00U
+
+/**
+ * @brief   Output active.
+ */
+#define TC_OUTPUT_ACTIVE                        0x01U
+
+/** @} */
+
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+
+/**
+ * @brief   Driver state machine possible states.
+ */
+typedef enum {
+  TC_UNINIT = 0,                    /**< Not initialized.                   */
+  TC_STOP = 1,                      /**< Stopped.                           */
+  TC_READY = 2                      /**< Ready.                             */
+} tcstate_t;
+
+/**
+ * @brief   Type of a structure representing a TC driver.
+ */
+typedef struct TCDriver TCDriver;
+
+/**
+ * @brief   Type of a TC notification callback.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ */
+typedef void (*tccallback_t)(TCDriver *tcp);
+
+
+/*===========================================================================*/
+/* Driver pre-compile time settings.                                         */
+/*===========================================================================*/
+
+/**
+ * @name    Configuration options
+ * @{
+ */
+/**
+ * @brief   TCD0 driver enable switch.
+ * @details If set to @p TRUE the support for TCD0 is included.
+ * @note    The default is @p TRUE.
+ */
+#if !defined(SAMA_USE_TC0) || defined(__DOXYGEN__)
+#define SAMA_USE_TC0                        FALSE
+#endif
+
+/**
+ * @brief   TCD1 driver enable switch.
+ * @details If set to @p TRUE the support for TCD1 is included.
+ * @note    The default is @p TRUE.
+ */
+#if !defined(SAMA_USE_TC1) || defined(__DOXYGEN__)
+#define SAMA_USE_TC1                        FALSE
+#endif
+
+/**
+ * @brief   TCD0 interrupt priority level setting.
+ */
+#if !defined(SAMA_TC0_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SAMA_TC0_IRQ_PRIORITY               2
+#endif
+
+/**
+ * @brief   TCD1 interrupt priority level setting.
+ */
+#if !defined(SAMA_TC1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SAMA_TC1_IRQ_PRIORITY               2
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Configuration checks.                                                     */
+/*===========================================================================*/
+
+#if !SAMA_USE_TC0 && !SAMA_USE_TC1
+#error "TC driver activated but no TC peripheral assigned"
+#endif
+
+/* Checks on allocation of TCx units.*/
+#if SAMA_USE_TC0
+#if defined(SAMA_TC0_IS_USED)
+#error "TC0 is already used"
+#else
+#define SAMA_TC0_IS_USED
+#endif
+#endif
+
+/* Checks on allocation of TCx units.*/
+#if SAMA_USE_TC1
+#if defined(SAMA_TC1_IS_USED)
+#error "TC1 is already used"
+#else
+#define SAMA_TC1_IS_USED
+#endif
+#endif
+/*===========================================================================*/
+/* Driver data structures and types.                                         */
+/*===========================================================================*/
+
+/**
+ * @brief   Type of a TC mode.
+ */
+typedef uint32_t tcmode_t;
+
+/**
+ * @brief   Type of a TC channel.
+ */
+typedef uint8_t tcchannel_t;
+
+/**
+ * @brief   Type of a channels mask.
+ */
+typedef uint32_t tcchnmsk_t;
+
+/**
+ * @brief   Type of a TC counter.
+ */
+typedef uint32_t tccnt_t;
+
+/**
+ * @brief   Type of a TC driver channel configuration structure.
+ */
+typedef struct {
+  /**
+   * @brief Channel active logic level.
+   */
+  tcmode_t                  mode;
+  /**
+   * @brief   Timer clock in Hz.
+   * @note    The low level can use assertions in order to catch invalid
+   *          frequency specifications.
+   */
+  uint32_t                  frequency;
+  /**
+   * @brief Channel callback pointer.
+   * @note  This callback is invoked on the channel compare event. If set to
+   *        @p NULL then the callback is disabled.
+   */
+  tccallback_t              callback;
+  /* End of the mandatory fields.*/
+} TCChannelConfig;
+
+/**
+ * @brief   Type of a TC driver configuration structure.
+ */
+typedef struct {
+  /**
+   * @brief Channels configurations.
+   */
+  TCChannelConfig           channels[TC_CHANNELS];
+  /* End of the mandatory fields.*/
+} TCConfig;
+
+/**
+ * @brief   Structure representing a TC driver.
+ */
+struct TCDriver {
+  /**
+   * @brief Driver state.
+   */
+  tcstate_t                 state;
+  /**
+   * @brief Current driver configuration data.
+   */
+  const TCConfig            *config;
+  /**
+   * @brief   Mask of the enabled channels.
+   */
+  tcchnmsk_t                enabled;
+  /**
+   * @brief   Number of channels in this instance.
+   */
+  tcchannel_t              channels;
+  /* End of the mandatory fields.*/
+  /**
+   * @brief Timer base clock.
+   */
+  uint32_t                  clock;
+  /**
+   * @brief Pointer to the TCx registers block.
+   */
+  Tc                        *tim;
+};
+
+/*===========================================================================*/
+/* Driver macros.                                                            */
+/*===========================================================================*/
+/**
+ * @brief   Enables a TC channel.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @post    The channel is active using the specified configuration.
+ * @note    Depending on the hardware implementation this function has
+ *          effect starting on the next cycle (recommended implementation)
+ *          or immediately (fallback implementation).
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ * @param[in] width     TC pulse width as clock pulses number
+ *
+ * @iclass
+ */
+#define tcEnableChannelI(tcp, channel, width) do {                          \
+  (tcp)->enabled |= ((tcchnmsk_t)1U << (tcchnmsk_t)(channel));              \
+  tc_lld_enable_channel(tcp, channel, width);                               \
+} while (false)
+
+/**
+ * @brief   Disables a TC channel.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @post    The channel is disabled and its output line returned to the
+ *          idle state.
+ * @note    Depending on the hardware implementation this function has
+ *          effect starting on the next cycle (recommended implementation)
+ *          or immediately (fallback implementation).
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @iclass
+ */
+#define tcDisableChannelI(tcp, channel) do {                                \
+  (tcp)->enabled &= ~((tcchnmsk_t)1U << (tcchnmsk_t)(channel));             \
+  tc_lld_disable_channel(tcp, channel);                                     \
+} while (false)
+
+/**
+ * @brief   Returns a TC channel status.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @iclass
+ */
+#define tcIsChannelEnabledI(tcp, channel)                                   \
+  (((tcp)->enabled & ((tcchnmsk_t)1U << (tcchnmsk_t)(channel))) != 0U)
+
+/**
+ * @brief   Enables a channel de-activation edge notification.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @pre     The channel must have been activated using @p tcEnableChannel().
+ * @note    If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @iclass
+ */
+#define tcEnableChannelNotificationI(tcp, channel)                          \
+  tc_lld_enable_channel_notification(tcp, channel)
+
+/**
+ * @brief   Disables a channel de-activation edge notification.
+ * @pre     The TC unit must have been activated using @p tcStart().
+ * @pre     The channel must have been activated using @p tcEnableChannel().
+ * @note    If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] tcp       pointer to a @p TCDriver object
+ * @param[in] channel   TC channel identifier (0...channels-1)
+ *
+ * @iclass
+ */
+#define tcDisableChannelNotificationI(tcp, channel)                         \
+  tc_lld_disable_channel_notification(tcp, channel)
+
+/*===========================================================================*/
+/* External declarations.                                                    */
+/*===========================================================================*/
+
+#if SAMA_USE_TC0 && !defined(__DOXYGEN__)
+extern TCDriver TCD0;
+#endif
+
+#if SAMA_USE_TC1 && !defined(__DOXYGEN__)
+extern TCDriver TCD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  void tcInit(void);
+  void tcObjectInit(TCDriver *tcp);
+  void tcStart(TCDriver *tcp, const TCConfig *config);
+  void tcStop(TCDriver *tcp);
+  void tcEnableChannel(TCDriver *tcp,
+                       tcchannel_t channel,
+                       tccnt_t width);
+  void tcDisableChannel(TCDriver *tcp, tcchannel_t channel);
+  void tcEnableChannelNotification(TCDriver *tcp, tcchannel_t channel);
+  void tcDisableChannelNotification(TCDriver *tcp, tcchannel_t channel);
+  void tcChangeChannelFrequency(TCDriver *tcp, tcchannel_t channel, uint32_t frequency);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SAMA_USE_TC */
+
+#endif /* SAMA_TC_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_trng.c b/os/hal/ports/SAMA/SAMA5D2x/sama_trng.c
deleted file mode 100644
index 287d37403..000000000
--- a/os/hal/ports/SAMA/SAMA5D2x/sama_trng.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
-    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-*/
-
-/**
- * @file    SAMA5D2x/sama_trng.c
- * @brief   SAMA TRNG support code.
- *
- * @addtogroup SAMA5D2x_TRNG
- * @{
- */
-
-#include "hal.h"
-
-#if (HAL_USE_TRNG) || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local macros.                                                      */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported variables.                                                */
-/*===========================================================================*/
-TRNGDriver TRNGD0;
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-/**
- * @brief   Low level TRNG driver initialization.
- *
- * @notapi
- */
-void trng_lld_init(void) {
-#if SAMA_HAL_IS_SECURE
-  mtxConfigPeriphSecurity(MATRIX1, ID_TRNG, SECURE_PER);
-#endif /* SAMA_HAL_IS_SECURE */
-  /* Driver initialization.*/
-  TRNGD0.state    = TRNG_STOP;
-  TRNGD0.trng     = TRNG;
-}
-
-/**
- * @brief   Configures and activates the TRNG peripheral.
- *
- * @param[in] trngp     pointer to the @p TRNGDriver object
- *
- * @notapi
- */
-void trng_lld_start(TRNGDriver *trngp) {
-
-  /* Configures the peripheral. */
-  if (trngp->state == TRNG_STOP) {
-
-    /* Enable the TRNG peripheral clock. */
-    pmcEnableTRNG0();
-
-    /* Enable the TRNG. */
-    trngp->trng->TRNG_CR = TRNG_CR_ENABLE | TRNG_CR_KEY_PASSWD;
-  }
-}
-
-/**
- * @brief   Deactivates the TRNG peripheral.
- *
- * @param[in] trngp     pointer to the @p TRNGDriver object
- *
- * @notapi
- */
-void trng_lld_stop(TRNGDriver *trngp) {
-
-  if (trngp->state == TRNG_READY) {
-    /* Disable the TRNG. */
-    trngp->trng->TRNG_CR = TRNG_CR_KEY_PASSWD;
-    /* Disable the TRNG clock. */
-    pmcDisableTRNG0();
-  }
-}
-
-/**
- * @brief   Get random number from TRNG.
- *
- * @param[in] trngp     pointer to the @p TRNGDriver object
- * @return    TRNG_ODATA  content of the TRNG_ODATA register
- *
- * @notapi
- */
-uint32_t trng_lld_get_random_number(TRNGDriver *trngp) {
-
-  while (!(trngp->trng->TRNG_ISR & TRNG_ISR_DATRDY));
-  return trngp->trng->TRNG_ODATA;
-}
-
-/**
- * @brief   TRNG driver initialization.
- *
- * @notapi
- */
-void trngInit(void) {
-
-  trng_lld_init();
-}
-
-/**
- * @brief   Configures and activates the TRNG peripheral.
- *
- * @param[in] trngp     pointer to the @p TRNGDriver object
- *
- * @api
- */
-void trngStart(TRNGDriver *trngp) {
-
-  osalDbgCheck(trngp != NULL);
-
-  osalSysLock();
-  osalDbgAssert((trngp->state == TRNG_STOP) ||
-                (trngp->state == TRNG_READY), "invalid state");
-  trng_lld_start(trngp);
-  trngp->state = TRNG_READY;
-  osalSysUnlock();
-}
-
-/**
- * @brief   Deactivates the TRNG peripheral.
- *
- * @param[in] trngp    pointer to the @p TRNGDriver object
- *
- * @api
- */
-void trngStop(TRNGDriver *trngp) {
-
-  osalDbgCheck(trngp != NULL);
-
-  osalSysLock();
-  osalDbgAssert((trngp->state == TRNG_STOP) ||
-                (trngp->state == TRNG_READY), "invalid state");
-
-  trng_lld_stop(trngp);
-  trngp->state = TRNG_STOP;
-  osalSysUnlock();
-}
-
-/**
- * @brief   Get random number from TRNG.
- *
- * @param[in] trngp     pointer to the @p CLASSDDriver object
- * @return    num       random number generated
- *
- * @api
- */
-uint32_t trngGetRandomNumber(TRNGDriver *trngp) {
-
-  osalDbgCheck(trngp != NULL);
-
-  uint32_t num = trng_lld_get_random_number(trngp);
-  return num;
-}
-
-#endif /* HAL_USE_TRNG == TRUE */
-
-/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_trng.h b/os/hal/ports/SAMA/SAMA5D2x/sama_trng.h
deleted file mode 100644
index ba9ab34a9..000000000
--- a/os/hal/ports/SAMA/SAMA5D2x/sama_trng.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-*/
-
-/**
- * @file    SAMA5D2x/sama_trng.h
- * @brief   SAMA TRNG support macros and structures.
- *
- * @addtogroup SAMA5D2x_TRNG
- * @{
- */
-
-#ifndef SAMA_TRNG_LLD_H
-#define SAMA_TRNG_LLD_H
-
-/**
- * @brief   Using the TRNG driver.
- */
-#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__)
-#define HAL_USE_TRNG                           FALSE
-#endif
-
-#if (HAL_USE_TRNG) || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver constants.                                                         */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver pre-compile time settings.                                         */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Derived constants and error checks.                                       */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver data structures and types.                                         */
-/*===========================================================================*/
-
-/**
- * @brief   Driver state machine possible states.
- */
-typedef enum {
-  TRNG_UNINIT = 0,                  /**< Not initialized.                   */
-  TRNG_STOP = 1,                    /**< Stopped.                           */
-  TRNG_READY = 2                    /**< Ready.                             */
-} trngstate_t;
-
-/**
- * @brief   Type of a structure representing an CLASSD driver.
- */
-typedef struct TRNGDriver TRNGDriver;
-
-/**
- * @brief   Structure representing an TRNG driver.
- */
-struct TRNGDriver {
-  /**
-   * @brief   Driver state.
-   */
-  trngstate_t               state;
-  /**
-   * @brief   Pointer to the WDT registers block.
-   */
-  Trng                      *trng;
-};
-
-/*===========================================================================*/
-/* Driver macros.                                                            */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* External declarations.                                                    */
-/*===========================================================================*/
-
-extern TRNGDriver TRNGD0;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-  void trngInit(void);
-  void trngStart(TRNGDriver *trngp);
-  void trngStop(TRNGDriver *trngp);
-  uint32_t trngGetRandomNumber(TRNGDriver *trngp);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HAL_USE_TRNG */
-
-#endif /* SAMA_TRNG_LLD_H */
-
-/** @} */
-- 
cgit v1.2.3