mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-11 07:24:46 +00:00
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-sh
These are mainly DBSC5 DRAM controller specific fixes and updates for current release. There is the long overdue BL31 start V4H board code as well, that should be in the current release to make the V4H White Hawk board usable with SPL, and a fallback U-Boot PSCI implementation enablement to make sure the board always boots. And finally, there are two comment fixes.
This commit is contained in:
commit
e1b6d514d4
9 changed files with 258 additions and 105 deletions
|
@ -147,6 +147,10 @@
|
|||
bootph-all;
|
||||
};
|
||||
|
||||
&otp {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&pfc {
|
||||
bootph-all;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#
|
||||
# board/renesas/whitehawk/Makefile
|
||||
#
|
||||
# Copyright (C) 2024 Marek Vasut <marek.vasut+renesas@mailbox.org>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
|
||||
#include <asm/arch/renesas.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/system.h>
|
||||
#include <image.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#define RST_BASE 0xE6160000 /* Domain0 */
|
||||
|
@ -88,3 +90,127 @@ int ft_board_setup(void *blob, struct bd_info *bd)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* R-Car Gen4 TFA BL31 handoff structure and handling. */
|
||||
struct param_header {
|
||||
u8 type;
|
||||
u8 version;
|
||||
u16 size;
|
||||
u32 attr;
|
||||
};
|
||||
|
||||
struct tfa_image_info {
|
||||
struct param_header h;
|
||||
uintptr_t image_base;
|
||||
u32 image_size;
|
||||
u32 image_max_size;
|
||||
};
|
||||
|
||||
struct aapcs64_params {
|
||||
u64 arg0;
|
||||
u64 arg1;
|
||||
u64 arg2;
|
||||
u64 arg3;
|
||||
u64 arg4;
|
||||
u64 arg5;
|
||||
u64 arg6;
|
||||
u64 arg7;
|
||||
};
|
||||
|
||||
struct entry_point_info {
|
||||
struct param_header h;
|
||||
uintptr_t pc;
|
||||
u32 spsr;
|
||||
struct aapcs64_params args;
|
||||
};
|
||||
|
||||
struct bl2_to_bl31_params_mem {
|
||||
struct tfa_image_info bl32_image_info;
|
||||
struct tfa_image_info bl33_image_info;
|
||||
struct entry_point_info bl33_ep_info;
|
||||
struct entry_point_info bl32_ep_info;
|
||||
};
|
||||
|
||||
/* Default jump address, return to U-Boot */
|
||||
#define BL33_BASE 0x44100000
|
||||
/* Custom parameters address passed to TFA by ICUMXA loader */
|
||||
#define PARAMS_BASE 0x46422200
|
||||
|
||||
/* Usually such a structure is produced by ICUMXA and passed in at 0x46422200 */
|
||||
static const struct bl2_to_bl31_params_mem blinfo_template = {
|
||||
.bl33_ep_info.h.type = 1, /* PARAM_EP */
|
||||
.bl33_ep_info.h.version = 2, /* Version 2 */
|
||||
.bl33_ep_info.h.size = sizeof(struct entry_point_info),
|
||||
.bl33_ep_info.h.attr = 0x81, /* Executable | Non-Secure */
|
||||
.bl33_ep_info.spsr = 0x2c9, /* Mode=EL2, SP=ELX, Exceptions=OFF */
|
||||
.bl33_ep_info.pc = BL33_BASE,
|
||||
|
||||
.bl33_image_info.h.type = 1, /* PARAM_EP */
|
||||
.bl33_image_info.h.version = 2, /* Version 2 */
|
||||
.bl33_image_info.h.size = sizeof(struct image_info),
|
||||
.bl33_image_info.h.attr = 0,
|
||||
.bl33_image_info.image_base = BL33_BASE,
|
||||
};
|
||||
|
||||
static bool tfa_bl31_image_loaded;
|
||||
static ulong tfa_bl31_image_addr;
|
||||
|
||||
static void tfa_bl31_image_process(ulong image, size_t size)
|
||||
{
|
||||
/* Custom parameters address passed to TFA by ICUMXA loader */
|
||||
struct bl2_to_bl31_params_mem *blinfo = (struct bl2_to_bl31_params_mem *)PARAMS_BASE;
|
||||
|
||||
/* Not in EL3, do nothing. */
|
||||
if (current_el() != 3)
|
||||
return;
|
||||
|
||||
/* Clear a page and copy template */
|
||||
memset((void *)PARAMS_BASE, 0, PAGE_SIZE);
|
||||
memcpy(blinfo, &blinfo_template, sizeof(*blinfo));
|
||||
tfa_bl31_image_addr = image;
|
||||
tfa_bl31_image_loaded = true;
|
||||
}
|
||||
|
||||
U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_TFA_BL31, tfa_bl31_image_process);
|
||||
|
||||
void armv8_switch_to_el2_prep(u64 args, u64 mach_nr, u64 fdt_addr,
|
||||
u64 arg4, u64 entry_point, u64 es_flag)
|
||||
{
|
||||
typedef void __noreturn (*image_entry_noargs_t)(void);
|
||||
image_entry_noargs_t image_entry =
|
||||
(image_entry_noargs_t)(void *)tfa_bl31_image_addr;
|
||||
struct bl2_to_bl31_params_mem *blinfo =
|
||||
(struct bl2_to_bl31_params_mem *)PARAMS_BASE;
|
||||
|
||||
/* Not in EL3, do nothing. */
|
||||
if (current_el() != 3)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Destination address in arch/arm/cpu/armv8/transition.S
|
||||
* right past the first bl in armv8_switch_to_el2() to let
|
||||
* the rest of U-Boot pre-Linux code run. The code does run
|
||||
* without stack pointer!
|
||||
*/
|
||||
const u64 ep = ((u64)(uintptr_t)&armv8_switch_to_el2) + 4;
|
||||
|
||||
/* If TFA BL31 was not part of the fitImage, do regular boot. */
|
||||
if (!tfa_bl31_image_loaded)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Set up kernel entry point and parameters:
|
||||
* x0 is FDT address, x1..x3 must be 0
|
||||
*/
|
||||
blinfo->bl33_ep_info.pc = ep;
|
||||
blinfo->bl33_ep_info.args.arg0 = args;
|
||||
blinfo->bl33_ep_info.args.arg1 = mach_nr;
|
||||
blinfo->bl33_ep_info.args.arg2 = fdt_addr;
|
||||
blinfo->bl33_ep_info.args.arg3 = arg4;
|
||||
blinfo->bl33_ep_info.args.arg4 = entry_point;
|
||||
blinfo->bl33_ep_info.args.arg5 = es_flag;
|
||||
blinfo->bl33_image_info.image_base = ep;
|
||||
|
||||
/* Jump to TFA BL31 */
|
||||
image_entry();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* R-Car Gen4 Cortex-R52 SPL
|
||||
* R-Car Gen4 SPL
|
||||
*
|
||||
* Copyright (C) 2024 Marek Vasut <marek.vasut+renesas@mailbox.org>
|
||||
*/
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_RENESAS=y
|
||||
CONFIG_RCAR_GEN4=y
|
||||
CONFIG_ARM_SMCCC=y
|
||||
CONFIG_ARMV8_PSCI=y
|
||||
CONFIG_ENV_SIZE=0x20000
|
||||
CONFIG_ENV_OFFSET=0xFFFE0000
|
||||
CONFIG_DEFAULT_DEVICE_TREE="renesas/r8a779g0-white-hawk"
|
||||
|
|
|
@ -59,7 +59,8 @@ int renesas_dbsc5_bind(struct udevice *dev)
|
|||
|
||||
struct renesas_dbsc5_data r8a779g0_dbsc5_data = {
|
||||
.clock_node = "renesas,r8a779g0-cpg-mssr",
|
||||
.reset_node = "renesas,r8a779g0-rst"
|
||||
.reset_node = "renesas,r8a779g0-rst",
|
||||
.otp_node = "renesas,r8a779g0-otp",
|
||||
};
|
||||
|
||||
static const struct udevice_id renesas_dbsc5_ids[] = {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
struct renesas_dbsc5_data {
|
||||
const char *clock_node;
|
||||
const char *reset_node;
|
||||
const char *otp_node;
|
||||
};
|
||||
|
||||
#endif /* __DRIVERS_RAM_RENESAS_DBSC5_DBSC5_H__ */
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <dbsc5.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <hang.h>
|
||||
|
@ -12,13 +13,6 @@
|
|||
#include <linux/sizes.h>
|
||||
#include "dbsc5.h"
|
||||
|
||||
/* The number of channels V4H has */
|
||||
#define DRAM_CH_CNT 4
|
||||
/* The number of slices V4H has */
|
||||
#define SLICE_CNT 2
|
||||
/* The number of chip select V4H has */
|
||||
#define CS_CNT 2
|
||||
|
||||
/* Number of array elements in Data Slice */
|
||||
#define DDR_PHY_SLICE_REGSET_SIZE_V4H 0x100
|
||||
/* Number of array elements in Data Slice */
|
||||
|
@ -220,6 +214,7 @@ static const u16 jedec_spec2_tRFC_ab[] = {
|
|||
#define PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS DDR_REGDEF(0x00, 0x09, 0x103F)
|
||||
#define PHY_WDQLVL_STATUS_OBS DDR_REGDEF(0x00, 0x20, 0x1043)
|
||||
#define PHY_DATA_DC_CAL_START DDR_REGDEF(0x18, 0x01, 0x104D)
|
||||
#define PHY_SLV_DLY_CTRL_GATE_DISABLE DDR_REGDEF(0x10, 0x01, 0x104E)
|
||||
#define PHY_REGULATOR_EN_CNT DDR_REGDEF(0x18, 0x06, 0x1050)
|
||||
#define PHY_VREF_INITIAL_START_POINT DDR_REGDEF(0x00, 0x09, 0x1055)
|
||||
#define PHY_VREF_INITIAL_STOP_POINT DDR_REGDEF(0x10, 0x09, 0x1055)
|
||||
|
@ -469,7 +464,7 @@ static const u32 DDR_PHY_SLICE_REGSET_V4H[DDR_PHY_SLICE_REGSET_NUM_V4H] = {
|
|||
0x00000000, 0x00500050, 0x00500050, 0x00500050,
|
||||
0x00500050, 0x0D000050, 0x10100004, 0x06102010,
|
||||
0x61619041, 0x07097000, 0x00644180, 0x00803280,
|
||||
0x00808001, 0x13010100, 0x02000016, 0x10001003,
|
||||
0x00808001, 0x13010101, 0x02000016, 0x10001003,
|
||||
0x06093E42, 0x0F063D01, 0x011700C8, 0x04100140,
|
||||
0x00000100, 0x000001D1, 0x05000068, 0x00030402,
|
||||
0x01400000, 0x80800300, 0x00160010, 0x76543210,
|
||||
|
@ -512,8 +507,8 @@ static const u32 DDR_PHY_ADR_G_REGSET_V4H[DDR_PHY_ADR_G_REGSET_NUM_V4H] = {
|
|||
0x00040101, 0x00000000, 0x00000000, 0x00000064,
|
||||
0x00000000, 0x00000000, 0x39421B42, 0x00010124,
|
||||
0x00520052, 0x00000052, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x07030102,
|
||||
0x00010001, 0x00000000, 0x00000000, 0x00010001,
|
||||
0x00000000, 0x00000000, 0x00010001, 0x07030102,
|
||||
0x01030307, 0x00000054, 0x00004096, 0x08200820,
|
||||
0x08200820, 0x08200820, 0x08200820, 0x00000820,
|
||||
0x004103B8, 0x0000003F, 0x000C0006, 0x00000000,
|
||||
|
@ -1294,7 +1289,7 @@ static const struct dbsc5_table_patch dbsc5_table_patch_slice_mbpsdiv_572 = {
|
|||
};
|
||||
|
||||
static const struct dbsc5_table_patch dbsc5_table_patch_adr_g_mbpsdiv_572 = {
|
||||
PHY_PAD_ACS_RX_PCLK_CLK_SEL, 0x03
|
||||
PHY_PAD_ACS_RX_PCLK_CLK_SEL, 0x02
|
||||
};
|
||||
|
||||
static const struct dbsc5_table_patch dbsc5_table_patch_adr_g_mbpsdiv_400[] = {
|
||||
|
@ -1374,46 +1369,6 @@ static const u32 PI_DARRAY3_1_CSx_Fx[CS_CNT][3] = {
|
|||
|
||||
#define CLK_DIV(a, diva, b, divb) (((a) * (divb)) / ((b) * (diva)))
|
||||
|
||||
struct renesas_dbsc5_board_config {
|
||||
/* Channels in use */
|
||||
u8 bdcfg_phyvalid;
|
||||
/* Read vref (SoC) training range */
|
||||
u32 bdcfg_vref_r;
|
||||
/* Write vref (MR14, MR15) training range */
|
||||
u16 bdcfg_vref_w;
|
||||
/* CA vref (MR12) training range */
|
||||
u16 bdcfg_vref_ca;
|
||||
/* RFM required check */
|
||||
bool bdcfg_rfm_chk;
|
||||
|
||||
/* Board parameter about channels */
|
||||
struct {
|
||||
/*
|
||||
* 0x00: 4Gb dual channel die / 2Gb single channel die
|
||||
* 0x01: 6Gb dual channel die / 3Gb single channel die
|
||||
* 0x02: 8Gb dual channel die / 4Gb single channel die
|
||||
* 0x03: 12Gb dual channel die / 6Gb single channel die
|
||||
* 0x04: 16Gb dual channel die / 8Gb single channel die
|
||||
* 0x05: 24Gb dual channel die / 12Gb single channel die
|
||||
* 0x06: 32Gb dual channel die / 16Gb single channel die
|
||||
* 0x07: 24Gb single channel die
|
||||
* 0x08: 32Gb single channel die
|
||||
* 0xFF: NO_MEMORY
|
||||
*/
|
||||
u8 bdcfg_ddr_density[CS_CNT];
|
||||
/* SoC caX([6][5][4][3][2][1][0]) -> MEM caY: */
|
||||
u32 bdcfg_ca_swap;
|
||||
/* SoC dqsX([1][0]) -> MEM dqsY: */
|
||||
u8 bdcfg_dqs_swap;
|
||||
/* SoC dq([7][6][5][4][3][2][1][0]) -> MEM dqY/dm: (8 means DM) */
|
||||
u32 bdcfg_dq_swap[SLICE_CNT];
|
||||
/* SoC dm -> MEM dqY/dm: (8 means DM) */
|
||||
u8 bdcfg_dm_swap[SLICE_CNT];
|
||||
/* SoC ckeX([1][0]) -> MEM csY */
|
||||
u8 bdcfg_cs_swap;
|
||||
} ch[4];
|
||||
};
|
||||
|
||||
struct renesas_dbsc5_dram_priv {
|
||||
void __iomem *regs;
|
||||
void __iomem *cpg_regs;
|
||||
|
@ -1713,14 +1668,17 @@ static void dbsc5_clk_wait_dbpdstat1(struct udevice *dev, u32 status)
|
|||
{
|
||||
struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev);
|
||||
void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET;
|
||||
u32 i, ch, reg;
|
||||
u32 i, ch, chk, reg;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
do {
|
||||
reg = status;
|
||||
r_foreach_vch(dev, ch)
|
||||
chk = 0;
|
||||
r_foreach_vch(dev, ch) {
|
||||
reg &= readl(regs_dbsc_d + DBSC_DBPDSTAT1(ch));
|
||||
} while (reg != status);
|
||||
chk |= readl(regs_dbsc_d + DBSC_DBPDSTAT0(ch));
|
||||
}
|
||||
} while (reg != status && !(chk & BIT(0)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2192,7 +2150,7 @@ static void dbsc5_ddrtbl_calc(struct renesas_dbsc5_dram_priv *priv)
|
|||
if (js1[i].fx3 * 2 * priv->ddr_mbpsdiv >= priv->ddr_mbps * 3)
|
||||
break;
|
||||
|
||||
priv->js1_ind = max(i, JS1_USABLEC_SPEC_HI);
|
||||
priv->js1_ind = clamp(i, 0, JS1_USABLEC_SPEC_HI);
|
||||
|
||||
priv->RL = js1[priv->js1_ind].RLset1;
|
||||
priv->WL = js1[priv->js1_ind].WLsetA;
|
||||
|
@ -2635,7 +2593,7 @@ static void dbsc5_dbsc_regset(struct udevice *dev)
|
|||
*/
|
||||
dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(11),
|
||||
priv->RL + 4 + priv->js2[JS2_tWCK2DQO_HF] -
|
||||
js1[priv->js1_ind].ODTLon - priv->js2[JS2_tODTon_min]);
|
||||
js1[priv->js1_ind].ODTLon - priv->js2[JS2_tODTon_min] + 2);
|
||||
|
||||
/* DBTR12.TWRRD_S : WL + BL/2 + tWTR_S, TWRRD_L : WL + BL + tWTR_L */
|
||||
dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(12),
|
||||
|
@ -3491,13 +3449,10 @@ static void dbsc5_manual_write_dca(struct udevice *dev)
|
|||
{
|
||||
struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev);
|
||||
const u32 rank = priv->ch_have_this_cs[1] ? 0x2 : 0x1;
|
||||
u32 slv_dly_center[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
|
||||
u32 slv_dly_center_cyc;
|
||||
u32 slv_dly_center_dly;
|
||||
u32 phy_slv_dly[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
|
||||
u32 phy_slv_dly_avg[DRAM_CH_CNT][SLICE_CNT];
|
||||
u32 slv_dly_min[DRAM_CH_CNT][SLICE_CNT];
|
||||
u32 slv_dly_max[DRAM_CH_CNT][SLICE_CNT];
|
||||
u32 slv_dly_min_tmp[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
|
||||
u32 slv_dly_max_tmp[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
|
||||
u32 phy_dcc_code_min[DRAM_CH_CNT][SLICE_CNT];
|
||||
u32 phy_dcc_code_max[DRAM_CH_CNT][SLICE_CNT];
|
||||
u32 phy_dcc_code_mid;
|
||||
|
@ -3521,18 +3476,9 @@ static void dbsc5_manual_write_dca(struct udevice *dev)
|
|||
dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_PER_CS_TRAINING_INDEX, cs);
|
||||
r_foreach_vch(dev, ch) {
|
||||
for (slice = 0; slice < SLICE_CNT; slice++) {
|
||||
slv_dly_center[ch][cs][slice] =
|
||||
dbsc5_ddr_getval_slice(dev, ch, slice, PHY_CLK_WRDQS_SLAVE_DELAY);
|
||||
slv_dly_center_cyc = slv_dly_center[ch][cs][slice] & 0x180;
|
||||
slv_dly_center_dly = slv_dly_center[ch][cs][slice] & 0x7F;
|
||||
slv_dly_min_tmp[ch][cs][slice] =
|
||||
slv_dly_center_cyc |
|
||||
(slv_dly_center_dly * ratio_min / ratio_min_div);
|
||||
slv_dly_max_tmp[ch][cs][slice] = slv_dly_center_cyc;
|
||||
if ((slv_dly_center_dly * ratio_max) > (0x7F * ratio_max_div))
|
||||
slv_dly_max_tmp[ch][cs][slice] |= 0x7F;
|
||||
else
|
||||
slv_dly_max_tmp[ch][cs][slice] |= slv_dly_center_dly * ratio_max / ratio_max_div;
|
||||
phy_slv_dly[ch][cs][slice] =
|
||||
dbsc5_ddr_getval_slice(dev, ch, slice,
|
||||
PHY_CLK_WRDQS_SLAVE_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3540,22 +3486,22 @@ static void dbsc5_manual_write_dca(struct udevice *dev)
|
|||
r_foreach_vch(dev, ch) {
|
||||
for (slice = 0; slice < SLICE_CNT; slice++) {
|
||||
if (rank == 0x2) {
|
||||
if (slv_dly_max_tmp[ch][0][slice] < slv_dly_max_tmp[ch][1][slice])
|
||||
slv_dly_max[ch][slice] = slv_dly_max_tmp[ch][1][slice];
|
||||
else
|
||||
slv_dly_max[ch][slice] = slv_dly_max_tmp[ch][0][slice];
|
||||
|
||||
if (slv_dly_min_tmp[ch][0][slice] < slv_dly_min_tmp[ch][1][slice])
|
||||
slv_dly_min[ch][slice] = slv_dly_min_tmp[ch][0][slice];
|
||||
else
|
||||
slv_dly_min[ch][slice] = slv_dly_min_tmp[ch][1][slice];
|
||||
/* Calculate average between ranks */
|
||||
phy_slv_dly_avg[ch][slice] = (phy_slv_dly[ch][0][slice] +
|
||||
phy_slv_dly[ch][1][slice]) / 2;
|
||||
} else {
|
||||
slv_dly_max[ch][slice] = slv_dly_max_tmp[ch][0][slice];
|
||||
slv_dly_min[ch][slice] = slv_dly_min_tmp[ch][0][slice];
|
||||
phy_slv_dly_avg[ch][slice] = phy_slv_dly[ch][0][slice];
|
||||
}
|
||||
/* Determine the search range */
|
||||
slv_dly_min[ch][slice] = (phy_slv_dly_avg[ch][slice] & 0x07F) * ratio_min / ratio_min_div;
|
||||
slv_dly_max[ch][slice] = (phy_slv_dly_avg[ch][slice] & 0x07F) * ratio_max / ratio_max_div;
|
||||
if (slv_dly_max[ch][slice] > 0x7F)
|
||||
slv_dly_max[ch][slice] = 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_SLV_DLY_CTRL_GATE_DISABLE, 0x1);
|
||||
|
||||
for (i = 0; i <= 0x7F; i++) {
|
||||
r_foreach_vch(dev, ch) {
|
||||
for (slice = 0; slice < SLICE_CNT; slice++) {
|
||||
|
@ -3621,13 +3567,16 @@ static void dbsc5_manual_write_dca(struct udevice *dev)
|
|||
for (slice = 0; slice < SLICE_CNT; slice++) {
|
||||
dbsc5_ddr_setval_slice(dev, ch, slice,
|
||||
PHY_CLK_WRDQS_SLAVE_DELAY,
|
||||
slv_dly_center[ch][cs][slice]);
|
||||
phy_slv_dly[ch][cs][slice]);
|
||||
dbsc5_ddr_setval_slice(dev, ch, slice,
|
||||
SC_PHY_WCK_CALC, 0x1);
|
||||
dbsc5_ddr_setval(dev, ch, SC_PHY_MANUAL_UPDATE, 0x1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_SLV_DLY_CTRL_GATE_DISABLE, 0x0);
|
||||
|
||||
dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_PER_CS_TRAINING_MULTICAST_EN, 0x1);
|
||||
|
||||
r_foreach_vch(dev, ch) {
|
||||
|
@ -4369,16 +4318,20 @@ static int renesas_dbsc5_dram_probe(struct udevice *dev)
|
|||
{
|
||||
#define RST_MODEMR0 0x0
|
||||
#define RST_MODEMR1 0x4
|
||||
#define OTP_MONITOR17 0x1144
|
||||
struct renesas_dbsc5_data *data = (struct renesas_dbsc5_data *)dev_get_driver_data(dev);
|
||||
ofnode cnode = ofnode_by_compatible(ofnode_null(), data->clock_node);
|
||||
ofnode rnode = ofnode_by_compatible(ofnode_null(), data->reset_node);
|
||||
ofnode onode = ofnode_by_compatible(ofnode_null(), data->otp_node);
|
||||
struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev);
|
||||
void __iomem *regs_dbsc_a = priv->regs + DBSC5_DBSC_A_OFFSET;
|
||||
void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET;
|
||||
phys_addr_t rregs = ofnode_get_addr(rnode);
|
||||
const u32 modemr0 = readl(rregs + RST_MODEMR0);
|
||||
const u32 modemr1 = readl(rregs + RST_MODEMR1);
|
||||
u32 breg, reg, md, sscg;
|
||||
phys_addr_t oregs = ofnode_get_addr(onode);
|
||||
const u32 otpmon17 = readl(oregs + OTP_MONITOR17);
|
||||
u32 breg, reg, md, sscg, product;
|
||||
u32 ch, cs;
|
||||
|
||||
/* Get board data */
|
||||
|
@ -4433,29 +4386,41 @@ static int renesas_dbsc5_dram_probe(struct udevice *dev)
|
|||
|
||||
/* Decode DDR operating frequency from MD[37:36,19,17] pins */
|
||||
md = ((modemr0 & BIT(19)) >> 18) | ((modemr0 & BIT(17)) >> 17);
|
||||
product = otpmon17 & 0xff;
|
||||
sscg = (modemr1 >> 4) & 0x03;
|
||||
if (sscg == 2) {
|
||||
printf("MD[37:36] setting 0x%x not supported!", sscg);
|
||||
hang();
|
||||
}
|
||||
|
||||
if (md == 0) {
|
||||
if (sscg == 0) {
|
||||
priv->ddr_mbps = 6400;
|
||||
priv->ddr_mbpsdiv = 1;
|
||||
} else {
|
||||
priv->ddr_mbps = 19000;
|
||||
priv->ddr_mbpsdiv = 3;
|
||||
}
|
||||
} else if (md == 1) {
|
||||
priv->ddr_mbps = 6000;
|
||||
priv->ddr_mbpsdiv = 1;
|
||||
} else if (md == 1) {
|
||||
priv->ddr_mbps = 5500;
|
||||
priv->ddr_mbpsdiv = 1;
|
||||
} else if (md == 1) {
|
||||
if (product == 0x2) { /* V4H-3 */
|
||||
priv->ddr_mbps = 4800;
|
||||
priv->ddr_mbpsdiv = 1;
|
||||
} else if (product == 0x1) { /* V4H-5 */
|
||||
if (md == 3)
|
||||
priv->ddr_mbps = 4800;
|
||||
else
|
||||
priv->ddr_mbps = 5000;
|
||||
priv->ddr_mbpsdiv = 1;
|
||||
} else { /* V4H-7 */
|
||||
if (md == 0) {
|
||||
if (sscg == 0) {
|
||||
priv->ddr_mbps = 6400;
|
||||
priv->ddr_mbpsdiv = 1;
|
||||
} else {
|
||||
priv->ddr_mbps = 19000;
|
||||
priv->ddr_mbpsdiv = 3;
|
||||
}
|
||||
} else if (md == 1) {
|
||||
priv->ddr_mbps = 6000;
|
||||
priv->ddr_mbpsdiv = 1;
|
||||
} else if (md == 2) {
|
||||
priv->ddr_mbps = 5500;
|
||||
priv->ddr_mbpsdiv = 1;
|
||||
} else if (md == 3) {
|
||||
priv->ddr_mbps = 4800;
|
||||
priv->ddr_mbpsdiv = 1;
|
||||
}
|
||||
}
|
||||
|
||||
priv->ddr_mul = CLK_DIV(priv->ddr_mbps, priv->ddr_mbpsdiv * 2,
|
||||
|
|
56
include/dbsc5.h
Normal file
56
include/dbsc5.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDE_DBSC5_H__
|
||||
#define __INCLUDE_DBSC5_H__
|
||||
|
||||
/* The number of channels V4H has */
|
||||
#define DRAM_CH_CNT 4
|
||||
/* The number of slices V4H has */
|
||||
#define SLICE_CNT 2
|
||||
/* The number of chip select V4H has */
|
||||
#define CS_CNT 2
|
||||
|
||||
struct renesas_dbsc5_board_config {
|
||||
/* Channels in use */
|
||||
u8 bdcfg_phyvalid;
|
||||
/* Read vref (SoC) training range */
|
||||
u32 bdcfg_vref_r;
|
||||
/* Write vref (MR14, MR15) training range */
|
||||
u16 bdcfg_vref_w;
|
||||
/* CA vref (MR12) training range */
|
||||
u16 bdcfg_vref_ca;
|
||||
/* RFM required check */
|
||||
bool bdcfg_rfm_chk;
|
||||
|
||||
/* Board parameter about channels */
|
||||
struct {
|
||||
/*
|
||||
* 0x00: 4Gb dual channel die / 2Gb single channel die
|
||||
* 0x01: 6Gb dual channel die / 3Gb single channel die
|
||||
* 0x02: 8Gb dual channel die / 4Gb single channel die
|
||||
* 0x03: 12Gb dual channel die / 6Gb single channel die
|
||||
* 0x04: 16Gb dual channel die / 8Gb single channel die
|
||||
* 0x05: 24Gb dual channel die / 12Gb single channel die
|
||||
* 0x06: 32Gb dual channel die / 16Gb single channel die
|
||||
* 0x07: 24Gb single channel die
|
||||
* 0x08: 32Gb single channel die
|
||||
* 0xFF: NO_MEMORY
|
||||
*/
|
||||
u8 bdcfg_ddr_density[CS_CNT];
|
||||
/* SoC caX([6][5][4][3][2][1][0]) -> MEM caY: */
|
||||
u32 bdcfg_ca_swap;
|
||||
/* SoC dqsX([1][0]) -> MEM dqsY: */
|
||||
u8 bdcfg_dqs_swap;
|
||||
/* SoC dq([7][6][5][4][3][2][1][0]) -> MEM dqY/dm: (8 means DM) */
|
||||
u32 bdcfg_dq_swap[SLICE_CNT];
|
||||
/* SoC dm -> MEM dqY/dm: (8 means DM) */
|
||||
u8 bdcfg_dm_swap[SLICE_CNT];
|
||||
/* SoC ckeX([1][0]) -> MEM csY */
|
||||
u8 bdcfg_cs_swap;
|
||||
} ch[4];
|
||||
};
|
||||
|
||||
#endif /* __INCLUDE_DBSC5_H__ */
|
Loading…
Add table
Reference in a new issue