/*******************************************************************************
 * 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   : QoS initialize function
 ******************************************************************************/
/******************************************************************************
 * @file          qos.c
 * - Version      : 0.02
 * @brief         Initial setting process of QoS.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 03.07.2020 0.01     First Release
 *         : 17.08.2020 0.02     Update QoS setting(rev0.10)
 *****************************************************************************/

#include <stdint.h>
#if defined(__RH850G3K__)
#include <log.h>
#include <remap_register.h>
#include <remap.h>
#else
#include <debug.h>
#endif
#include <qos.h>
#include <qos_mstat.h>
#include <qos_qoswt.h>
#include <mem_io.h>
#include <rcar_def.h>     /* V3H: PRR */


#define RCAR_QOS_VERSION        "rev.0.11"

#define RCAR_REWT_TRAINING_DISABLE  (0U)
#define RCAR_REWT_TRAINING_ENABLE   (1U)


#if defined(__RH850G3K__)
#define DBSC_BASE           (BASE_DBSC_ADDR)
#else
#define DBSC_BASE           (0xE6790000U)
#endif
#define DBSC_SYSCNT0            (DBSC_BASE + 0x0100U)
#define DBSC_SYSCNT1            (DBSC_BASE + 0x0104U)
#define DBSC_AXARB              (DBSC_BASE + 0x0800U)
#define DBSC_DBCAM0CNF0         (DBSC_BASE + 0x0900U)
#define DBSC_DBCAM0CNF1         (DBSC_BASE + 0x0904U)
#define DBSC_DBCAM0CNF2         (DBSC_BASE + 0x0908U)
#define DBSC_DBCAM0CNF3         (DBSC_BASE + 0x090CU)
#define DBSC_DBCAMDIS           (DBSC_BASE + 0x09fCU)
#define DBSC_DBSCHCNT0          (DBSC_BASE + 0x1000U)
#define DBSC_DBSCHSZ0           (DBSC_BASE + 0x1010U)
#define DBSC_DBSCHRW0           (DBSC_BASE + 0x1020U)
#define DBSC_DBSCHRW1           (DBSC_BASE + 0x1024U)
#define DBSC_DBSCHQOS_0_0       (DBSC_BASE + 0x1030U)
#define DBSC_DBSCHQOS_0_1       (DBSC_BASE + 0x1034U)
#define DBSC_DBSCHQOS_0_2       (DBSC_BASE + 0x1038U)
#define DBSC_DBSCHQOS_0_3       (DBSC_BASE + 0x103CU)
#define DBSC_DBSCHQOS_4_0       (DBSC_BASE + 0x1070U)
#define DBSC_DBSCHQOS_4_1       (DBSC_BASE + 0x1074U)
#define DBSC_DBSCHQOS_4_2       (DBSC_BASE + 0x1078U)
#define DBSC_DBSCHQOS_4_3       (DBSC_BASE + 0x107CU)
#define DBSC_DBSCHQOS_9_0       (DBSC_BASE + 0x10C0U)
#define DBSC_DBSCHQOS_9_1       (DBSC_BASE + 0x10C4U)
#define DBSC_DBSCHQOS_9_2       (DBSC_BASE + 0x10C8U)
#define DBSC_DBSCHQOS_9_3       (DBSC_BASE + 0x10CCU)
#define DBSC_DBSCHQOS_12_0      (DBSC_BASE + 0x10F0U)
#define DBSC_DBSCHQOS_12_1      (DBSC_BASE + 0x10F4U)
#define DBSC_DBSCHQOS_12_2      (DBSC_BASE + 0x10F8U)
#define DBSC_DBSCHQOS_12_3      (DBSC_BASE + 0x10FCU)
#define DBSC_DBSCHQOS_13_0      (DBSC_BASE + 0x1100U)
#define DBSC_DBSCHQOS_13_1      (DBSC_BASE + 0x1104U)
#define DBSC_DBSCHQOS_13_2      (DBSC_BASE + 0x1108U)
#define DBSC_DBSCHQOS_13_3      (DBSC_BASE + 0x110CU)
#define DBSC_DBSCHQOS_14_0      (DBSC_BASE + 0x1110U)
#define DBSC_DBSCHQOS_14_1      (DBSC_BASE + 0x1114U)
#define DBSC_DBSCHQOS_14_2      (DBSC_BASE + 0x1118U)
#define DBSC_DBSCHQOS_14_3      (DBSC_BASE + 0x111CU)
#define DBSC_DBSCHQOS_15_0      (DBSC_BASE + 0x1120U)
#define DBSC_DBSCHQOS_15_1      (DBSC_BASE + 0x1124U)
#define DBSC_DBSCHQOS_15_2      (DBSC_BASE + 0x1128U)
#define DBSC_DBSCHQOS_15_3      (DBSC_BASE + 0x112CU)
#define DBSC_SCFCTST0           (DBSC_BASE + 0x1700U)
#define DBSC_SCFCTST1           (DBSC_BASE + 0x1708U)
#define DBSC_SCFCTST2           (DBSC_BASE + 0x170CU)


#if defined(__RH850G3K__)
#define MSTAT_BASE          (BASE_MSTAT_ADDR)
#else
#define MSTAT_BASE          (0xE67E0000U)
#endif
#define MSTAT_FIX_QOS_BANK0     (MSTAT_BASE + 0x0000U)
#define MSTAT_FIX_QOS_BANK1     (MSTAT_BASE + 0x1000U)
#define MSTAT_BE_QOS_BANK0      (MSTAT_BASE + 0x2000U)
#define MSTAT_BE_QOS_BANK1      (MSTAT_BASE + 0x3000U)
#define MSTAT_SL_INIT           (MSTAT_BASE + 0x8000U)
#define MSTAT_REF_ARS           (MSTAT_BASE + 0x8004U)
#define MSTAT_STATQC            (MSTAT_BASE + 0x8008U)
#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE
#define QOSWT_FIX_QOS_BANK0     (MSTAT_BASE + 0x0800U)
#define QOSWT_FIX_QOS_BANK1     (MSTAT_BASE + 0x1800U)
#define QOSWT_BE_QOS_BANK0      (MSTAT_BASE + 0x2800U)
#define QOSWT_BE_QOS_BANK1      (MSTAT_BASE + 0x3800U)
#define QOSWT_WTEN              (MSTAT_BASE + 0x8030U)
#define QOSWT_WTREF             (MSTAT_BASE + 0x8034U)
#define QOSWT_WTSET0            (MSTAT_BASE + 0x8038U)
#define QOSWT_WTSET1            (MSTAT_BASE + 0x803CU)
#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */

#if defined(__RH850G3K__)
#define RALLOC_BASE         (BASE_QOS_ADDR)
#else
#define RALLOC_BASE         (0xE67F0000U)
#endif
#define RALLOC_RAS          (RALLOC_BASE + 0x0000U)
#define RALLOC_FIXTH        (RALLOC_BASE + 0x0004U)
#define RALLOC_RAEN         (RALLOC_BASE + 0x0018U)
#define RALLOC_REGGD        (RALLOC_BASE + 0x0020U)
#define RALLOC_DANN_LOW     (RALLOC_BASE + 0x0030U)
#define RALLOC_DANN_HIGH    (RALLOC_BASE + 0x0034U)
#define RALLOC_DANT         (RALLOC_BASE + 0x0038U)
#define RALLOC_EC           (RALLOC_BASE + 0x003CU)
#define RALLOC_EMS_LOW      (RALLOC_BASE + 0x0040U)
#define RALLOC_EMS_HIGH     (RALLOC_BASE + 0x0044U)
#define RALLOC_FSS          (RALLOC_BASE + 0x0048U)
#define RALLOC_INSFC        (RALLOC_BASE + 0x0050U)
#define RALLOC_BERR         (RALLOC_BASE + 0x0054U)
#define RALLOC_EARLYR       (RALLOC_BASE + 0x0060U)
#define RALLOC_RACNT0       (RALLOC_BASE + 0x0080U)


#if defined(__RH850G3K__)
#define RT_ACT_BASE         (BASE_RTACT_ADDR)
#else
#define RT_ACT_BASE         (0xFFC50800U)
#endif
#define RT_ACT0             (RT_ACT_BASE + 0x0000U)
#define RT_ACT1             (RT_ACT_BASE + 0x1000U)

#define CPU_ACT_BASE        (0xF1300800U)
#define CPU_ACT_REMAP_SIZE  (0x00040010U)
#define CPU_ACT1_OFFSET     (0x00040000U)


#define OPERATING_FREQ      (400U)      /* MHz */
#define BASE_SUB_SLOT_NUM   (0x6U)
#define SUB_SLOT_CYCLE      (0x7EU)     /* 126 */

#define QOSWT_WTSET0_CYCLE  ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U)/OPERATING_FREQ)   /* unit:ns */

/* Calculating the number of array */
#define ARRAY_SIZE(a)   (sizeof(a) / sizeof((a)[0]))


static void dbsc_setting(void)
{
    /* DBSC CAM, Scheduling Setting */
    mem_write32(DBSC_SYSCNT0,       0x00001234U);
    mem_write32(DBSC_DBCAM0CNF1,    0x00043218U);   /* dbcam0cnf1 */
    mem_write32(DBSC_DBCAM0CNF2,    0x000000F4U);   /* dbcam0cnf2 */
    mem_write32(DBSC_DBCAM0CNF3,    0x00000000U);   /* dbcam0cnf3 */
    mem_write32(DBSC_DBSCHCNT0,     0x000F0037U);   /* dbschcnt0 */
    mem_write32(DBSC_DBSCHSZ0,      0x00000001U);   /* dbschsz0 */
    mem_write32(DBSC_DBSCHRW0,      0x22421111U);   /* dbschrw0 */
    mem_write32(DBSC_SCFCTST2,      0x012F1123U);

    /* DBSC QoS Setting */
    mem_write32(DBSC_DBSCHQOS_0_0,  0x00000F00U);
    mem_write32(DBSC_DBSCHQOS_0_1,  0x00000B00U);
    mem_write32(DBSC_DBSCHQOS_0_2,  0x00000000U);
    mem_write32(DBSC_DBSCHQOS_0_3,  0x00000000U);
    mem_write32(DBSC_DBSCHQOS_4_0,  0x00000300U);
    mem_write32(DBSC_DBSCHQOS_4_1,  0x000002F0U);
    mem_write32(DBSC_DBSCHQOS_4_2,  0x00000200U);
    mem_write32(DBSC_DBSCHQOS_4_3,  0x00000100U);
    mem_write32(DBSC_DBSCHQOS_9_0,  0x00000100U);
    mem_write32(DBSC_DBSCHQOS_9_1,  0x000000F0U);
    mem_write32(DBSC_DBSCHQOS_9_2,  0x000000A0U);
    mem_write32(DBSC_DBSCHQOS_9_3,  0x00000040U);
    mem_write32(DBSC_DBSCHQOS_12_0, 0x00000040U);
    mem_write32(DBSC_DBSCHQOS_12_1, 0x00000030U);
    mem_write32(DBSC_DBSCHQOS_12_2, 0x00000020U);
    mem_write32(DBSC_DBSCHQOS_12_3, 0x00000010U);
    mem_write32(DBSC_DBSCHQOS_13_0, 0x00000100U);
    mem_write32(DBSC_DBSCHQOS_13_1, 0x000000F0U);
    mem_write32(DBSC_DBSCHQOS_13_2, 0x000000A0U);
    mem_write32(DBSC_DBSCHQOS_13_3, 0x00000040U);
    mem_write32(DBSC_DBSCHQOS_14_0, 0x000000C0U);
    mem_write32(DBSC_DBSCHQOS_14_1, 0x000000B0U);
    mem_write32(DBSC_DBSCHQOS_14_2, 0x00000080U);
    mem_write32(DBSC_DBSCHQOS_14_3, 0x00000040U);
    mem_write32(DBSC_DBSCHQOS_15_0, 0x00000040U);
    mem_write32(DBSC_DBSCHQOS_15_1, 0x00000030U);
    mem_write32(DBSC_DBSCHQOS_15_2, 0x00000020U);
    mem_write32(DBSC_DBSCHQOS_15_3, 0x00000010U);

    mem_write32(DBSC_SYSCNT0,   0x00000000U);
}
/* End of function dbsc_setting(void) */

void qos_init(void)
{
    uint32_t i;
    uint32_t remap_addr;
    uint32_t prr_major_ver;
    uint32_t qoswt_tablenum;

    /* Setting the register of DBSC4 for QoS initialize */
    dbsc_setting();

    NOTICE("QoS setting(%s)\n", RCAR_QOS_VERSION);
    NOTICE("DRAM refresh interval 1.89 usec\n");

#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE
    NOTICE("Periodic Write DQ Training\n");
#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */

    /* Resource Alloc setting */
    mem_write32(RALLOC_RAS,         0x00000028U);
    mem_write32(RALLOC_DANN_LOW,    0x02020201U);
    mem_write32(RALLOC_DANN_HIGH,   0x04020000U);
    mem_write32(RALLOC_DANT,        0x00100804U);
    mem_write32(RALLOC_FSS,         0x0000000AU);
    mem_write32(RALLOC_INSFC,       0x06330001U);
    mem_write32(RALLOC_RACNT0,      0x00050003U);

    /* QoS MSTAT setting */
    mem_write32(MSTAT_SL_INIT,  0x0305007DU);
    mem_write32(MSTAT_REF_ARS,  0x00780000U);
    for (i = 0U; i < ARRAY_SIZE(mstat_tbl); i++)
    {
        mem_write64(MSTAT_FIX_QOS_BANK0 + mstat_tbl[i].offset,
                mstat_tbl[i].mstat_fix);
        mem_write64(MSTAT_FIX_QOS_BANK1 + mstat_tbl[i].offset,
                mstat_tbl[i].mstat_fix);
        mem_write64(MSTAT_BE_QOS_BANK0 + mstat_tbl[i].offset,
                mstat_tbl[i].mstat_be);
        mem_write64(MSTAT_BE_QOS_BANK1 + mstat_tbl[i].offset,
                mstat_tbl[i].mstat_be);
    }
    /* V3H */
    prr_major_ver = mem_read32(PRR) & PRR_MAJOR_MASK;
    if(prr_major_ver != 0U)   /* Not Ver.1.x */
    {
        for (i = 0U; i < ARRAY_SIZE(mstat_v2_tbl); i++)
        {
            mem_write64(MSTAT_FIX_QOS_BANK0 + mstat_v2_tbl[i].offset,
                    mstat_v2_tbl[i].mstat_fix);
            mem_write64(MSTAT_BE_QOS_BANK0 + mstat_v2_tbl[i].offset,
                    mstat_v2_tbl[i].mstat_be);
        }
    }

#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE
    qoswt_tablenum = ARRAY_SIZE(qoswt_tbl);
    if(prr_major_ver == 0U)   /* Ver.1.x */
    {
        qoswt_tablenum -= 2U;
    }
    for (i = 0U; i < qoswt_tablenum; i++)
    {
        mem_write64(MSTAT_FIX_QOS_BANK0 + qoswt_tbl[i].offset,
                qoswt_tbl[i].qoswt_fix);
        mem_write64(MSTAT_FIX_QOS_BANK1 + qoswt_tbl[i].offset,
                qoswt_tbl[i].qoswt_fix);
        mem_write64(MSTAT_BE_QOS_BANK0 + qoswt_tbl[i].offset,
                qoswt_tbl[i].qoswt_be);
        mem_write64(MSTAT_BE_QOS_BANK1 + qoswt_tbl[i].offset,
                qoswt_tbl[i].qoswt_be);
    }
#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */

    /* RT bus Leaf setting */
    mem_write32(RT_ACT0,        0x00000000U);
    mem_write32(RT_ACT1,        0x00000000U);

    /* CPU bus Leaf setting */
    remap_register(CPU_ACT_BASE, CPU_ACT_REMAP_SIZE, &remap_addr);
    mem_write32(remap_addr, 0x00000003U);
    mem_write32((remap_addr + CPU_ACT1_OFFSET), 0x00000003U);
    remap_unregister(remap_addr);

    /* QoS SRAM setting */
    mem_write32(RALLOC_RAEN,    0x00000001U);
#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE
    mem_write32(QOSWT_WTREF,    0x02080208U);
    mem_write32(QOSWT_WTSET0,   0x2955040BU);
    mem_write32(QOSWT_WTSET1,   0x2955040BU);
    mem_write32(QOSWT_WTEN,     0x00000001U);
#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */
    mem_write32(MSTAT_STATQC,   0x00000001U);
}
/* End of function qos_init(void) */

uint32_t get_refperiod(void)
{
    return QOSWT_WTSET0_CYCLE;
}
/* End of function get_refperiod(void) */
