/*******************************************************************************
 * Copyright (c) 2018-2021 Renesas Electronics Corporation. All rights reserved.
 *
 *     RENESAS ELECTRONICS CONFIDENTIAL AND PROPRIETARY
 *
 * This software is provided as reference/sample code under the license
 * agreement between Renesas Electronics Corporation and licensee (the
 * "License Agreement") and shall be treated as specified in the License
 * Agreement.
 * These instructions, statements, and software are the confidential
 * information of Renesas Electronics Corporation. They must be used and
 * modified solely for the purpose for which it was furnished by Renesas
 * Electronics Corporation. All or part of these instructions, statements and
 * software must not be reproduced nor disclosed to any third party in any
 * form, unless permitted by the License Agreement.
 *
 * THIS SOFTWARE IS PROVIDED BY RENESAS ELEOCTRONICS CORPORATION "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
 * SATISFACTORY QUALITY, ACCURACY, TITLE AND NON-INFRINGEMENT ARE DISCLAIMED.
 * IN NO EVENT SHALL RENESAS ELECTRONICS CORPORATION BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 ******************************************************************************/

/*******************************************************************************
 * DESCRIPTION   : CPG initialize
 ******************************************************************************/
 /******************************************************************************
 * @file          cpg.c
 * - Version      : 0.03
 * @brief         Initial setting process of CPG.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 03.07.2020 0.01     First Release
 *         : 13.04.2021 0.02     Added processing to disable automatic module
 *                               clock stop function
 *         : 06.07.2021 0.03     Update setting value of module stop register
 *****************************************************************************/

#include <cpg_register.h>
#include <cpg.h>
#include <mem_io.h>
#include <rcar_def.h>

/* CPG write protect value */
#define CPGWPCR_PASSWORD    (0xA5A50000U)
#define CPGWPCR_WPE     ((uint32_t)1U << 0U)
#define CPGWPCR_WPE_VALID   (0U)

/* CPG module standby defineation */
/* define */
#define CPG_MSTPSR0_RTDMAC0                     (((uint32_t)1U) << 21U)
#define CPG_MSTPSR0_RTDMAC0_FAILURE_DETCTION    (((uint32_t)1U) << 17U)
#define CPG_MSTPSR0_RTDMAC1                     (((uint32_t)1U) << 16U)
#define CPG_MSTPSR1_IVCP1E                      (((uint32_t)1U) << 27U)
#define CPG_MSTPSR1_TMU0                        (((uint32_t)1U) << 25U)
#define CPG_MSTPSR1_TMU1                        (((uint32_t)1U) << 24U)
#define CPG_MSTPSR1_TMU2                        (((uint32_t)1U) << 23U)
#define CPG_MSTPSR1_TMU3                        (((uint32_t)1U) << 22U)
#define CPG_MSTPSR1_TMU4                        (((uint32_t)1U) << 21U)
#define CPG_MSTPSR1_KCRC0                       (((uint32_t)1U) << 14U)
#define CPG_MSTPSR1_KCRC1                       (((uint32_t)1U) << 13U)
#define CPG_MSTPSR1_KCRC2                       (((uint32_t)1U) << 11U)
#define CPG_MSTPSR1_KCRC3                       (((uint32_t)1U) << 10U)
#define CPG_MSTPSR1_DOF                         (((uint32_t)1U) << 2U)
#define CPG_MSTPSR1_STV                         (((uint32_t)1U) << 1U)
#define CPG_MSTPSR2_SYS_DMAC1                   (((uint32_t)1U) << 18U)
#define CPG_MSTPSR2_SYS_DMAC2                   (((uint32_t)1U) << 17U)
#define CPG_MSTPSR2_RTSRAM                      (((uint32_t)1U) << 15U)
#define CPG_MSTPSR2_MFIS                        (((uint32_t)1U) << 13U)
#define CPG_MSTPSR2_MSIOF0                      (((uint32_t)1U) << 11U)
#define CPG_MSTPSR2_MSIOF1                      (((uint32_t)1U) << 10U)
#define CPG_MSTPSR2_MSIOF2                      (((uint32_t)1U) << 9U)
#define CPG_MSTPSR2_MSIOF3                      (((uint32_t)1U) << 8U)
#define CPG_MSTPSR2_SCIF0                       (((uint32_t)1U) << 7U)
#define CPG_MSTPSR2_SCIF1                       (((uint32_t)1U) << 6U)
#define CPG_MSTPSR2_SCIF3                       (((uint32_t)1U) << 4U)
#define CPG_MSTPSR2_SCIF4                       (((uint32_t)1U) << 3U)
#define CPG_MSTPSR3_CRC2                        (((uint32_t)1U) << 23U)
#define CPG_MSTPSR3_CRC3                        (((uint32_t)1U) << 22U)
#define CPG_MSTPSR3_PCIEC0                      (((uint32_t)1U) << 19U)
#define CPG_MSTPSR3_IPC                         (((uint32_t)1U) << 15U)
#define CPG_MSTPSR3_SD_IF                       (((uint32_t)1U) << 14U)
#define CPG_MSTPSR3_CRC0                        (((uint32_t)1U) << 7U)
#define CPG_MSTPSR3_CRC1                        (((uint32_t)1U) << 6U)
#define CPG_MSTPSR3_TPU0                        (((uint32_t)1U) << 4U)
#define CPG_MSTPSR3_CMT0                        (((uint32_t)1U) << 3U)
#define CPG_MSTPSR3_CMT1                        (((uint32_t)1U) << 2U)
#define CPG_MSTPSR3_CMT2                        (((uint32_t)1U) << 1U)
#define CPG_MSTPSR3_CMT3                        (((uint32_t)1U) << 0U)
#define CPG_MSTPSR4_SUCMT                       (((uint32_t)1U) << 31U)
#define CPG_MSTPSR4_RWDT                        (((uint32_t)1U) << 2U)
#define CPG_MSTPSR5_IMP_OCV2                    (((uint32_t)1U) << 31U)
#define CPG_MSTPSR5_IMP_OCV3                    (((uint32_t)1U) << 29U)
#define CPG_MSTPSR5_IMP_OCV4                    (((uint32_t)1U) << 28U)
#define CPG_MSTPSR5_IMPDMA0                     (((uint32_t)1U) << 27U)
#define CPG_MSTPSR5_IMPDMA1                     (((uint32_t)1U) << 26U)
#define CPG_MSTPSR5_IMPPSC0                     (((uint32_t)1U) << 25U)
#define CPG_MSTPSR5_IMPPSC1                     (((uint32_t)1U) << 24U)
#define CPG_MSTPSR5_PWM                         (((uint32_t)1U) << 23U)
#define CPG_MSTPSR5_THS_TSC                     (((uint32_t)1U) << 22U)
#define CPG_MSTPSR5_IMP4                        (((uint32_t)1U) << 21U)
#define CPG_MSTPSR5_HSCIF0                      (((uint32_t)1U) << 20U)
#define CPG_MSTPSR5_HSCIF1                      (((uint32_t)1U) << 19U)
#define CPG_MSTPSR5_HSCIF2                      (((uint32_t)1U) << 18U)
#define CPG_MSTPSR5_HSCIF3                      (((uint32_t)1U) << 17U)
#define CPG_MSTPSR5_FLEXRAY                     (((uint32_t)1U) << 5U)
#define CPG_MSTPSR5_SIMP                        (((uint32_t)1U) << 0U)
#define CPG_MSTPSR6_VIN8                        (((uint32_t)1U) << 28U)
#define CPG_MSTPSR6_VIN9                        (((uint32_t)1U) << 27U)
#define CPG_MSTPSR6_VIN10                       (((uint32_t)1U) << 25U)
#define CPG_MSTPSR6_VSP                         (((uint32_t)1U) << 23U)
#define CPG_MSTPSR6_VIN11                       (((uint32_t)1U) << 18U)
#define CPG_MSTPSR6_VIN12                       (((uint32_t)1U) << 12U)
#define CPG_MSTPSR6_VIN13                       (((uint32_t)1U) << 8U)
#define CPG_MSTPSR6_VIN14                       (((uint32_t)1U) << 5U)
#define CPG_MSTPSR6_VIN15                       (((uint32_t)1U) << 4U)
#define CPG_MSTPSR6_FCPVD0                      (((uint32_t)1U) << 3U)
#define CPG_MSTPSR7_LVDS_IF                     (((uint32_t)1U) << 27U)
#define CPG_MSTPSR7_DU0                         (((uint32_t)1U) << 24U)
#define CPG_MSTPSR7_CSI40                       (((uint32_t)1U) << 16U)
#define CPG_MSTPSR7_CSI41                       (((uint32_t)1U) << 15U)
#define CPG_MSTPSR7_IMR_LX44                    (((uint32_t)1U) << 7U)
#define CPG_MSTPSR7_IMR_LX45                    (((uint32_t)1U) << 6U)
#define CPG_MSTPSR8_IMPCNN                      (((uint32_t)1U) << 31U)
#define CPG_MSTPSR8_IMPRAM                      (((uint32_t)1U) << 30U)
#define CPG_MSTPSR8_IMP_OCV0                    (((uint32_t)1U) << 29U)
#define CPG_MSTPSR8_IMP_OCV1                    (((uint32_t)1U) << 28U)
#define CPG_MSTPSR8_IMP0                        (((uint32_t)1U) << 27U)
#define CPG_MSTPSR8_IMP1                        (((uint32_t)1U) << 26U)
#define CPG_MSTPSR8_IMP2                        (((uint32_t)1U) << 25U)
#define CPG_MSTPSR8_IMP3                        (((uint32_t)1U) << 24U)
#define CPG_MSTPSR8_IMR_LX40                    (((uint32_t)1U) << 23U)
#define CPG_MSTPSR8_IMR_LX41                    (((uint32_t)1U) << 22U)
#define CPG_MSTPSR8_IMR_LX42                    (((uint32_t)1U) << 21U)
#define CPG_MSTPSR8_IMR_LX43                    (((uint32_t)1U) << 20U)
#define CPG_MSTPSR8_ISP0                        (((uint32_t)1U) << 17U)
#define CPG_MSTPSR8_ISP1                        (((uint32_t)1U) << 14U)
#define CPG_MSTPSR8_GIGABIT_ETEERNET            (((uint32_t)1U) << 13U)
#define CPG_MSTPSR8_EAVB_IF                     (((uint32_t)1U) << 12U)
#define CPG_MSTPSR8_VIN0                        (((uint32_t)1U) << 11U)
#define CPG_MSTPSR8_VIN1                        (((uint32_t)1U) << 10U)
#define CPG_MSTPSR8_VIN2                        (((uint32_t)1U) << 9U)
#define CPG_MSTPSR8_VIN3                        (((uint32_t)1U) << 8U)
#define CPG_MSTPSR8_VIN4                        (((uint32_t)1U) << 7U)
#define CPG_MSTPSR8_VIN5                        (((uint32_t)1U) << 6U)
#define CPG_MSTPSR8_VIN6                        (((uint32_t)1U) << 5U)
#define CPG_MSTPSR8_VIN7                        (((uint32_t)1U) << 4U)
#define CPG_MSTPSR9_I2C_IF0                     (((uint32_t)1U) << 31U)
#define CPG_MSTPSR9_I2C_IF1                     (((uint32_t)1U) << 30U)
#define CPG_MSTPSR9_I2C_IF2                     (((uint32_t)1U) << 29U)
#define CPG_MSTPSR9_I2C_IF3                     (((uint32_t)1U) << 28U)
#define CPG_MSTPSR9_I2C_IF4                     (((uint32_t)1U) << 27U)
#define CPG_MSTPSR9_I2C_IF5                     (((uint32_t)1U) << 19U)
#define CPG_MSTPSR9_RPC_IF                      (((uint32_t)1U) << 17U)
#define CPG_MSTPSR9_CAN_FD                      (((uint32_t)1U) << 14U)
#define CPG_MSTPSR9_GPIO0                       (((uint32_t)1U) << 12U)
#define CPG_MSTPSR9_GPIO1                       (((uint32_t)1U) << 11U)
#define CPG_MSTPSR9_GPIO2                       (((uint32_t)1U) << 10U)
#define CPG_MSTPSR9_GPIO3                       (((uint32_t)1U) << 9U)
#define CPG_MSTPSR9_GPIO4                       (((uint32_t)1U) << 8U)
#define CPG_MSTPSR9_GPIO5                       (((uint32_t)1U) << 7U)
#define CPG_MSTPSR9_SPIF                        (((uint32_t)1U) << 2U)
#define CPG_MSTPSR10_ACF0                       (((uint32_t)1U) << 4U)
#define CPG_MSTPSR10_ACF1                       (((uint32_t)1U) << 3U)
#define CPG_MSTPSR10_ACF2                       (((uint32_t)1U) << 2U)
#define CPG_MSTPSR10_ACF3                       (((uint32_t)1U) << 1U)
#define CPG_MSTPSR10_ACF4                       (((uint32_t)1U) << 0U)

/* define for ASTPOFFR register */
#define IMP0_A_DISABLE      (((uint32_t)1U) << 12U)
#define IMP1_A_DISABLE      (((uint32_t)1U) << 13U)
#define IMP2_A_DISABLE      (((uint32_t)1U) << 14U)
#define IMP3_A_DISABLE      (((uint32_t)1U) << 15U)
#define IMP4_A_DISABLE      (((uint32_t)1U) << 16U)
#define IMP5_A_DISABLE      (((uint32_t)1U) << 17U)

void cpg_init(void)
{
    uint32_t reg;

    /* Release CPG write protect */
    if((mem_read32(CPG_CPGWPCR) & CPGWPCR_WPE) != CPGWPCR_WPE_VALID)
    {
        mem_write32(CPG_CPGWPR, ~(uint32_t)(CPGWPCR_PASSWORD));
        mem_write32(CPG_CPGWPCR, CPGWPCR_PASSWORD);

        /* bit in WPE = 0? */
        while ((mem_read32(CPG_CPGWPCR) & CPGWPCR_WPE) != CPGWPCR_WPE_VALID)
        {
            ;
        }
    }

    /* Initialize CPG (Realtime) registers. */
    /* RMSTPCR0 not set */
    /* RMSTPCR1 */
    reg = mem_read32(CPG_RMSTPCR1);
    reg &= ~(uint32_t)(CPG_MSTPSR1_TMU0
            | CPG_MSTPSR1_TMU4);
    cpg_reg_write(CPG_RMSTPCR1, CPG_MSTPSR1, reg);
    /* RMSTPCR2 not set */
    /* RMSTPCR3 */
    reg = mem_read32(CPG_RMSTPCR3);
    reg &= ~(uint32_t)(CPG_MSTPSR3_CRC2
            | CPG_MSTPSR3_CRC0
            | CPG_MSTPSR3_CRC1
            | CPG_MSTPSR3_CMT1
            | CPG_MSTPSR3_CMT2);
    cpg_reg_write(CPG_RMSTPCR3, CPG_MSTPSR3, reg);
    /* RMSTPCR4 not set */
    /* RMSTPCR5 */
    reg = mem_read32(CPG_RMSTPCR5);
    reg &= ~(uint32_t)(CPG_MSTPSR5_FLEXRAY);
    reg |= (uint32_t)(CPG_MSTPSR5_IMP_OCV2
            | CPG_MSTPSR5_IMP_OCV3
            | CPG_MSTPSR5_IMP_OCV4
            | CPG_MSTPSR5_IMPDMA0
            | CPG_MSTPSR5_IMPDMA1
            | CPG_MSTPSR5_IMPPSC0
            | CPG_MSTPSR5_IMPPSC1
            | CPG_MSTPSR5_IMP4
            | CPG_MSTPSR5_SIMP);
    cpg_reg_write(CPG_RMSTPCR5, CPG_MSTPSR5, reg);
    /* RMSTPCR6 not set */
    /* RMSTPCR7 not set */
    /* RMSTPCR8 */
    reg = mem_read32(CPG_RMSTPCR8);
    reg &= ~(uint32_t)(CPG_MSTPSR8_EAVB_IF);
    reg |= (uint32_t)(CPG_MSTPSR8_IMPCNN
            | CPG_MSTPSR8_IMPRAM
            | CPG_MSTPSR8_IMP_OCV0
            | CPG_MSTPSR8_IMP_OCV1
            | CPG_MSTPSR8_IMP0
            | CPG_MSTPSR8_IMP1
            | CPG_MSTPSR8_IMP2
            | CPG_MSTPSR8_IMP3);
    cpg_reg_write(CPG_RMSTPCR8, CPG_MSTPSR8, reg);
    /* RMSTPCR9 */
    reg = mem_read32(CPG_RMSTPCR9);
    reg &= ~(uint32_t)(CPG_MSTPSR9_CAN_FD);
    cpg_reg_write(CPG_RMSTPCR9, CPG_MSTPSR9, reg);
    /* RMSTPCR10 not set */
    /* RMSTPCR11 not set */

    /* Initialize CPG (System) registers. */
    /* SMSTPCR0 not set */
    /* SMSTPCR1 */
    reg = mem_read32(CPG_SMSTPCR1);
    reg &= ~(uint32_t)(CPG_MSTPSR1_IVCP1E
             | CPG_MSTPSR1_TMU0);
    cpg_reg_write(CPG_SMSTPCR1, CPG_MSTPSR1, reg);
    /* SMSTPCR2 not set */
    /* SMSTPCR3 not set */
    /* SMSTPCR4 not set */
    /* SMSTPCR5 not set */
    /* SMSTPCR6 not set */
    /* SMSTPCR7 */
    reg = mem_read32(CPG_SMSTPCR7);
    reg &= ~(uint32_t)(CPG_MSTPSR7_IMR_LX44 | CPG_MSTPSR7_IMR_LX45);
    cpg_reg_write(CPG_SMSTPCR7, CPG_MSTPSR7, reg);
    /* SMSTPCR8 not set */
    /* SMSTPCR9 not set */
    /* SMSTPCR10 not set */
    /* SMSTPCR11 not set */

    /* Initialize CPG (SECURITY) registers. */
    /* SCMSTPCR0 not set */
    /* SCMSTPCR1 not set */
    /* SCMSTPCR2 not set */
    /* SCMSTPCR3 not set */
    /* SCMSTPCR4 not set */
    /* SCMSTPCR5 not set */
    /* SCMSTPCR6 not set */
    /* SCMSTPCR7 not set */
    /* SCMSTPCR8 not set */
    /* SCMSTPCR9 */
    reg = mem_read32(CPG_SCMSTPCR9);
    reg &= ~(uint32_t)(CPG_MSTPSR9_RPC_IF);
    cpg_reg_write(CPG_SCMSTPCR9, CPG_MSTPSR9, reg);
    /* SCMSTPCR10 not set */
    /* SCMSTPCR11 not set */

    /* Initialize CPG (SAFETY) registers. */
    /* SAMSTPCR0 not set */
    /* SAMSTPCR1 not set */
    /* SAMSTPCR2 not set */
    /* SAMSTPCR3 not set */
    /* SAMSTPCR4 not set */
    /* SAMSTPCR5 not set */
    /* SAMSTPCR6 not set */
    /* SAMSTPCR7 not set */
    /* SAMSTPCR8 not set */
    /* SAMSTPCR9 not set */
    /* SAMSTPCR10 not set */
    /* SAMSTPCR11 not set */

    /* Disable automatic module clock stop function */
    reg = mem_read32(PRR);
    if ((reg & PRR_CUT_MASK) < PRR_PRODUCT_20) {
        reg = mem_read32(ASTPOFFR);
        reg |= (IMP0_A_DISABLE | IMP1_A_DISABLE | IMP2_A_DISABLE |
            IMP3_A_DISABLE | IMP4_A_DISABLE | IMP5_A_DISABLE);
        mem_write32(ASTPOFFR, reg);
    }
}
/* End of function cpg_init(void) */

void cpg_reg_write(uintptr_t mstpcr, uintptr_t mstpsr, uint32_t data)
{
    mem_write32(mstpcr, data);
    while ((mem_read32(mstpsr) & ~(uint32_t)(data)) != 0U)
    {
        /* Loop to wait for confirmation that changes to "MSTPCRn" are reflected in "MSTPSRn". */
    }
}
/* End of function cpg_reg_write(uintptr_t mstpcr, uintptr_t mstpsr, uint32_t data) */
