/*******************************************************************************
 * Copyright (c) 2021-2022 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.
 ******************************************************************************/

/*******************************************************************************
 * DRAM Param setting
 ******************************************************************************/
#define JS2_DERATE	0
#define DBSC_REFINT	1920		/* Average periodic refresh interval/Average Refresh Interval [ns] */
#define DBSC_REFINTS	0		/* 0: Average interval is REFINT. / 1: Average interval is 1/2 REFINT. */

#define REWT_TRAINING_INTERVAL	20000		/* Periodic-WriteDQ Training Interval [us] */

/*******************************************************************************
 *	NUMBER OF BOARD CONFIGRATION
 *	PLEASE DEFINE
 ******************************************************************************/
#define BOARDNUM 3  /* Add User platform BOARD */

/*******************************************************************************
 *	PLEASE SET board number or board judge function
 ******************************************************************************/
#define BOARD_JUDGE_AUTO
#ifdef BOARD_JUDGE_AUTO
static uint32_t _board_judge(void);
static uint32_t boardcnf_get_brd_type(void) {
		return _board_judge();
}
#else /* BOARD_JUDGE_AUTO */
static uint32_t boardcnf_get_brd_type(void) {
		return (0);
}
#endif /* BOARD_JUDGE_AUTO */

/*******************************************************************************
 *	BOARD CONFIGRATION
 *	PLEASE DEFINE boardcnfs[]
 ******************************************************************************/
struct _boardcnf_ch {
	/*
	 0x00...0000B:  4Gb dual channel die /  2Gb single channel die
	 0x01...0001B:  6Gb dual channel die /  3Gb single channel die
	 0x02...0010B:  8Gb dual channel die /  4Gb single channel die
	 0x03...0011B: 12Gb dual channel die /  6Gb single channel die
	 0x04...0100B: 16Gb dual channel die /  8Gb single channel die
	 0xff...NO_MEMORY
	*/
	uint8_t ddr_density[CS_CNT];
	/* SoC caX([5][4][3][2][1][0]) -> MEM caY: */
	uint32_t ca_swap;
	/* SoC dqsX([3][2][1][0]) -> MEM dqsY: */
	uint16_t dqs_swap;
	/* SoC dq([7][6][5][4][3][2][1][0]) -> MEM dqY/dm:  (8 means DM) */
	uint32_t dq_swap[SLICE_CNT];
	/* SoC dm -> MEM dqY/dm:  (8 means DM) */
	uint8_t dm_swap[SLICE_CNT];
};

struct _boardcnf {
	/* ch in use */
	uint16_t phyvalid;
	/* Read vref (SoC) training range   : [15:8]stop / [7:0]start, 0x0000 = default val */
	uint16_t vref_r;
	/* Write vref (MR14) training range : [15:8]stop / [7:0]start, 0x0000 = default val */
	uint16_t vref_w;
	/* CA vref (MR12) training range    : [15:8]stop / [7:0]start, 0x0000 = default val */
	uint16_t vref_ca;

	struct _boardcnf_ch ch[2];
};

static const struct _boardcnf boardcnfs[BOARDNUM] = {
/*
 * boardcnf[0] RENESAS S4 Spider (16Gbit 2rank)
 */
{
	0x03,		/* phyvalid */
	0x0000,		/* vref_r */
	0x0000,		/* vref_w */
	0x0000,		/* vref_ca */
	{
/* ch[0] */	{	/* M0CAxB/M0DQ[23:16],M0DQ[31:24] */
/* ddr_density[] */	{ 0x04, 0x04 },
/* ca_swap */		0x243510U,
/* dqs_swap */		0x10,
/* dq_swap[] */		{ 0x21706345, 0x23510746 },
/* dm_swap[] */		{ 0x08, 0x08 }
		},
/* ch[1] */	{	/* M0CAxA/M0DQ[15: 0] */
/* ddr_density[] */	{ 0x04, 0x04 },
/* ca_swap */		0x345210U,
/* dqs_swap */		0x10,
/* dq_swap[] */		{ 0x30124675, 0x53126047 },
/* dm_swap[] */		{ 0x08, 0x08 }
		}
	}
},
/*
 * boardcnf[1] RENESAS S4-N Spider (16Gbit 2rank)
 */
{
	0x03,		/* phyvalid */
	0x0000,		/* vref_r */
	0x0000,		/* vref_w */
	0x0000,		/* vref_ca */
	{
/* ch[0] */	{	/* M0CAxB/M0DQ[23:16],M0DQ[31:24] */
/* ddr_density[] */	{ 0x04, 0x04 },
/* ca_swap */		0x243510U,
/* dqs_swap */		0x10,
/* dq_swap[] */		{ 0x21705634, 0x23516048 },
/* dm_swap[] */		{ 0x08, 0x07 }
		},
/* ch[1] */	{	/* M0CAxA/M0DQ[15: 0] */
/* ddr_density[] */	{ 0x04, 0x04 },
/* ca_swap */		0x345201U,
/* dqs_swap */		0x10,
/* dq_swap[] */		{ 0x03124675, 0x35126047 },
/* dm_swap[] */		{ 0x08, 0x08 }
		}
	}
},
/*
 * boardcnf[2] RENESAS S4(2ch)
 */
{
	0x03,		/* phyvalid */
	0x0000,		/* vref_r */
	0x0000,		/* vref_w */
	0x0000,		/* vref_ca */
	{
/* ch[0] */	{
/* ddr_density[] */	{ 0x04, 0x04 },
/* ca_swap */		0x00543210U,
/* dqs_swap */		0x10,
/* dq_swap[] */		{ 0x76543210, 0x76543210 },
/* dm_swap[] */		{ 0x08, 0x08 }
		},
/* ch[1] */	{
/* ddr_density[] */	{ 0x04, 0x04 },
/* ca_swap */		0x00543210U,
/* dqs_swap */		0x10,
/* dq_swap[] */		{ 0x76543210, 0x76543210 },
/* dm_swap[] */		{ 0x08, 0x08 }
		}
	}
}
};

/*******************************************************************************
 *	EXTAL CLOCK DEFINITION
 *	PLEASE DEFINE HOW TO JUDGE BORAD CLK
 ******************************************************************************/
/*
 * RENESAS SPIDER BOARD EXAMPLE
 * judge by md14/md13
 *
 * 16.00MHz CLK,DIV= 48,3  (md14,md13==0,0)
 * 20.00MHz CLK,DIV= 60,3  (md14,md13==0,1)
 * 40.00MHz CLK,DIV=120,3  (md14,md13==1,1)
*/
void boardcnf_get_brd_clk(uint32_t brd, uint32_t *clk, uint32_t *div) {
	uint32_t md;

	md = (mmio_read_32(RST_MODEMR0) >> 13) & 0x3;
	switch(md) {
		case 0x0 : *clk = 48; *div = 3; break;		/*  48 / 3 = 16.00MHz */
		case 0x1 : *clk = 60; *div = 3; break;		/*  60 / 3 = 20.00MHz */
/*		case 0x2 : *clk = 75; *div = 3; break;	*/	/*  Not supported     */
		case 0x3 : *clk =120; *div = 3; break;		/* 120 / 3 = 40.00MHz */
	}
	(void)brd;
}

/*******************************************************************************
 *	DDR MBPS TARGET
 *	PLEASE DEFINE HOW TO JUDGE DDR BPS
 ******************************************************************************/
/*
  DDRxxxx (judge by md17) : Mbps
  SSCG enable / disable for PLL1 (judge by md37/md36)
*/
void boardcnf_get_ddr_mbps(uint32_t brd, uint32_t *mbps, uint32_t *div) {
	uint32_t md;
	uint32_t sscg;

	md = (mmio_read_32(RST_MODEMR0) >> 17) & 0x01U;
	sscg = (mmio_read_32(RST_MODEMR1) >> 4) & 0x03U;

	switch(sscg) {
		case 0x0 :
			switch(md) {
				case 0x0 : *mbps =  3200; *div = 1; break;
				case 0x1 : *mbps =  2120; *div = 1; break;
			}
			break;
		case 0x1 :
			switch(md) {
				case 0x0 : *mbps =  3120; *div = 1; break;
				case 0x1 : *mbps =  2120; *div = 1; break;
			}
			break;
		case 0x2 :
			switch(md) {
				case 0x0 : *mbps =  3040; *div = 1; break;
				case 0x1 : *mbps =  2120; *div = 1; break;
			}
			break;
		case 0x3 :
			switch(md) {
				case 0x0 : *mbps =  3000; *div = 1; break;
				case 0x1 : *mbps =  2120; *div = 1; break;
			}
			break;
	}
	(void)brd;
}

#ifdef BOARD_JUDGE_AUTO
/*******************************************************************************
 *	SAMPLE board detect function
 ******************************************************************************/
static uint32_t _board_judge(void) {
	uint32_t brd;

	brd = 0;	/* spider (16Gbit 2rank)*/

	return brd;
}
#endif
