summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/dts/r8a779g0-u-boot.dtsi4
-rw-r--r--board/renesas/common/Makefile2
-rw-r--r--board/renesas/common/gen4-common.c126
-rw-r--r--board/renesas/common/gen4-spl.c2
-rw-r--r--configs/r8a779g0_whitehawk_defconfig2
-rw-r--r--drivers/ram/renesas/dbsc5/dbsc5.c3
-rw-r--r--drivers/ram/renesas/dbsc5/dbsc5.h1
-rw-r--r--drivers/ram/renesas/dbsc5/dram.c167
-rw-r--r--include/dbsc5.h56
9 files changed, 258 insertions, 105 deletions
diff --git a/arch/arm/dts/r8a779g0-u-boot.dtsi b/arch/arm/dts/r8a779g0-u-boot.dtsi
index 10051c9dbfe..cc9d99b0f34 100644
--- a/arch/arm/dts/r8a779g0-u-boot.dtsi
+++ b/arch/arm/dts/r8a779g0-u-boot.dtsi
@@ -147,6 +147,10 @@
bootph-all;
};
+&otp {
+ bootph-all;
+};
+
&pfc {
bootph-all;
};
diff --git a/board/renesas/common/Makefile b/board/renesas/common/Makefile
index 347be5cc93c..5e51b691178 100644
--- a/board/renesas/common/Makefile
+++ b/board/renesas/common/Makefile
@@ -1,6 +1,4 @@
#
-# board/renesas/whitehawk/Makefile
-#
# Copyright (C) 2024 Marek Vasut <marek.vasut+renesas@mailbox.org>
#
# SPDX-License-Identifier: GPL-2.0+
diff --git a/board/renesas/common/gen4-common.c b/board/renesas/common/gen4-common.c
index 52a0639073b..f7d129be4c8 100644
--- a/board/renesas/common/gen4-common.c
+++ b/board/renesas/common/gen4-common.c
@@ -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();
+}
diff --git a/board/renesas/common/gen4-spl.c b/board/renesas/common/gen4-spl.c
index e46ef0a3075..ebfefab7253 100644
--- a/board/renesas/common/gen4-spl.c
+++ b/board/renesas/common/gen4-spl.c
@@ -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>
*/
diff --git a/configs/r8a779g0_whitehawk_defconfig b/configs/r8a779g0_whitehawk_defconfig
index b49a81dcd49..8dcf8e35ee0 100644
--- a/configs/r8a779g0_whitehawk_defconfig
+++ b/configs/r8a779g0_whitehawk_defconfig
@@ -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"
diff --git a/drivers/ram/renesas/dbsc5/dbsc5.c b/drivers/ram/renesas/dbsc5/dbsc5.c
index d24b7c5c30a..4cbc6aeda43 100644
--- a/drivers/ram/renesas/dbsc5/dbsc5.c
+++ b/drivers/ram/renesas/dbsc5/dbsc5.c
@@ -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[] = {
diff --git a/drivers/ram/renesas/dbsc5/dbsc5.h b/drivers/ram/renesas/dbsc5/dbsc5.h
index c410eb0c5ed..bf22fcb8c11 100644
--- a/drivers/ram/renesas/dbsc5/dbsc5.h
+++ b/drivers/ram/renesas/dbsc5/dbsc5.h
@@ -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__ */
diff --git a/drivers/ram/renesas/dbsc5/dram.c b/drivers/ram/renesas/dbsc5/dram.c
index 210a68f6496..6f78afb0ab5 100644
--- a/drivers/ram/renesas/dbsc5/dram.c
+++ b/drivers/ram/renesas/dbsc5/dram.c
@@ -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,
diff --git a/include/dbsc5.h b/include/dbsc5.h
new file mode 100644
index 00000000000..cec937d89e7
--- /dev/null
+++ b/include/dbsc5.h
@@ -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__ */