/*
** ###################################################################
**     Processors:          MIMX8DX1AVLFZ
**                          MIMX8DX1AVOFZ
**
**     Compilers:           GNU C Compiler
**                          IAR ANSI C/C++ Compiler for ARM
**                          Keil ARM C/C++ Compiler
**
**     Reference manual:    IMX8DQXPRM, Rev. E, 6/2019
**     Version:             rev. 4.0, 2020-06-19
**     Build:               b200806
**
**     Abstract:
**         Provides a system configuration function and a global variable that
**         contains the system frequency. It configures the device and initializes
**         the oscillator (PLL) that is part of the microcontroller device.
**
**     Copyright 2016 Freescale Semiconductor, Inc.
**     Copyright 2016-2020 NXP
**     All rights reserved.
**
**     SPDX-License-Identifier: BSD-3-Clause
**
**     http:                 www.nxp.com
**     mail:                 support@nxp.com
**
**     Revisions:
**     - rev. 1.0 (2016-06-02)
**         Initial version.
**     - rev. 2.0 (2017-08-23)
**         RevA Header EAR
**     - rev. 3.0 (2018-08-22)
**         RevB Header EAR
**     - rev. 4.0 (2020-06-19)
**         RevC Header RFP
**
** ###################################################################
*/

/*!
 * @file MIMX8DX1_cm4
 * @version 1.0
 * @date 060820
 * @brief Device specific configuration file for MIMX8DX1_cm4 (implementation file)
 *
 * Provides a system configuration function and a global variable that contains
 * the system frequency. It configures the device and initializes the oscillator
 * (PLL) that is part of the microcontroller device.
 */

#include <stdint.h>
#include "fsl_device_registers.h"

/* ----------------------------------------------------------------------------
   -- Core clock
   ---------------------------------------------------------------------------- */

uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
static sc_ipc_t ipcHandle;

/* ----------------------------------------------------------------------------
   -- SystemInit()
   ---------------------------------------------------------------------------- */

void SystemInit(void)
{
#if (ENABLE_ECC_DEBUG)
    volatile uint32_t *p = (uint32_t *)0xE0080480U;

    /* Configure LMEM Parity/ECC Control Register
    ;
    ; Note: ECC Multi-bit IRQ should be disabled
    ;       prior to list/dump of locations that
    ;       have not been written to avoid vectoring
    ;       to the NMI
    ;
    ; 31:22 RESERVED
    ; 21    Enable Cache Parity IRQ
    ; 20    Enable Cache Parity Report
    ; 19:17 RESERVED
    ; 16    Enable RAM Parity Reporting
    ; 15:10 RESERVED
    ; 9     Enable RAM ECC 1-bit IRQ
    ; 8     Enable RAM ECC 1-bit Report
    ; 7:2   RESERVED
    ; 1     Enable RAM ECC Multi-bit IRQ
    ; 0     Enable RAM ECC Multi-bit
    */
    *p = 0x00300003;
#endif

#if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
    SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access */
#endif                                                 /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */

#if (DISABLE_WDOG)
    CM4__WDOG->CNT   = WDOG_UPDATE_KEY;
    CM4__WDOG->TOVAL = 0xFFFF;
    CM4__WDOG->CS    = (uint32_t)((CM4__WDOG->CS) & ~WDOG_CS_EN_MASK) | WDOG_CS_UPDATE_MASK;
#endif /* (DISABLE_WDOG) */

    /* Initialize Cache */
    /* Enable Code Bus Cache */
    /* set command to invalidate all ways, and write GO bit to initiate command */
    LMEM->PCCCR |= LMEM_PCCCR_INVW1_MASK | LMEM_PCCCR_INVW0_MASK;
    LMEM->PCCCR |= LMEM_PCCCR_GO_MASK;
    /* Wait until the command completes */
    while ((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) != 0UL)
    {
    }
    /* Enable cache, enable write buffer */
    LMEM->PCCCR |= (LMEM_PCCCR_ENWRBUF_MASK | LMEM_PCCCR_ENCACHE_MASK);

    /* Enable System Bus Cache */
    /* set command to invalidate all ways, and write GO bit to initiate command */
    LMEM->PSCCR |= LMEM_PSCCR_INVW1_MASK | LMEM_PSCCR_INVW0_MASK;
    LMEM->PSCCR |= LMEM_PSCCR_GO_MASK;
    /* Wait until the command completes */
    while ((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) != 0UL)
    {
    }
    /* Enable cache, enable write buffer */
    LMEM->PSCCR |= (LMEM_PSCCR_ENWRBUF_MASK | LMEM_PSCCR_ENCACHE_MASK);
    /* i.MX8QX systemInit */
}

/* ----------------------------------------------------------------------------
   -- SystemCoreClockUpdate()
   ---------------------------------------------------------------------------- */

void SystemCoreClockUpdate(void)
{
    /* i.MX8QX SystemCoreClockUpdate */
    sc_err_t err;
    uint32_t freq = SystemCoreClock;

    err = sc_pm_get_clock_rate(ipcHandle, SC_R_M4_0_PID0, SC_PM_CLK_CPU, &freq);

    if (SC_ERR_NONE == err)
    {
        SystemCoreClock = freq;
    }
}

/* ----------------------------------------------------------------------------
   -- SystemInitScfwIpc()
   ---------------------------------------------------------------------------- */

void SystemInitScfwIpc(void)
{
    sc_ipc_t ipc;
    sc_err_t err;

    err = sc_ipc_open(&ipc, (sc_ipc_id_t)CM4__MU1_A);

    if (err == SC_ERR_NONE)
    {
        ipcHandle = ipc;
    }
    else
    {
        ipcHandle = 0;
    }
}

/* ----------------------------------------------------------------------------
   -- SystemGetScfwIpcHandle()
   ---------------------------------------------------------------------------- */

sc_ipc_t SystemGetScfwIpcHandle(void)
{
    return ipcHandle;
}
