[PATCH 1/2] ram: renesas: Add Renesas R-Car Gen4 DBSC5 driver

Add Renesas R-Car Gen4 DBSC5 DRAM controller driver. This driver is currently capable of bringing LPDDR5 DRAM on Renesas R-Car V4H Whitehawk board. Further boards can be supported by supplying board specific DRAM configuration data via dbsc5_get_board_data(). Support for R-Car V4M is not implemented, however the driver is already mostly prepared to support this SoC.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org --- Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com Cc: u-boot@lists.denx.de --- drivers/ram/Kconfig | 1 + drivers/ram/renesas/Kconfig | 7 + drivers/ram/renesas/Makefile | 3 + drivers/ram/renesas/dbsc5/Makefile | 3 + drivers/ram/renesas/dbsc5/dbsc5.c | 79 + drivers/ram/renesas/dbsc5/dbsc5.h | 28 + drivers/ram/renesas/dbsc5/dram.c | 4532 ++++++++++++++++++++++++++++ drivers/ram/renesas/dbsc5/qos.c | 636 ++++ drivers/ram/renesas/dbsc5/rtvram.c | 93 + 9 files changed, 5382 insertions(+) create mode 100644 drivers/ram/renesas/Kconfig create mode 100644 drivers/ram/renesas/dbsc5/Makefile create mode 100644 drivers/ram/renesas/dbsc5/dbsc5.c create mode 100644 drivers/ram/renesas/dbsc5/dbsc5.h create mode 100644 drivers/ram/renesas/dbsc5/dram.c create mode 100644 drivers/ram/renesas/dbsc5/qos.c create mode 100644 drivers/ram/renesas/dbsc5/rtvram.c
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig index f7e357f24da..2b0cd312883 100644 --- a/drivers/ram/Kconfig +++ b/drivers/ram/Kconfig @@ -119,6 +119,7 @@ config IMXRT_SDRAM source "drivers/ram/aspeed/Kconfig" source "drivers/ram/cadence/Kconfig" source "drivers/ram/octeon/Kconfig" +source "drivers/ram/renesas/Kconfig" source "drivers/ram/rockchip/Kconfig" source "drivers/ram/sifive/Kconfig" source "drivers/ram/stm32mp1/Kconfig" diff --git a/drivers/ram/renesas/Kconfig b/drivers/ram/renesas/Kconfig new file mode 100644 index 00000000000..6a1ef2a0c63 --- /dev/null +++ b/drivers/ram/renesas/Kconfig @@ -0,0 +1,7 @@ +config RAM_RENESAS_DBSC5 + bool "Renesas R-Car V4H/V4M DBSC5 controller driver" + depends on SPL && RAM && (R8A779G0 || R8A779H0) + default n + help + Enable this to support the DBSC5 DRAM controller initialization + on Renesas R8A779G0/R8A779H0 SoCs. diff --git a/drivers/ram/renesas/Makefile b/drivers/ram/renesas/Makefile index 705cc4b6fa5..578d05622d7 100644 --- a/drivers/ram/renesas/Makefile +++ b/drivers/ram/renesas/Makefile @@ -1,3 +1,6 @@ # SPDX-License-Identifier: GPL-2.0+
+ifdef CONFIG_XPL_BUILD +obj-$(CONFIG_RAM_RENESAS_DBSC5) += dbsc5/ +endif obj-$(CONFIG_RZN1) += rzn1/ diff --git a/drivers/ram/renesas/dbsc5/Makefile b/drivers/ram/renesas/dbsc5/Makefile new file mode 100644 index 00000000000..177be893e10 --- /dev/null +++ b/drivers/ram/renesas/dbsc5/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += dbsc5.o dram.o qos.o rtvram.o diff --git a/drivers/ram/renesas/dbsc5/dbsc5.c b/drivers/ram/renesas/dbsc5/dbsc5.c new file mode 100644 index 00000000000..d24b7c5c30a --- /dev/null +++ b/drivers/ram/renesas/dbsc5/dbsc5.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +#include <asm/io.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <errno.h> +#include <linux/sizes.h> +#include <ram.h> +#include "dbsc5.h" + +static int renesas_dbsc5_probe(struct udevice *dev) +{ + struct udevice *pdev; + int ret; + + ret = uclass_get_device_by_name(UCLASS_RAM, "dbsc5_dram", &pdev); + if (ret) + return ret; + + ret = uclass_get_device_by_name(UCLASS_NOP, "dbsc5_qos", &pdev); + if (ret) + return ret; + + return 0; +} + +int renesas_dbsc5_bind(struct udevice *dev) +{ + struct udevice *ramdev, *qosdev; + struct driver *ramdrv, *qosdrv; + int ret; + + ramdrv = lists_driver_lookup_name("dbsc5_dram"); + if (!ramdrv) + return -ENOENT; + + + qosdrv = lists_driver_lookup_name("dbsc5_qos"); + if (!qosdrv) + return -ENOENT; + + ret = device_bind_with_driver_data(dev, ramdrv, "dbsc5_dram", + dev_get_driver_data(dev), + dev_ofnode(dev), &ramdev); + if (ret) + return ret; + + ret = device_bind_with_driver_data(dev, qosdrv, "dbsc5_qos", 0, + dev_ofnode(dev), &qosdev); + if (ret) + device_unbind(ramdev); + + return ret; +} + +struct renesas_dbsc5_data r8a779g0_dbsc5_data = { + .clock_node = "renesas,r8a779g0-cpg-mssr", + .reset_node = "renesas,r8a779g0-rst" +}; + +static const struct udevice_id renesas_dbsc5_ids[] = { + { + .compatible = "renesas,r8a779g0-dbsc", + .data = (ulong)&r8a779g0_dbsc5_data + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(renesas_dbsc5) = { + .name = "dbsc5", + .id = UCLASS_NOP, + .of_match = renesas_dbsc5_ids, + .bind = renesas_dbsc5_bind, + .probe = renesas_dbsc5_probe, +}; diff --git a/drivers/ram/renesas/dbsc5/dbsc5.h b/drivers/ram/renesas/dbsc5/dbsc5.h new file mode 100644 index 00000000000..c410eb0c5ed --- /dev/null +++ b/drivers/ram/renesas/dbsc5/dbsc5.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +#ifndef __DRIVERS_RAM_RENESAS_DBSC5_DBSC5_H__ +#define __DRIVERS_RAM_RENESAS_DBSC5_DBSC5_H__ + +/* + * DBSC5 ... 0xe678_0000..0xe67fffff + * - AXMM_BASE 0xe6780000 MM (DDR Hier) MM AXI Router - Region 0 + * - DBSC_A_BASE 0xe6790000 MM (DDR Hier) DBSC0A - Region 0 + * - CCI_BASE 0xe67A0000 MM (DDR Hier) FBA for MM + * - DBSC_D_BASE 0xE67A4000 MM (DDR Hier) DBSC0D - Region 0 + * - QOS_BASE 0xe67E0000 MM (DDR Hier) M-STATQ (64kiB) + */ +#define DBSC5_AXMM_OFFSET 0x00000 +#define DBSC5_DBSC_A_OFFSET 0x10000 +#define DBSC5_CCI_OFFSET 0x20000 +#define DBSC5_DBSC_D_OFFSET 0x24000 +#define DBSC5_QOS_OFFSET 0x60000 + +struct renesas_dbsc5_data { + const char *clock_node; + const char *reset_node; +}; + +#endif /* __DRIVERS_RAM_RENESAS_DBSC5_DBSC5_H__ */ diff --git a/drivers/ram/renesas/dbsc5/dram.c b/drivers/ram/renesas/dbsc5/dram.c new file mode 100644 index 00000000000..210a68f6496 --- /dev/null +++ b/drivers/ram/renesas/dbsc5/dram.c @@ -0,0 +1,4532 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include <hang.h> +#include <ram.h> +#include <linux/iopoll.h> +#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 */ +#define DDR_PHY_SLICE_REGSET_NUM_V4H 153 +/* Number of array elements in Address Slice */ +#define DDR_PHY_ADR_V_REGSET_NUM_V4H 61 +/* Number of array elements in Address Control Slice */ +#define DDR_PHY_ADR_G_REGSET_NUM_V4H 97 +/* Number of array elements in PI Register */ +#define DDR_PI_REGSET_NUM_V4H 1381 + +/* Minimum value table for JS1 configuration table that can be taken */ +#define JS1_USABLEC_SPEC_LO 5 +/* Maximum value table for JS1 configuration table that can be taken */ +#define JS1_USABLEC_SPEC_HI 11 +/* The number of JS1 setting table */ +#define JS1_FREQ_TBL_NUM 12 +/* Macro to set the value of MR1 */ +#define JS1_MR1(f) (((f) << 4) | 0x00) /* CK mode = 0B */ +/* Macro to set the value of MR2 */ +#define JS1_MR2(f) (((f) << 4) | (f)) + +#define JS2_tSR 0 /* Element for self refresh */ +#define JS2_tXP 1 /* Exit power-down mode to first valid command */ +#define JS2_tRCD 2 /* Active to read or write delay */ +#define JS2_tRPpb 3 /* Minimum Row Precharge Delay Time */ +#define JS2_tRPab 4 /* Minimum Row Precharge Delay Time */ +#define JS2_tRAS 5 /* ACTIVE-to-PRECHARGE command */ +#define JS2_tWTR_S 6 /* Internal WRITE-to-READ command delay */ +#define JS2_tWTR_L 7 /* Internal WRITE-to-READ command delay */ +#define JS2_tRRD 8 /* Active bank a to active bank b command */ +#define JS2_tPPD 9 /* Precharge Power Down */ +#define JS2_tFAW 10 /* Four bank ACT window */ +#define JS2_tMRR 11 /* Mode Register Read */ +#define JS2_tMRW 12 /* Mode Register Write */ +#define JS2_tMRD 13 /* LOAD MODE REGISTER command cycle time */ +#define JS2_tZQCALns 14 /* ZQ Calibration */ +#define JS2_tZQLAT 15 /* ZQ Latency */ +#define JS2_tODTon_min 16 /* Minimum time on die termination */ +#define JS2_tPDN_DSM 17 /* Recommended minimum time for Deep Sleep Mode duration */ +#define JS2_tXSR_DSM 18 /* Required time to be fully re-powered up from Deep Sleep Mode */ +#define JS2_tXDSM_XP 19 /* Delay from Deep Sleep Mode Exit to Power-Down Exit */ +#define JS2_tWCK2DQI_HF 20 /* Setting value of DQ to WCK input offset */ +#define JS2_tWCK2DQO_HF 21 /* Setting value of WCK to DQ output offset */ +#define JS2_tWCK2DQI_LF 22 /* Setting value of DQ to WCK input offset */ +#define JS2_tWCK2DQO_LF 23 /* Setting value of WCK to DQ output offset */ +#define JS2_tOSCODQI 24 /* Delay time from Stop WCK2DQI Interval Oscillator command to Mode Register Readout */ +#define JS2_tDQ72DQns 25 /* Reception time to change the value fof REF(CA) for Command Bus Training Mode2 */ +#define JS2_tCAENTns 26 /* Reception time to change the value fof REF(CA) for Command Bus Training Mode1 */ +#define JS2_tCSCAL 27 /* Minimum CA Low Duration time */ +#define JS2_TBLCNT 28 /* The number of table */ + +#define JS2_tRCpb JS2_TBLCNT /* ACTIVATE-to-ACTIVATE command period with per bank precharge */ +#define JS2_tRCab (JS2_TBLCNT + 1) /* ACTIVATE-to-ACTIVATE command period with all bank precharge */ +#define JS2_tRFCab (JS2_TBLCNT + 2) /* Refresh Cycle Time with All Banks */ +#define JS2_tRBTP (JS2_TBLCNT + 3) /* READ Burst end to PRECHARGE command delay */ +#define JS2_tXSR (JS2_TBLCNT + 4) /* Exit Self Refresh to Valid commands */ +#define JS2_tPDN (JS2_TBLCNT + 5) +#define JS2_tWLWCKOFF (JS2_TBLCNT + 6) +#define JS2_CNT (JS2_TBLCNT + 7) + +struct jedec_spec1 { + u32 fx3; /* Frequency */ + u8 RLset1; /* setting value of Read Latency */ + u8 RLset2; /* setting value of Read Latency */ + u8 WLsetA; /* setting value of Write Latency */ + u8 WLsetB; /* setting value of Write Latency */ + u32 nWR; /* Write-Recovery for Auto-Precharge commands */ + u32 nRBTP; /* the minimum interval from a READ command to a PRE command */ + u32 ODTLon; /* On Die Termination */ + u8 MR1; /* Mode Register 1 */ + u8 MR2; /* Mode Register 2 */ + u32 WCKENLR; /* The setting time from CAS command to the Start-up of WCK in READ operation */ + u32 WCKENLW; /* The setting time from CAS command to the Start-up of WCK in WRITE operation */ + u32 WCKENLF; /* The setting time from CAS command to the Start-up of WCK in FAST-sync operation */ + u32 WCKPRESTA; /* The setting time from the Start-up of WCK to WCK Clocling Start */ + u32 WCKPRETGLR; /* The setting time from WCK Clocling Start to Reflecting frequency of WCK */ +}; + +static const struct jedec_spec1 js1[JS1_FREQ_TBL_NUM] = { + /* fx3, RL1, RL2, WLA.WLB.nWR.nRBTP, ODTLon */ + { 800, 3, 3, 2, 2, 3, 0, 1, JS1_MR1(0), JS1_MR2(0), 0, 0, 0, 1, 3 }, /* 533.333Mbps*/ + { 1600, 4, 4, 2, 3, 5, 0, 1, JS1_MR1(1), JS1_MR2(1), 0, 0, 0, 1, 4 }, /* 1066.666Mbps*/ + { 2400, 5, 6, 3, 4, 7, 0, 2, JS1_MR1(2), JS1_MR2(2), 1, 1, 1, 1, 4 }, /* 1600.000Mbps*/ + { 3200, 7, 7, 4, 5, 10, 0, 2, JS1_MR1(3), JS1_MR2(3), 2, 1, 1, 2, 4 }, /* 2133.333Mbps*/ + { 4000, 8, 9, 4, 7, 12, 1, 2, JS1_MR1(4), JS1_MR2(4), 2, 1, 1, 2, 5 }, /* 2666.666Mbps*/ + { 4800, 10, 10, 5, 8, 14, 1, 3, JS1_MR1(5), JS1_MR2(5), 4, 2, 1, 2, 5 }, /* 3200.000Mbps*/ + { 5600, 11, 12, 6, 9, 16, 2, 4, JS1_MR1(6), JS1_MR2(6), 4, 2, 1, 3, 5 }, /* 3733.333Mbps*/ + { 6400, 13, 14, 6, 11, 19, 2, 3, JS1_MR1(7), JS1_MR2(7), 5, 2, 1, 3, 6 }, /* 4266.666Mbps*/ + { 7200, 14, 15, 7, 12, 21, 3, 4, JS1_MR1(8), JS1_MR2(8), 6, 3, 2, 3, 6 }, /* 4800.000Mbps*/ + { 8250, 16, 17, 8, 14, 24, 4, 5, JS1_MR1(9), JS1_MR2(9), 7, 3, 2, 4, 6 }, /* 5500.000Mbps*/ + { 9000, 17, 19, 9, 15, 26, 4, 6, JS1_MR1(10), JS1_MR2(10), 7, 4, 2, 4, 7 }, /* 6000.000Mbps*/ + { 9600, 18, 20, 9, 16, 28, 4, 6, JS1_MR1(11), JS1_MR2(11), 8, 4, 2, 4, 7 } /* 6400.000Mbps*/ +}; + +struct jedec_spec2 { + u16 ps; /* Value in pico seconds */ + u16 cyc; /* Value in cycle count */ +}; + +static const struct jedec_spec2 jedec_spec2[2][JS2_TBLCNT] = { + { + { 15000, 2 }, /* tSR */ + { 7000, 3 }, /* tXP */ + { 18000, 2 }, /* tRCD */ + { 18000, 2 }, /* tRPpb */ + { 21000, 2 }, /* tRPab */ + { 42000, 3 }, /* tRAS */ + { 6250, 4 }, /* tWTR_S */ + { 12000, 4 }, /* tWTR_L */ + { 5000, 2 }, /* tRRD */ + { 0, 2 }, /* tPPD */ + { 20000, 0 }, /* tFAW */ + { 0, 4 }, /* tMRR */ + { 10000, 5 }, /* tMRW */ + { 14000, 5 }, /* tMRD */ + { 1500, 0 }, /* tZQCALns */ + { 30000, 4 }, /* tZQLAT */ + { 1500, 0 }, /* tODTon_min */ + { 4000, 0 }, /* tPDN_DSMus */ + { 200, 0 }, /* tXSR_DSMus */ + { 190, 0 }, /* tXDSM_XPus */ + { 700, 0 }, /* tWCK2DQI_HF */ + { 1600, 0 }, /* tWCK2DQO_HF */ + { 900, 0 }, /* tWCK2DQI_LF */ + { 1900, 0 }, /* tWCK2DQO_LF */ + { 40000, 8 }, /* tOSCODQI */ + { 125, 0 }, /* tDQ72DQns */ + { 250, 0 }, /* tCAENTns */ + { 1750, 0 } /* tCSCAL */ + }, { + { 15000, 2 }, /* tSR */ + { 7000, 3 }, /* tXP */ + { 19875, 2 }, /* tRCD */ + { 19875, 2 }, /* tRPpb */ + { 22875, 2 }, /* tRPab */ + { 43875, 3 }, /* tRAS */ + { 6250, 4 }, /* tWTR_S */ + { 12000, 4 }, /* tWTR_L */ + { 5000, 2 }, /* tRRD */ + { 0, 2 }, /* tPPD */ + { 20000, 0 }, /* tFAW */ + { 0, 4 }, /* tMRR */ + { 10000, 5 }, /* tMRW */ + { 14000, 5 }, /* tMRD */ + { 1500, 0 }, /* tZQCALns */ + { 30000, 4 }, /* tZQLAT */ + { 1500, 0 }, /* tODTon_min */ + { 4000, 0 }, /* tPDN_DSMus */ + { 200, 0 }, /* tXSR_DSMus */ + { 190, 0 }, /* tXDSM_XPus */ + { 715, 0 }, /* tWCK2DQI_HF */ + { 1635, 0 }, /* tWCK2DQO_HF */ + { 920, 0 }, /* tWCK2DQI_LF */ + { 1940, 0 }, /* tWCK2DQO_LF */ + { 40000, 8 }, /* tOSCODQI */ + { 125, 0 }, /* tDQ72DQns */ + { 250, 0 }, /* tCAENTns */ + { 1750, 0 } /* tCSCAL */ + } +}; + +static const u16 jedec_spec2_tRFC_ab[] = { + /* 2Gb, 3Gb, 4Gb, 6Gb, 8Gb, 12Gb, 16Gb, 24Gb, 32Gb */ + 130, 180, 180, 210, 210, 280, 280, 380, 380 +}; + +/* The address offsets of PI Register */ +#define DDR_PI_REGSET_OFS_V4H 0x0800 +/* The address offsets of Data Slice */ +#define DDR_PHY_SLICE_REGSET_OFS_V4H 0x1000 +/* The address offsets of Address Slice */ +#define DDR_PHY_ADR_V_REGSET_OFS_V4H 0x1200 +/* The address offsets of Address Control Slice */ +#define DDR_PHY_ADR_G_REGSET_OFS_V4H 0x1300 + +#define DDR_REGDEF_ADR(regdef) ((regdef) & 0xFFFF) +#define DDR_REGDEF_LEN(regdef) (((regdef) >> 16) & 0xFF) +#define DDR_REGDEF_LSB(regdef) (((regdef) >> 24) & 0xFF) + +#define DDR_REGDEF(lsb, len, adr) \ + (((lsb) << 24) | ((len) << 16) | (adr)) + +#define PHY_LP4_BOOT_RX_PCLK_CLK_SEL DDR_REGDEF(0x10, 0x03, 0x1000) +#define PHY_PER_CS_TRAINING_MULTICAST_EN DDR_REGDEF(0x10, 0x01, 0x1006) +#define PHY_PER_CS_TRAINING_INDEX DDR_REGDEF(0x18, 0x01, 0x1006) +#define PHY_VREF_INITIAL_STEPSIZE DDR_REGDEF(0x18, 0x08, 0x100D) +#define PHY_RDLVL_BEST_THRSHLD DDR_REGDEF(0x00, 0x04, 0x100E) +#define PHY_RDLVL_VREF_OUTLIER DDR_REGDEF(0x10, 0x03, 0x100E) +#define SC_PHY_WCK_CALC DDR_REGDEF(0x18, 0x01, 0x101A) +#define PHY_RDLVL_RDDQS_DQ_OBS_SELECT DDR_REGDEF(0x10, 0x05, 0x102C) +#define PHY_CALVL_VREF_DRIVING_SLICE DDR_REGDEF(0x18, 0x01, 0x1030) +#define PHY_WRLVL_HARD0_DELAY_OBS DDR_REGDEF(0x00, 0x0A, 0x1038) +#define PHY_WRLVL_HARD1_DELAY_OBS DDR_REGDEF(0x10, 0x0A, 0x1038) +#define PHY_WRLVL_STATUS_OBS DDR_REGDEF(0x00, 0x1C, 0x1039) +#define PHY_WRLVL_ERROR_OBS DDR_REGDEF(0x00, 0x10, 0x103B) +#define PHY_GTLVL_STATUS_OBS DDR_REGDEF(0x00, 0x12, 0x103D) +#define PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS DDR_REGDEF(0x10, 0x09, 0x103E) +#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_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) +#define PHY_VREF_TRAINING_CTRL DDR_REGDEF(0x00, 0x02, 0x1056) +#define PHY_RDDQ0_SLAVE_DELAY DDR_REGDEF(0x00, 0x09, 0x105D) +#define PHY_RDDQ1_SLAVE_DELAY DDR_REGDEF(0x10, 0x09, 0x105D) +#define PHY_RDDQ2_SLAVE_DELAY DDR_REGDEF(0x00, 0x09, 0x105E) +#define PHY_RDDQ3_SLAVE_DELAY DDR_REGDEF(0x10, 0x09, 0x105E) +#define PHY_RDDQ4_SLAVE_DELAY DDR_REGDEF(0x00, 0x09, 0x105F) +#define PHY_RDDQ5_SLAVE_DELAY DDR_REGDEF(0x10, 0x09, 0x105F) +#define PHY_RDDQ6_SLAVE_DELAY DDR_REGDEF(0x00, 0x09, 0x1060) +#define PHY_RDDQ7_SLAVE_DELAY DDR_REGDEF(0x10, 0x09, 0x1060) +#define PHY_RDDM_SLAVE_DELAY DDR_REGDEF(0x00, 0x09, 0x1061) +#define PHY_RX_CAL_ALL_DLY DDR_REGDEF(0x18, 0x06, 0x1061) +#define PHY_RX_PCLK_CLK_SEL DDR_REGDEF(0x00, 0x03, 0x1062) +#define PHY_DATA_DC_CAL_CLK_SEL DDR_REGDEF(0x18, 0x03, 0x1063) +#define PHY_PAD_VREF_CTRL_DQ DDR_REGDEF(0x00, 0x0E, 0x1067) +#define PHY_PER_CS_TRAINING_EN DDR_REGDEF(0x00, 0x01, 0x1068) +#define PHY_RDDATA_EN_TSEL_DLY DDR_REGDEF(0x18, 0x05, 0x1069) +#define PHY_RDDATA_EN_OE_DLY DDR_REGDEF(0x00, 0x05, 0x106A) +#define PHY_RPTR_UPDATE DDR_REGDEF(0x10, 0x04, 0x106C) +#define PHY_WRLVL_RESP_WAIT_CNT DDR_REGDEF(0x08, 0x06, 0x106D) +#define PHY_RDLVL_DLY_STEP DDR_REGDEF(0x08, 0x04, 0x1070) +#define PHY_RDLVL_MAX_EDGE DDR_REGDEF(0x00, 0x09, 0x1071) +#define PHY_DATA_DC_WDQLVL_ENABLE DDR_REGDEF(0x08, 0x02, 0x1075) +#define PHY_RDDATA_EN_DLY DDR_REGDEF(0x10, 0x05, 0x1076) +#define PHY_MEAS_DLY_STEP_ENABLE DDR_REGDEF(0x08, 0x06, 0x1076) +#define PHY_DQ_DM_SWIZZLE0 DDR_REGDEF(0x00, 0x20, 0x1077) +#define PHY_DQ_DM_SWIZZLE1 DDR_REGDEF(0x00, 0x04, 0x1078) +#define PHY_CLK_WRDQS_SLAVE_DELAY DDR_REGDEF(0x00, 0x09, 0x107E) +#define PHY_WRITE_PATH_LAT_DEC DDR_REGDEF(0x10, 0x01, 0x107E) +#define PHY_RDDQS_GATE_SLAVE_DELAY DDR_REGDEF(0x00, 0x09, 0x1088) +#define PHY_RDDQS_LATENCY_ADJUST DDR_REGDEF(0x10, 0x05, 0x1088) +#define PHY_WRITE_PATH_LAT_ADD DDR_REGDEF(0x18, 0x03, 0x1088) +#define PHY_WRITE_PATH_LAT_FRAC DDR_REGDEF(0x00, 0x08, 0x1089) +#define PHY_GTLVL_LAT_ADJ_START DDR_REGDEF(0x00, 0x05, 0x108A) +#define PHY_DATA_DC_DQS_CLK_ADJUST DDR_REGDEF(0x00, 0x08, 0x108C) +#define PHY_ADR_CALVL_SWIZZLE0 DDR_REGDEF(0x00, 0x20, 0x1202) +#define PHY_ADR_MEAS_DLY_STEP_ENABLE DDR_REGDEF(0x10, 0x01, 0x1203) +#define PHY_ADR_CALVL_RANK_CTRL DDR_REGDEF(0x18, 0x02, 0x1205) +#define PHY_ADR_CALVL_OBS1 DDR_REGDEF(0x00, 0x20, 0x120A) +#define PHY_ADR_CALVL_OBS2 DDR_REGDEF(0x00, 0x20, 0x120B) +#define PHY_ADR_CALVL_DLY_STEP DDR_REGDEF(0x00, 0x04, 0x1210) +#define PHY_CS_ACS_ALLOCATION_BIT2_2 DDR_REGDEF(0x08, 0x02, 0x1215) +#define PHY_CS_ACS_ALLOCATION_BIT3_2 DDR_REGDEF(0x10, 0x02, 0x1215) +#define PHY_CSLVL_OBS1 DDR_REGDEF(0x00, 0x20, 0x1221) +#define PHY_CLK_DC_CAL_CLK_SEL DDR_REGDEF(0x08, 0x03, 0x123A) +#define PHY_FREQ_SEL_MULTICAST_EN DDR_REGDEF(0x08, 0x01, 0x1301) +#define PHY_FREQ_SEL_INDEX DDR_REGDEF(0x10, 0x02, 0x1301) +#define SC_PHY_MANUAL_UPDATE DDR_REGDEF(0x18, 0x01, 0x1304) +#define PHY_SET_DFI_INPUT_RST_PAD DDR_REGDEF(0x18, 0x01, 0x1311) +#define PHY_CAL_MODE_0 DDR_REGDEF(0x00, 0x0D, 0x132C) +#define PHY_CAL_INTERVAL_COUNT_0 DDR_REGDEF(0x00, 0x20, 0x132D) +#define PHY_DATA_BYTE_ORDER_SEL DDR_REGDEF(0x00, 0x20, 0x133E) +#define PHY_PAD_ACS_RX_PCLK_CLK_SEL DDR_REGDEF(0x10, 0x03, 0x1348) +#define PHY_PLL_CTRL DDR_REGDEF(0x00, 0x0E, 0x134B) +#define PHY_PLL_CTRL_8X DDR_REGDEF(0x10, 0x0E, 0x134B) +#define PHY_CAL_CLK_SELECT_0 DDR_REGDEF(0x00, 0x03, 0x1360) + +#define PI_START DDR_REGDEF(0x00, 0x01, 0x0800) +#define PI_TRAIN_ALL_FREQ_REQ DDR_REGDEF(0x18, 0x01, 0x0802) +#define PI_CS_MAP DDR_REGDEF(0x08, 0x02, 0x0813) +#define PI_WRLVL_REQ DDR_REGDEF(0x10, 0x01, 0x081C) +#define PI_WRLVL_CS_SW DDR_REGDEF(0x18, 0x02, 0x081C) +#define PI_RDLVL_REQ DDR_REGDEF(0x18, 0x01, 0x0824) +#define PI_RDLVL_GATE_REQ DDR_REGDEF(0x00, 0x01, 0x0825) +#define PI_RDLVL_CS_SW DDR_REGDEF(0x08, 0x02, 0x0825) +#define PI_RDLVL_PERIODIC DDR_REGDEF(0x08, 0x01, 0x082E) +#define PI_RDLVL_INTERVAL DDR_REGDEF(0x08, 0x10, 0x0835) +#define PI_DRAMDCA_FLIP_MASK DDR_REGDEF(0x08, 0x02, 0x083B) +#define PI_DRAMDCA_LVL_REQ DDR_REGDEF(0x10, 0x01, 0x083D) +#define PI_DCMLVL_CS_SW DDR_REGDEF(0x18, 0x02, 0x083D) +#define PI_WRDCM_LVL_EN_F1 DDR_REGDEF(0x00, 0x02, 0x083F) +#define PI_DRAMDCA_LVL_EN_F1 DDR_REGDEF(0x08, 0x02, 0x083F) +#define PI_WRDCM_LVL_EN_F2 DDR_REGDEF(0x18, 0x02, 0x083F) +#define PI_DRAMDCA_LVL_EN_F2 DDR_REGDEF(0x00, 0x02, 0x0840) +#define PI_DRAMDCA_LVL_ACTIVE_SEQ_2 DDR_REGDEF(0x00, 0x1B, 0x0868) +#define PI_DRAMDCA_LVL_ACTIVE_SEQ_3 DDR_REGDEF(0x00, 0x1B, 0x0869) +#define PI_DRAMDCA_LVL_ACTIVE_SEQ_4 DDR_REGDEF(0x00, 0x1B, 0x086A) +#define PI_TCKCKEL_F2 DDR_REGDEF(0x18, 0x04, 0x089D) +#define PI_WDQLVL_VREF_EN DDR_REGDEF(0x08, 0x04, 0x089E) +#define PI_WDQLVL_PERIODIC DDR_REGDEF(0x00, 0x01, 0x08A0) +#define PI_WDQLVL_INTERVAL DDR_REGDEF(0x00, 0x10, 0x08A4) +#define PI_INT_STATUS DDR_REGDEF(0x00, 0x20, 0x0900) +#define PI_INT_ACK_0 DDR_REGDEF(0x00, 0x20, 0x0902) +#define PI_INT_ACK_1 DDR_REGDEF(0x00, 0x03, 0x0903) +#define PI_LONG_COUNT_MASK DDR_REGDEF(0x10, 0x05, 0x090F) +#define PI_ADDR_MUX_0 DDR_REGDEF(0x00, 0x03, 0x0910) +#define PI_ADDR_MUX_1 DDR_REGDEF(0x08, 0x03, 0x0910) +#define PI_ADDR_MUX_2 DDR_REGDEF(0x10, 0x03, 0x0910) +#define PI_ADDR_MUX_3 DDR_REGDEF(0x18, 0x03, 0x0910) +#define PI_ADDR_MUX_4 DDR_REGDEF(0x00, 0x03, 0x0911) +#define PI_ADDR_MUX_5 DDR_REGDEF(0x08, 0x03, 0x0911) +#define PI_ADDR_MUX_6 DDR_REGDEF(0x10, 0x03, 0x0911) +#define PI_DATA_BYTE_SWAP_EN DDR_REGDEF(0x18, 0x01, 0x0911) +#define PI_DATA_BYTE_SWAP_SLICE0 DDR_REGDEF(0x00, 0x01, 0x0912) +#define PI_DATA_BYTE_SWAP_SLICE1 DDR_REGDEF(0x08, 0x01, 0x0912) +#define PI_PWRUP_SREFRESH_EXIT DDR_REGDEF(0x18, 0x01, 0x093D) +#define PI_PWRUP_SREFRESH_EXIT DDR_REGDEF(0x18, 0x01, 0x093D) +#define PI_DLL_RST DDR_REGDEF(0x00, 0x01, 0x0941) +#define PI_TDELAY_RDWR_2_BUS_IDLE_F2 DDR_REGDEF(0x00, 0x08, 0x0964) +#define PI_WRLAT_F2 DDR_REGDEF(0x10, 0x07, 0x096A) +#define PI_TWCKENL_WR_ADJ_F2 DDR_REGDEF(0x18, 0x06, 0x096A) +#define PI_TWCKENL_RD_ADJ_F2 DDR_REGDEF(0x00, 0x06, 0x096B) +#define PI_TWCKPRE_STATIC_F2 DDR_REGDEF(0x08, 0x06, 0x096B) +#define PI_TWCKPRE_TOGGLE_RD_F2 DDR_REGDEF(0x18, 0x06, 0x096B) +#define PI_TWCKENL_FS_ADJ_F2 DDR_REGDEF(0x00, 0x06, 0x096C) +#define PI_CASLAT_F2 DDR_REGDEF(0x08, 0x07, 0x096C) +#define PI_TRFC_F2 DDR_REGDEF(0x00, 0x0A, 0x0971) +#define PI_TREF_F2 DDR_REGDEF(0x00, 0x14, 0x0972) +#define PI_TDFI_WRLVL_WW_F0 DDR_REGDEF(0x00, 0x0A, 0x0974) +#define PI_TDFI_WRLVL_WW_F1 DDR_REGDEF(0x00, 0x0A, 0x0975) +#define PI_WRLVL_EN_F2 DDR_REGDEF(0x18, 0x02, 0x0975) +#define PI_TDFI_WRLVL_WW_F2 DDR_REGDEF(0x00, 0x0A, 0x0976) +#define PI_WRLVL_WCKOFF_F2 DDR_REGDEF(0x10, 0x08, 0x0976) +#define PI_RDLVL_EN_F2 DDR_REGDEF(0x18, 0x02, 0x097A) +#define PI_RDLVL_GATE_EN_F2 DDR_REGDEF(0x00, 0x02, 0x097B) +#define PI_RDLVL_VREF_EN_F0 DDR_REGDEF(0x10, 0x04, 0x097B) +#define PI_RDLVL_VREF_EN_F1 DDR_REGDEF(0x00, 0x04, 0x097D) +#define PI_RDLVL_VREF_EN_F2 DDR_REGDEF(0x10, 0x04, 0x097E) +#define PI_RDLAT_ADJ_F2 DDR_REGDEF(0x00, 0x09, 0x0981) +#define PI_WRLAT_ADJ_F2 DDR_REGDEF(0x00, 0x07, 0x0982) +#define PI_TDFI_CALVL_CC_F2 DDR_REGDEF(0x00, 0x0A, 0x0985) +#define PI_TDFI_CALVL_CAPTURE_F2 DDR_REGDEF(0x10, 0x0A, 0x0985) +#define PI_CALVL_EN_F2 DDR_REGDEF(0x10, 0x02, 0x0986) +#define PI_TCAENT_F2 DDR_REGDEF(0x00, 0x0E, 0x0989) +#define PI_TVREF_SHORT_F2 DDR_REGDEF(0x00, 0x0A, 0x098F) +#define PI_TVREF_LONG_F2 DDR_REGDEF(0x10, 0x0A, 0x098F) +#define PI_TVRCG_ENABLE_F2 DDR_REGDEF(0x00, 0x0A, 0x0990) +#define PI_TVRCG_DISABLE_F2 DDR_REGDEF(0x10, 0x0A, 0x0990) +#define PI_CALVL_VREF_INITIAL_START_POINT_F0 DDR_REGDEF(0x00, 0x07, 0x0991) +#define PI_CALVL_VREF_INITIAL_STOP_POINT_F0 DDR_REGDEF(0x08, 0x07, 0x0991) +#define PI_CALVL_VREF_INITIAL_START_POINT_F1 DDR_REGDEF(0x18, 0x07, 0x0991) +#define PI_CALVL_VREF_INITIAL_STOP_POINT_F1 DDR_REGDEF(0x00, 0x07, 0x0992) +#define PI_CALVL_VREF_INITIAL_START_POINT_F2 DDR_REGDEF(0x10, 0x07, 0x0992) +#define PI_CALVL_VREF_INITIAL_STOP_POINT_F2 DDR_REGDEF(0x18, 0x07, 0x0992) +#define PI_TDFI_CALVL_STROBE_F2 DDR_REGDEF(0x08, 0x04, 0x0995) +#define PI_TXP_F2 DDR_REGDEF(0x10, 0x05, 0x0995) +#define PI_TMRWCKEL_F2 DDR_REGDEF(0x18, 0x08, 0x0995) +#define PI_TCKEHDQS_F2 DDR_REGDEF(0x10, 0x06, 0x099D) +#define PI_TFC_F2 DDR_REGDEF(0x00, 0x0A, 0x099E) +#define PI_WDQLVL_VREF_INITIAL_START_POINT_F0 DDR_REGDEF(0x10, 0x07, 0x09A0) +#define PI_WDQLVL_VREF_INITIAL_STOP_POINT_F0 DDR_REGDEF(0x18, 0x07, 0x09A0) +#define PI_WDQLVL_VREF_INITIAL_START_POINT_F1 DDR_REGDEF(0x00, 0x07, 0x09A4) +#define PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1 DDR_REGDEF(0x08, 0x07, 0x09A4) +#define PI_TDFI_WDQLVL_WR_F2 DDR_REGDEF(0x00, 0x0A, 0x09A6) +#define PI_TDFI_WDQLVL_RW_F2 DDR_REGDEF(0x10, 0x0A, 0x09A6) +#define PI_WDQLVL_VREF_INITIAL_START_POINT_F2 DDR_REGDEF(0x00, 0x07, 0x09A7) +#define PI_WDQLVL_VREF_INITIAL_STOP_POINT_F2 DDR_REGDEF(0x08, 0x07, 0x09A7) +#define PI_WDQLVL_EN_F2 DDR_REGDEF(0x18, 0x02, 0x09A7) +#define PI_MBIST_RDLAT_ADJ_F2 DDR_REGDEF(0x08, 0x09, 0x09A8) +#define PI_MBIST_TWCKENL_RD_ADJ_F2 DDR_REGDEF(0x18, 0x06, 0x09A8) +#define PI_TRTP_F2 DDR_REGDEF(0x18, 0x08, 0x09B3) +#define PI_TRP_F2 DDR_REGDEF(0x00, 0x08, 0x09B4) +#define PI_TRCD_F2 DDR_REGDEF(0x08, 0x08, 0x09B4) +#define PI_TWTR_S_F2 DDR_REGDEF(0x18, 0x06, 0x09B4) +#define PI_TWTR_L_F2 DDR_REGDEF(0x00, 0x06, 0x09B5) +#define PI_TWTR_F2 DDR_REGDEF(0x10, 0x06, 0x09B5) +#define PI_TWR_F2 DDR_REGDEF(0x18, 0x08, 0x09B5) +#define PI_TRAS_MIN_F2 DDR_REGDEF(0x10, 0x09, 0x09B6) +#define PI_TDQSCK_MAX_F2 DDR_REGDEF(0x00, 0x04, 0x09B7) +#define PI_TSR_F2 DDR_REGDEF(0x10, 0x08, 0x09B7) +#define PI_TMRD_F2 DDR_REGDEF(0x18, 0x08, 0x09B7) +#define PI_TDFI_CTRLUPD_MAX_F2 DDR_REGDEF(0x00, 0x15, 0x09BC) +#define PI_TDFI_CTRLUPD_INTERVAL_F2 DDR_REGDEF(0x00, 0x20, 0x09BD) +#define PI_TINIT_F2 DDR_REGDEF(0x00, 0x18, 0x09CC) +#define PI_TINIT1_F2 DDR_REGDEF(0x00, 0x18, 0x09CD) +#define PI_TINIT3_F2 DDR_REGDEF(0x00, 0x18, 0x09CE) +#define PI_TINIT4_F2 DDR_REGDEF(0x00, 0x18, 0x09CF) +#define PI_TINIT5_F2 DDR_REGDEF(0x00, 0x18, 0x09D0) +#define PI_TXSNR_F2 DDR_REGDEF(0x00, 0x10, 0x09D1) +#define PI_TZQCAL_F2 DDR_REGDEF(0x10, 0x0C, 0x09D6) +#define PI_TZQLAT_F2 DDR_REGDEF(0x00, 0x07, 0x09D7) +#define PI_ZQRESET_F2 DDR_REGDEF(0x10, 0x0C, 0x09D8) +#define PI_TDQ72DQ_F2 DDR_REGDEF(0x10, 0x0A, 0x09DD) +#define PI_TCBTRTW_F2 DDR_REGDEF(0x00, 0x06, 0x09DE) +#define PI_MC_TRFC_F2 DDR_REGDEF(0x00, 0x0A, 0x09E1) +#define PI_CKE_MUX_0 DDR_REGDEF(0x00, 0x03, 0x09E6) +#define PI_CKE_MUX_1 DDR_REGDEF(0x08, 0x03, 0x09E6) +#define PI_SEQ_DEC_SW_CS DDR_REGDEF(0x00, 0x02, 0x0A4E) +#define PI_SW_SEQ_START DDR_REGDEF(0x10, 0x01, 0x0A4E) +#define PI_SW_SEQ_0 DDR_REGDEF(0x00, 0x1B, 0x0BF1) +#define PI_SW_SEQ_1 DDR_REGDEF(0x00, 0x1B, 0x0BF2) +#define PI_DFS_ENTRY_SEQ_0 DDR_REGDEF(0x00, 0x1D, 0x0BFB) +#define PI_DFS_INITIALIZATION_SEQ_1 DDR_REGDEF(0x00, 0x1D, 0x0C24) +#define PI_DFS_INITIALIZATION_SEQ_9 DDR_REGDEF(0x00, 0x1D, 0x0C2C) +#define PI_DFS_INITIALIZATION_SEQ_10 DDR_REGDEF(0x00, 0x1D, 0x0C2D) +#define PI_RDLVL_TRAIN_SEQ_1 DDR_REGDEF(0x00, 0x1B, 0x0C42) +#define PI_RDLVL_TRAIN_SEQ_2 DDR_REGDEF(0x00, 0x1B, 0x0C43) +#define PI_RDLVL_TRAIN_SEQ_3 DDR_REGDEF(0x00, 0x1B, 0x0C44) +#define PI_RDLVL_TRAIN_SEQ_4 DDR_REGDEF(0x00, 0x1B, 0x0C45) +#define PI_RDLVL_TRAIN_SEQ_5 DDR_REGDEF(0x00, 0x1B, 0x0C46) +#define PI_SEQ_WAIT_16_F2 DDR_REGDEF(0x00, 0x18, 0x0C77) +#define PI_SEQ_WAIT_17_F2 DDR_REGDEF(0x00, 0x18, 0x0C7A) +#define PI_SEQ_WAIT_18_F2 DDR_REGDEF(0x00, 0x18, 0x0C7D) +#define PI_SEQ_WAIT_19_F2 DDR_REGDEF(0x00, 0x18, 0x0C80) +#define PI_SEQ_WAIT_20_F2 DDR_REGDEF(0x00, 0x18, 0x0C83) +#define PI_SEQ_WAIT_21_F2 DDR_REGDEF(0x00, 0x18, 0x0C86) +#define PI_SEQ_WAIT_22_F2 DDR_REGDEF(0x00, 0x18, 0x0C89) +#define PI_SEQ_WAIT_23_F2 DDR_REGDEF(0x00, 0x18, 0x0C8C) +#define PI_SEQ_WAIT_24_F2 DDR_REGDEF(0x00, 0x18, 0x0C8F) +#define PI_SEQ_WAIT_25_F2 DDR_REGDEF(0x00, 0x18, 0x0C92) +#define PI_SEQ_WAIT_26_F2 DDR_REGDEF(0x00, 0x18, 0x0C95) +#define PI_SEQ_WAIT_30_F2 DDR_REGDEF(0x00, 0x18, 0x0CA1) +#define PI_DARRAY3_0_CS0_F0 DDR_REGDEF(0x00, 0x08, 0x0D0B) +#define PI_DARRAY3_1_CS0_F0 DDR_REGDEF(0x08, 0x08, 0x0D0B) +#define PI_DARRAY3_0_CS0_F1 DDR_REGDEF(0x00, 0x08, 0x0D15) +#define PI_DARRAY3_1_CS0_F1 DDR_REGDEF(0x08, 0x08, 0x0D15) +#define PI_DARRAY3_0_CS0_F2 DDR_REGDEF(0x00, 0x08, 0x0D1F) +#define PI_DARRAY3_1_CS0_F2 DDR_REGDEF(0x08, 0x08, 0x0D1F) +#define PI_DARRAY3_4_CS0_F2 DDR_REGDEF(0x00, 0x08, 0x0D20) +#define PI_DARRAY3_20_CS0_F2 DDR_REGDEF(0x00, 0x08, 0x0D24) +#define PI_DARRAY3_0_CS1_F0 DDR_REGDEF(0x00, 0x08, 0x0D29) +#define PI_DARRAY3_1_CS1_F0 DDR_REGDEF(0x08, 0x08, 0x0D29) +#define PI_DARRAY3_0_CS1_F1 DDR_REGDEF(0x00, 0x08, 0x0D33) +#define PI_DARRAY3_1_CS1_F1 DDR_REGDEF(0x08, 0x08, 0x0D33) +#define PI_DARRAY3_0_CS1_F2 DDR_REGDEF(0x00, 0x08, 0x0D3D) +#define PI_DARRAY3_1_CS1_F2 DDR_REGDEF(0x08, 0x08, 0x0D3D) +#define PI_DARRAY3_4_CS1_F2 DDR_REGDEF(0x00, 0x08, 0x0D3E) +#define PI_DARRAY3_20_CS1_F2 DDR_REGDEF(0x00, 0x08, 0x0D42) + +/* The setting table of Data Slice for V4H */ +static const u32 DDR_PHY_SLICE_REGSET_V4H[DDR_PHY_SLICE_REGSET_NUM_V4H] = { + 0x30020370, 0x00000000, 0x01000002, 0x00000000, + 0x00000000, 0x00000000, 0x00010300, 0x04000100, + 0x00010000, 0x01000000, 0x00000000, 0x00000000, + 0x00010000, 0x08010000, 0x00022003, 0x00000000, + 0x040F0100, 0x1404034F, 0x04040102, 0x04040404, + 0x00000100, 0x00000000, 0x00000000, 0x000800C0, + 0x000F18FF, 0x00000000, 0x00000001, 0x00070000, + 0x0000AAAA, 0x00005555, 0x0000B5B5, 0x00004A4A, + 0x00005656, 0x0000A9A9, 0x0000A9A9, 0x0000B5B5, + 0x00000000, 0xBFBF0000, 0xCCCCF7F7, 0x00000000, + 0x00000000, 0x00000000, 0x00080815, 0x08040000, + 0x00000004, 0x00103000, 0x000C0040, 0x00200200, + 0x01010000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000020, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x001F07FF, 0x08000303, + 0x10200080, 0x00000006, 0x00000401, 0x00000000, + 0x20CEC201, 0x00000001, 0x00017706, 0x01007706, + 0x00000000, 0x008D006D, 0x00100001, 0x03FF0100, + 0x00006E01, 0x00000301, 0x00000000, 0x00000000, + 0x00000000, 0x00500050, 0x00500050, 0x00500050, + 0x00500050, 0x0D000050, 0x10100004, 0x06102010, + 0x61619041, 0x07097000, 0x00644180, 0x00803280, + 0x00808001, 0x13010100, 0x02000016, 0x10001003, + 0x06093E42, 0x0F063D01, 0x011700C8, 0x04100140, + 0x00000100, 0x000001D1, 0x05000068, 0x00030402, + 0x01400000, 0x80800300, 0x00160010, 0x76543210, + 0x00000008, 0x03010301, 0x03010301, 0x03010301, + 0x03010301, 0x03010301, 0x00000000, 0x00500050, + 0x00500050, 0x00500050, 0x00500050, 0x00500050, + 0x00500050, 0x00500050, 0x00500050, 0x00500050, + 0x00070087, 0x00000000, 0x08010007, 0x00000000, + 0x20202020, 0x20202020, 0x20202020, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000 +}; + +/* The setting table of Address Slice for V4H */ +static const u32 DDR_PHY_ADR_V_REGSET_V4H[DDR_PHY_ADR_V_REGSET_NUM_V4H] = { + 0x00200030, 0x00200002, 0x76543210, 0x00010001, + 0x06543210, 0x03070000, 0x00001000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x0000807F, + 0x00000001, 0x00000003, 0x00000000, 0x000F0000, + 0x030C000F, 0x00020103, 0x0000000F, 0x00000100, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x02000400, 0x0000002A, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00200101, + 0x10002C03, 0x00000003, 0x00030240, 0x00008008, + 0x00081020, 0x01200000, 0x00010001, 0x00000000, + 0x00100302, 0x003E4208, 0x01400140, 0x01400140, + 0x01400140, 0x01400140, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00020580, 0x03000040, + 0x00000000 +}; + +/* The setting table of Address Control Slice for V4H */ +static const u32 DDR_PHY_ADR_G_REGSET_V4H[DDR_PHY_ADR_G_REGSET_NUM_V4H] = { + 0x00000000, 0x00000100, 0x00000001, 0x23800000, + 0x00000000, 0x01000101, 0x00000000, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00040101, 0x00000000, 0x00000000, 0x00000064, + 0x00000000, 0x00000000, 0x39421B42, 0x00010124, + 0x00520052, 0x00000052, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x07030102, + 0x01030307, 0x00000054, 0x00004096, 0x08200820, + 0x08200820, 0x08200820, 0x08200820, 0x00000820, + 0x004103B8, 0x0000003F, 0x000C0006, 0x00000000, + 0x000004C0, 0x00007A12, 0x00000208, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x03000000, 0x00000000, 0x00000000, 0x04102002, + 0x00041020, 0x01C98C98, 0x3F400000, 0x003F3F3F, + 0x00000000, 0x00000000, 0x76543210, 0x00010198, + 0x00000007, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x01032380, 0x00000100, 0x00000000, 0x31421342, + 0x00308000, 0x00000080, 0x00063F77, 0x00000006, + 0x0000033F, 0x00000000, 0x0000033F, 0x00000000, + 0x0000033F, 0x00000000, 0x00033F00, 0x00CC0000, + 0x00033F77, 0x00000000, 0x00033F00, 0x00EE0000, + 0x00033F00, 0x00EE0000, 0x00033F00, 0x00EE0000, + 0x00200106 +}; + +/* The setting table of PI Register for V4H */ +static const u32 DDR_PI_REGSET_V4H[DDR_PI_REGSET_NUM_V4H] = { + 0x00000D00, 0x00010100, 0x00640004, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0x02010000, 0x00000003, 0x00000005, + 0x00000002, 0x00000000, 0x00000101, 0x0012080E, + 0x00000000, 0x001E2C0E, 0x00000000, 0x00030300, + 0x01010700, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x01000000, 0x00002807, 0x00000000, 0x32000300, + 0x00000000, 0x00000000, 0x04022004, 0x01040100, + 0x00010000, 0x00000100, 0x000000AA, 0x00000055, + 0x000000B5, 0x0000004A, 0x00000056, 0x000000A9, + 0x000000A9, 0x000000B5, 0x00000000, 0x01000000, + 0x00030300, 0x0000001A, 0x000007D0, 0x00000300, + 0x00000000, 0x00000000, 0x01000000, 0x00000101, + 0x00000000, 0x00000000, 0x00000000, 0x00000200, + 0x03030300, 0x01000000, 0x00000000, 0x00000100, + 0x00000003, 0x001100EF, 0x01A1120B, 0x00051400, + 0x001A0700, 0x001101FC, 0x00011A00, 0x00000000, + 0x001F0000, 0x00000000, 0x00000000, 0x00051500, + 0x001103FC, 0x00011A00, 0x00051500, 0x001102FC, + 0x00011A00, 0x00001A00, 0x00000000, 0x001F0000, + 0x001100FC, 0x00011A00, 0x01A1120B, 0x001A0701, + 0x00000000, 0x001F0000, 0x00000000, 0x00000000, + 0x001100EF, 0x01A1120B, 0x00051400, 0x01910480, + 0x01821009, 0x001F0000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x001A0700, 0x01A11E14, + 0x001101FC, 0x00211A00, 0x00051500, 0x001103FC, + 0x00011A00, 0x00051500, 0x001102FC, 0x00011A00, + 0x00031A00, 0x001A0701, 0x00000000, 0x001F0000, + 0x00000000, 0x00000000, 0x01A11E14, 0x01A1120B, + 0x00000000, 0x001F0000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x001100FD, 0x00012E00, + 0x00051700, 0x01A1120B, 0x001A0701, 0x001F0000, + 0x00000000, 0x00000000, 0x001100EF, 0x01A1120B, + 0x00051400, 0x001A0700, 0x001102FD, 0x00012E00, + 0x00000000, 0x001F0000, 0x00000000, 0x00000000, + 0x00070700, 0x00000000, 0x01000000, 0x00000300, + 0x17030000, 0x00000000, 0x00000000, 0x00000000, + 0x0A0A140A, 0x10020201, 0x332A0002, 0x01010000, + 0x0B000404, 0x04030308, 0x00010100, 0x02020301, + 0x01001000, 0x00000034, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x55AA55AA, 0x33CC33CC, + 0x0FF00FF0, 0x0F0FF0F0, 0x00008E38, 0x00000001, + 0x00000002, 0x00020001, 0x00020001, 0x02010201, + 0x0000000F, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xAAAAA593, + 0xA5939999, 0x00000000, 0x00005555, 0x00003333, + 0x0000CCCC, 0x00000000, 0x0003FFFF, 0x00003333, + 0x0000CCCC, 0x00000000, 0x036DB6DB, 0x00249249, + 0x05B6DB6D, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x036DB6DB, 0x00249249, + 0x05B6DB6D, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x01000000, 0x00000100, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00010000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00010000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00080000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x01180400, + 0x03020100, 0x00060504, 0x00010100, 0x00000008, + 0x00080000, 0x00000001, 0x00000000, 0x0001AA00, + 0x00000100, 0x00000000, 0x00010000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00020000, 0x00000100, 0x00010000, 0x0000000B, + 0x0000001C, 0x00000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x03010000, 0x01000100, + 0x01020001, 0x00010300, 0x05000104, 0x01060001, + 0x00010700, 0x00000000, 0x00000000, 0x00010000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000301, 0x00000000, 0x00000000, 0x01010000, + 0x00000000, 0x00000200, 0x00000000, 0xB8000000, + 0x010000FF, 0x0000FFE8, 0x00FFA801, 0xFFD80100, + 0x00007F10, 0x00000000, 0x00000034, 0x0000003D, + 0x00020079, 0x02000200, 0x02000204, 0x06000C06, + 0x04040200, 0x04100804, 0x14090004, 0x1C081024, + 0x0000120C, 0x00000015, 0x000000CF, 0x00000026, + 0x0000017F, 0x00000130, 0x04000C2E, 0x00000404, + 0x01080032, 0x01080032, 0x000F0032, 0x00000000, + 0x00000000, 0x00000000, 0x00010300, 0x00010301, + 0x03030000, 0x00000001, 0x00010303, 0x00030000, + 0x0013000C, 0x0A060037, 0x03030526, 0x000C0032, + 0x0017003D, 0x0025004B, 0x00010101, 0x0000000E, + 0x00000019, 0x010000C8, 0x000F000F, 0x0007000C, + 0x001A0100, 0x0015001A, 0x0100000B, 0x00C900C9, + 0x005100A1, 0x29003329, 0x33290033, 0x0A070600, + 0x0A07060D, 0x0D09070D, 0x000C000D, 0x00001000, + 0x00000C00, 0x00001000, 0x00000C00, 0x02001000, + 0x0002000E, 0x00160019, 0x1E1A00C8, 0x00100004, + 0x361C0008, 0x00000000, 0x0000000C, 0x0006000C, + 0x0300361C, 0x04001300, 0x000D0019, 0x0000361C, + 0x20003300, 0x00000000, 0x02000000, 0x04040802, + 0x00060404, 0x0003C34F, 0x05022001, 0x0203000A, + 0x04040408, 0xC34F0604, 0x10010005, 0x040A0502, + 0x0A080F11, 0x1C0A040A, 0x0022C34F, 0x0C0C1002, + 0x00019E0A, 0x0000102C, 0x000002FE, 0x00001DEC, + 0x0000185C, 0x0000F398, 0x04000400, 0x03030400, + 0x002AF803, 0x00002AF8, 0x0000D6D7, 0x00000003, + 0x0000006E, 0x00000016, 0x00004E20, 0x00004E20, + 0x00030D40, 0x00000005, 0x000000C8, 0x00000027, + 0x00027100, 0x00027100, 0x00186A00, 0x00000028, + 0x00000640, 0x01000136, 0x00530040, 0x00010004, + 0x00960040, 0x00010004, 0x04B00040, 0x00000318, + 0x00280005, 0x05040404, 0x00070603, 0x06030503, + 0x0503000D, 0x00640603, 0x06040608, 0x00040604, + 0x00260015, 0x01050130, 0x01000100, 0x00020201, + 0x04040000, 0x01010104, 0x03020302, 0x00000100, + 0x02020101, 0x00000000, 0x09910260, 0x11911600, + 0x19A21009, 0x19A10100, 0x19A10201, 0x19A10302, + 0x19A10A03, 0x19A10B04, 0x19A10C05, 0x19A10E07, + 0x19A10F08, 0x19A1110A, 0x19A1120B, 0x19A1130C, + 0x19A1140D, 0x19A00C00, 0x199F0000, 0x199F0000, + 0x199F0000, 0x199F0000, 0x01910300, 0x01A21009, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x001140BF, 0x01811009, 0x01850400, 0x01A10C05, + 0x01850300, 0x01A10C11, 0x01850300, 0x001100BF, + 0x01811009, 0x01850500, 0x019F0000, 0x019F0000, + 0x01510001, 0x01D102A0, 0x01E21009, 0x00051900, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x01510001, + 0x01D10290, 0x01E21009, 0x01510001, 0x01D10000, + 0x01E21009, 0x00051800, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x0011008F, 0x00910000, + 0x01811009, 0x01910040, 0x01A21009, 0x019F0000, + 0x01911000, 0x01A21009, 0x01A10100, 0x01A10201, + 0x01A10302, 0x01A10A03, 0x01A10B04, 0x01A10C05, + 0x01A10E07, 0x01A10F08, 0x01A1110A, 0x01A1120B, + 0x01A1130C, 0x01A1140D, 0x01A00C00, 0x01910800, + 0x01A21009, 0x019F0000, 0x019F0000, 0x019F0000, + 0x0101017F, 0x00010101, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x01000000, 0x01000101, + 0x00000000, 0x00000000, 0x00050000, 0x00070100, + 0x000F0200, 0x00000000, 0x01A10100, 0x01A10201, + 0x01A10302, 0x01A00B04, 0x00210D06, 0x01A1110A, + 0x01A1140D, 0x00098000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x019F0000, 0x019F0000, + 0x019F0000, 0x019F0000, 0x01A10100, 0x01A10201, + 0x01A10302, 0x01A10A03, 0x01A10B04, 0x00210D06, + 0x01A1110A, 0x00000000, 0x01A1140D, 0x00000000, + 0x00000000, 0x00000000, 0x01A1120B, 0x000A0000, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x000A0000, 0x01061300, + 0x00000000, 0x00000000, 0x00061180, 0x000612C0, + 0x00000000, 0x00000000, 0x001F0000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x01811009, 0x0011EFAF, + 0x01A1120B, 0x001F0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001100BF, + 0x01A1120B, 0x080D0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x080C0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x001F0200, 0x001F0200, + 0x001F0200, 0x001F0200, 0x001F0200, 0x001F0200, + 0x001F0200, 0x001F0200, 0x001F0200, 0x001F0200, + 0x001F0200, 0x001F0200, 0x001100EF, 0x01A1120B, + 0x001F0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x01A1120B, 0x001F0000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x001100EF, 0x01A1120B, + 0x001F0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00211F14, 0x00212014, + 0x00212116, 0x00212217, 0x001F0000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x001A85FF, 0x00051E00, 0x001F0000, 0x00000000, + 0x00211F14, 0x00212015, 0x00212116, 0x00212217, + 0x01A1120B, 0x001F0000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0031FFBF, 0x01A11009, + 0x01A10E07, 0x01A10F08, 0x003100BF, 0x01A11009, + 0x00051800, 0x003F0000, 0x003F0000, 0x003F0000, + 0x003F0000, 0x003F0000, 0x003F0000, 0x003F0000, + 0x003F0000, 0x003F0000, 0x0031FFBF, 0x01A11009, + 0x01A10E07, 0x01A10F08, 0x003100BF, 0x01A11009, + 0x00051800, 0x003F0000, 0x003F0000, 0x003F0000, + 0x003F0000, 0x003F0000, 0x003F0000, 0x003F0000, + 0x003F0000, 0x003F0000, 0x08084340, 0x0011FFFF, + 0x2011FFFB, 0x00012E00, 0x001100EF, 0x01A1120B, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x083E4340, 0x00212E00, + 0x01A1120B, 0x003F0000, 0x003F0000, 0x003F0000, + 0x003F0000, 0x003F0000, 0x003F0000, 0x08201020, + 0x28100020, 0x08083020, 0x08400020, 0x08402020, + 0x08483020, 0x10083020, 0x20180020, 0x30480020, + 0x78880020, 0x488010E0, 0x494B0000, 0x49089080, + 0x49080000, 0x490011C0, 0x0A000020, 0x08000020, + 0x08000020, 0x08000020, 0x08000020, 0x08000020, + 0x08000020, 0x08000020, 0x08000020, 0x08000020, + 0x08000020, 0x08000020, 0x08000020, 0x08000020, + 0x08000020, 0x08000020, 0x08000020, 0x08000020, + 0x08000020, 0x08000020, 0x08000020, 0x08000020, + 0x08000020, 0x08000020, 0x08000020, 0x08000020, + 0x08000020, 0x08000020, 0x08000020, 0x08000020, + 0x001100FF, 0x01810302, 0x001100DF, 0x00010D06, + 0x001100EF, 0x01A1120B, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001F0000, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001F0000, + 0x00010D06, 0x01810302, 0x0181160E, 0x001F0000, + 0x001F0000, 0x001F0000, 0x001F0000, 0x001F0000, + 0x081A52FD, 0x001A12FF, 0x00051A00, 0x001A13FF, + 0x00051B00, 0x001F13FF, 0x081A52FD, 0x001A12FF, + 0x00051A00, 0x001A13FF, 0x00051B00, 0x001F13FF, + 0x081A52FD, 0x001A12FF, 0x00051A00, 0x001A13FF, + 0x00051B00, 0x001F13FF, 0x00032300, 0x00032400, + 0x001F0000, 0x001F0000, 0x00800000, 0x0031FFBF, + 0x01A11009, 0x01A10E07, 0x01A10F08, 0x003100BF, + 0x01A11009, 0x00051800, 0x003F0000, 0x003F0000, + 0x003F0000, 0x003F0000, 0x003F0000, 0x003F0000, + 0x003F0000, 0x003F0000, 0x00800000, 0x0031FFBF, + 0x01A11009, 0x01A10E07, 0x01A10F08, 0x003100BF, + 0x01A11009, 0x00051800, 0x003F0000, 0x003F0000, + 0x003F0000, 0x003F0000, 0x003F0000, 0x003F0000, + 0x003F0000, 0x003F0000, 0x081100DF, 0x08010D06, + 0x0011000F, 0x0181160E, 0x001100EF, 0x01A1120B, + 0x001F0000, 0x001F0000, 0x001F0000, 0x009C0000, + 0x08010D06, 0x0181160E, 0x01A1120B, 0x001F0000, + 0x001F0000, 0x001F0000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11910048, + 0x09910060, 0x19A21009, 0x19A10100, 0x19A10201, + 0x19A10302, 0x19A10A03, 0x19A10B04, 0x18051C00, + 0x19A1110A, 0x19A1120B, 0x19A1130C, 0x19A1140D, + 0x19A1160E, 0x181140BF, 0x19A11009, 0x19A10C05, + 0x19A00C00, 0x19A10E07, 0x19A10F08, 0x19910280, + 0x19A21009, 0x18051000, 0x18861101, 0x181F0000, + 0x18000000, 0x18000000, 0x18000000, 0x18000000, + 0x18000000, 0x18000000, 0x18000000, 0x18000000, + 0x18000000, 0x18000000, 0x18000000, 0x18000000, + 0x18000000, 0x18000000, 0x18000000, 0x18861100, + 0x19A11009, 0x101B0001, 0x181B0100, 0x18000500, + 0x181B0200, 0x00000000, 0x181B0600, 0x181B0C00, + 0x181B0100, 0x181B0200, 0x181B0300, 0x181B0400, + 0x181F0000, 0x18000000, 0x18000000, 0x18000000, + 0x18000000, 0x18000000, 0x18000000, 0x18000000, + 0x18000000, 0x18000000, 0x18000000, 0x18000000, + 0x18000000, 0x18000000, 0x18000000, 0x18000000, + 0x18000000, 0x004B1040, 0x001011C0, 0x00089080, + 0x000811C0, 0x040811C0, 0x02000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x5F407FAA, + 0x007B776F, 0x4AB555AA, 0xB5A9A956, 0x9F80BFAA, + 0x00BBB7AF, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00002AF8, 0x0000D6D7, 0x0000006E, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x0000000E, 0x00000019, 0x000000C8, + 0x00000001, 0x00000001, 0x00000003, 0x00000007, + 0x00000007, 0x00000009, 0x00000001, 0x00000001, + 0x00000003, 0x00000001, 0x00000001, 0x00000003, + 0x0000006E, 0x000000C8, 0x00000640, 0x00000001, + 0x00000001, 0x00000003, 0x00000002, 0x00000004, + 0x0000001C, 0x00000007, 0x0000000B, 0x00000051, + 0x0000000C, 0x00000015, 0x000000A1, 0x00000003, + 0x00000000, 0x0000000C, 0x00000000, 0x00000000, + 0x00000000, 0x0000000F, 0x0000000F, 0x0000000F, + 0x00002AF9, 0x00002AF9, 0x00002AF9, 0x00000034, + 0x0000001E, 0x0000003C, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x000000C0, 0x00000000, 0x00000000, 0x55550000, + 0x00003C5A, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00D60000, + 0x50005000, 0x803E0050, 0x00000200, 0x00000000, + 0x00000000, 0x00007800, 0x00000000, 0x00000000, + 0x00000000, 0x00C61110, 0x2C002834, 0x0C06002C, + 0x00000200, 0x00000000, 0x00000000, 0x00007800, + 0x00000000, 0x00000000, 0x00000000, 0x00C6BBB0, + 0x2C002834, 0x0C06002C, 0x00000200, 0x00000000, + 0x00000000, 0x00007800, 0x00000000, 0x00000000, + 0x00000000, 0x00D60000, 0x50005000, 0x803E0050, + 0x00000200, 0x00000000, 0x00000000, 0x00007800, + 0x00000000, 0x00000000, 0x00000000, 0x00C61110, + 0x2C002834, 0x082E002C, 0x00000200, 0x00000000, + 0x00000000, 0x00007800, 0x00000000, 0x00000000, + 0x00000000, 0x00C6BBB0, 0x2C002834, 0x082E002C, + 0x00000200, 0x00000000, 0x00000000, 0x00007800, + 0x00000000, 0x00000000, 0x00000000, 0x80808080, + 0x800D8080, 0x80808080, 0x17808080, 0x80808025, + 0x2221201F, 0x80808080, 0x80808080, 0x80808080, + 0x80808080, 0x80808080, 0x80808080, 0x80808080, + 0x80808080, 0x80808080, 0x80808080, 0x80808080, + 0x80808080, 0x80808080, 0x80808080, 0x0A030201, + 0x0E800C0B, 0x1211100F, 0x80161413, 0x08004C80, + 0x8080801E, 0x80804E80, 0x80808080, 0x80808080, + 0x80808080 +}; + +struct dbsc5_table_patch { + const u32 reg; + const u32 val; +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_slice_3200[] = { + { PHY_REGULATOR_EN_CNT, 0x10 }, + { PHY_RX_CAL_ALL_DLY, 0x07 }, + { PHY_RDDATA_EN_TSEL_DLY, 0x08 }, + { PHY_RDDATA_EN_OE_DLY, 0x0B }, + { PHY_RPTR_UPDATE, 0x07 }, + { PHY_WRLVL_RESP_WAIT_CNT, 0x25 }, + { PHY_RDLVL_MAX_EDGE, 0x012D }, + { PHY_RDDATA_EN_DLY, 0x0B }, + { PHY_RDDQS_LATENCY_ADJUST, 0x04 }, + { PHY_RDDQS_GATE_SLAVE_DELAY, 0x05 }, + { PHY_GTLVL_LAT_ADJ_START, 0x03 }, + { PHY_LP4_BOOT_RX_PCLK_CLK_SEL, 0x00 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_v_3200[] = { + { PHY_ADR_MEAS_DLY_STEP_ENABLE, 0x00 }, + { PHY_ADR_CALVL_DLY_STEP, 0x02 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_pi_3200[] = { + { PI_TCKCKEL_F2, 0x03 }, + { PI_TDELAY_RDWR_2_BUS_IDLE_F2, 0x57 }, + { PI_TREF_F2, 0x613 }, + { PI_TDFI_WRLVL_WW_F0, 0x2B }, + { PI_TDFI_WRLVL_WW_F1, 0x2B }, + { PI_TDFI_WRLVL_WW_F2, 0x2B }, + { PI_RDLAT_ADJ_F2, 0x22 }, + { PI_TDFI_CALVL_CAPTURE_F2, 0x1D }, + { PI_TDFI_CALVL_CC_F2, 0x43 }, + { PI_TVRCG_ENABLE_F2, 0x51 }, + { PI_TVRCG_DISABLE_F2, 0x29 }, + { PI_TXP_F2, 0x07 }, + { PI_TMRWCKEL_F2, 0x0A }, + { PI_TDFI_CALVL_STROBE_F2, 0x06 }, + { PI_TFC_F2, 0x64 }, + { PI_TCKEHDQS_F2, 0x12 }, + { PI_TDFI_WDQLVL_RW_F2, 0x09 }, + { PI_TDFI_WDQLVL_WR_F2, 0x10 }, + { PI_MBIST_TWCKENL_RD_ADJ_F2, 0x10 }, + { PI_MBIST_RDLAT_ADJ_F2, 0x1E }, + { PI_TWTR_S_F2, 0x05 }, + { PI_TWTR_L_F2, 0x05 }, + { PI_TWTR_F2, 0x05 }, + { PI_TWR_F2, 0x0E }, + { PI_TDQSCK_MAX_F2, 0x01 }, + { PI_TDFI_CTRLUPD_MAX_F2, 0x0C26 }, + { PI_TDFI_CTRLUPD_INTERVAL_F2, 0x797C }, + { PI_TXSNR_F2, 0x9B }, + { PI_ZQRESET_F2, 0x0014 }, + { PI_TCBTRTW_F2, 0x04 }, + { PI_SEQ_WAIT_16_F2, 0x000064 }, + { PI_SEQ_WAIT_17_F2, 0x000002 }, + { PI_SEQ_WAIT_18_F2, 0x000007 }, + { PI_SEQ_WAIT_19_F2, 0x000002 }, + { PI_SEQ_WAIT_20_F2, 0x000002 }, + { PI_SEQ_WAIT_21_F2, 0x000320 }, + { PI_SEQ_WAIT_22_F2, 0x000002 }, + { PI_SEQ_WAIT_23_F2, 0x00000E }, + { PI_SEQ_WAIT_24_F2, 0x000029 }, + { PI_SEQ_WAIT_25_F2, 0x000051 }, + { PI_SEQ_WAIT_26_F2, 0x000003 }, + { PI_SEQ_WAIT_30_F2, 0x00002B }, + { PI_WRDCM_LVL_EN_F1, 0x00 }, + { PI_WRDCM_LVL_EN_F2, 0x00 }, + { PI_DRAMDCA_LVL_EN_F1, 0x00 }, + { PI_DRAMDCA_LVL_EN_F2, 0x00 }, + { PI_TINIT_F2, 0x013880 }, + { PI_TINIT1_F2, 0x013880 }, + { PI_TINIT3_F2, 0x0C3500 }, + { PI_TINIT4_F2, 0x000014 }, + { PI_TINIT5_F2, 0x000320 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_slice_3733[] = { + { PHY_REGULATOR_EN_CNT, 0x13 }, + { PHY_RX_CAL_ALL_DLY, 0x08 }, + { PHY_RDDATA_EN_TSEL_DLY, 0x0A }, + { PHY_RDDATA_EN_OE_DLY, 0x0D }, + { PHY_RPTR_UPDATE, 0x08 }, + { PHY_WRLVL_RESP_WAIT_CNT, 0x2A }, + { PHY_RDLVL_MAX_EDGE, 0x0149 }, + { PHY_RDDATA_EN_DLY, 0x0D }, + { PHY_RDDQS_LATENCY_ADJUST, 0x04 }, + { PHY_RDDQS_GATE_SLAVE_DELAY, 0x9C }, + { PHY_GTLVL_LAT_ADJ_START, 0x04 }, + { PHY_LP4_BOOT_RX_PCLK_CLK_SEL, 0x00 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_v_3733[] = { + { PHY_ADR_MEAS_DLY_STEP_ENABLE, 0x00 }, + { PHY_ADR_CALVL_DLY_STEP, 0x02 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_pi_3733[] = { + { PI_TCKCKEL_F2, 0x03 }, + { PI_TDELAY_RDWR_2_BUS_IDLE_F2, 0x5B }, + { PI_TREF_F2, 0x717 }, + { PI_TDFI_WRLVL_WW_F0, 0x2C }, + { PI_TDFI_WRLVL_WW_F1, 0x2C }, + { PI_TDFI_WRLVL_WW_F2, 0x2C }, + { PI_RDLAT_ADJ_F2, 0x24 }, + { PI_TDFI_CALVL_CAPTURE_F2, 0x1F }, + { PI_TDFI_CALVL_CC_F2, 0x45 }, + { PI_TVRCG_ENABLE_F2, 0x5F }, + { PI_TVRCG_DISABLE_F2, 0x30 }, + { PI_TXP_F2, 0x07 }, + { PI_TMRWCKEL_F2, 0x0A }, + { PI_TDFI_CALVL_STROBE_F2, 0x06 }, + { PI_TFC_F2, 0x75 }, + { PI_TCKEHDQS_F2, 0x13 }, + { PI_TDFI_WDQLVL_RW_F2, 0x09 }, + { PI_TDFI_WDQLVL_WR_F2, 0x12 }, + { PI_MBIST_TWCKENL_RD_ADJ_F2, 0x10 }, + { PI_MBIST_RDLAT_ADJ_F2, 0x20 }, + { PI_TWTR_S_F2, 0x06 }, + { PI_TWTR_L_F2, 0x06 }, + { PI_TWTR_F2, 0x06 }, + { PI_TWR_F2, 0x10 }, + { PI_TDFI_CTRLUPD_MAX_F2, 0x0E2E }, + { PI_TDFI_CTRLUPD_INTERVAL_F2, 0x8DCC }, + { PI_TXSNR_F2, 0xB5 }, + { PI_ZQRESET_F2, 0x0018 }, + { PI_TCBTRTW_F2, 0x05 }, + { PI_SEQ_WAIT_16_F2, 0x000075 }, + { PI_SEQ_WAIT_17_F2, 0x000002 }, + { PI_SEQ_WAIT_18_F2, 0x000007 }, + { PI_SEQ_WAIT_19_F2, 0x000002 }, + { PI_SEQ_WAIT_20_F2, 0x000002 }, + { PI_SEQ_WAIT_21_F2, 0x0003A6 }, + { PI_SEQ_WAIT_22_F2, 0x000002 }, + { PI_SEQ_WAIT_23_F2, 0x000011 }, + { PI_SEQ_WAIT_24_F2, 0x000030 }, + { PI_SEQ_WAIT_25_F2, 0x00005F }, + { PI_SEQ_WAIT_26_F2, 0x000005 }, + { PI_SEQ_WAIT_30_F2, 0x00002D }, + { PI_TINIT_F2, 0x016C90 }, + { PI_TINIT1_F2, 0x016C90 }, + { PI_TINIT3_F2, 0x0E3D98 }, + { PI_TINIT4_F2, 0x000018 }, + { PI_TINIT5_F2, 0x0003A6 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_slice_4266[] = { + { PHY_REGULATOR_EN_CNT, 0x16 }, + { PHY_RX_CAL_ALL_DLY, 0x09 }, + { PHY_RDDATA_EN_TSEL_DLY, 0x0B }, + { PHY_RDDATA_EN_OE_DLY, 0x0E }, + { PHY_RPTR_UPDATE, 0x08 }, + { PHY_WRLVL_RESP_WAIT_CNT, 0x2E }, + { PHY_RDLVL_MAX_EDGE, 0x0164 }, + { PHY_RDDATA_EN_DLY, 0x0E }, + { PHY_RDDQS_LATENCY_ADJUST, 0x05 }, + { PHY_RDDQS_GATE_SLAVE_DELAY, 0x30 }, + { PHY_GTLVL_LAT_ADJ_START, 0x04 }, + { PHY_LP4_BOOT_RX_PCLK_CLK_SEL, 0x00 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_v_4266[] = { + { PHY_ADR_MEAS_DLY_STEP_ENABLE, 0x00 }, + { PHY_ADR_CALVL_DLY_STEP, 0x02 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_pi_4266[] = { + { PI_TCKCKEL_F2, 0x03 }, + { PI_TDELAY_RDWR_2_BUS_IDLE_F2, 0x64 }, + { PI_TREF_F2, 0x81C }, + { PI_TDFI_WRLVL_WW_F0, 0x2D }, + { PI_TDFI_WRLVL_WW_F1, 0x2D }, + { PI_TDFI_WRLVL_WW_F2, 0x2D }, + { PI_RDLAT_ADJ_F2, 0x2B }, + { PI_TDFI_CALVL_CAPTURE_F2, 0x20 }, + { PI_TDFI_CALVL_CC_F2, 0x46 }, + { PI_TVRCG_ENABLE_F2, 0x6C }, + { PI_TVRCG_DISABLE_F2, 0x37 }, + { PI_TXP_F2, 0x07 }, + { PI_TMRWCKEL_F2, 0x0A }, + { PI_TFC_F2, 0x86 }, + { PI_TCKEHDQS_F2, 0x14 }, + { PI_TDFI_WDQLVL_RW_F2, 0x0B }, + { PI_TDFI_WDQLVL_WR_F2, 0x13 }, + { PI_MBIST_TWCKENL_RD_ADJ_F2, 0x14 }, + { PI_MBIST_RDLAT_ADJ_F2, 0x27 }, + { PI_TWTR_S_F2, 0x07 }, + { PI_TWTR_L_F2, 0x07 }, + { PI_TWTR_F2, 0x07 }, + { PI_TWR_F2, 0x13 }, + { PI_TDFI_CTRLUPD_MAX_F2, 0x1038 }, + { PI_TDFI_CTRLUPD_INTERVAL_F2, 0xA230 }, + { PI_TXSNR_F2, 0xCF }, + { PI_ZQRESET_F2, 0x001B }, + { PI_TCBTRTW_F2, 0x06 }, + { PI_SEQ_WAIT_16_F2, 0x000086 }, + { PI_SEQ_WAIT_17_F2, 0x000002 }, + { PI_SEQ_WAIT_18_F2, 0x000007 }, + { PI_SEQ_WAIT_19_F2, 0x000002 }, + { PI_SEQ_WAIT_20_F2, 0x000002 }, + { PI_SEQ_WAIT_21_F2, 0x00042B }, + { PI_SEQ_WAIT_22_F2, 0x000002 }, + { PI_SEQ_WAIT_23_F2, 0x000013 }, + { PI_SEQ_WAIT_24_F2, 0x000037 }, + { PI_SEQ_WAIT_25_F2, 0x00006C }, + { PI_SEQ_WAIT_26_F2, 0x000006 }, + { PI_SEQ_WAIT_30_F2, 0x000032 }, + { PI_TINIT_F2, 0x01A0AB }, + { PI_TINIT1_F2, 0x01A0AB }, + { PI_TINIT3_F2, 0x1046AB }, + { PI_TINIT4_F2, 0x00001B }, + { PI_TINIT5_F2, 0x00042B } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_slice_4800[] = { + { PHY_REGULATOR_EN_CNT, 0x18 }, + { PHY_RX_CAL_ALL_DLY, 0x0A }, + { PHY_RDDATA_EN_TSEL_DLY, 0x0D }, + { PHY_RDDATA_EN_OE_DLY, 0x10 }, + { PHY_RPTR_UPDATE, 0x08 }, + { PHY_WRLVL_RESP_WAIT_CNT, 0x31 }, + { PHY_RDLVL_MAX_EDGE, 0x017F }, + { PHY_RDDATA_EN_DLY, 0x10 }, + { PHY_RDDQS_LATENCY_ADJUST, 0x05 }, + { PHY_RDDQS_GATE_SLAVE_DELAY, 0xC6 }, + { PHY_GTLVL_LAT_ADJ_START, 0x05 }, + { PHY_LP4_BOOT_RX_PCLK_CLK_SEL, 0x00 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_v_4800[] = { + { PHY_ADR_MEAS_DLY_STEP_ENABLE, 0x00 }, + { PHY_ADR_CALVL_DLY_STEP, 0x02 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_pi_4800[] = { + { PI_TCKCKEL_F2, 0x03 }, + { PI_TDELAY_RDWR_2_BUS_IDLE_F2, 0x68 }, + { PI_RDLAT_ADJ_F2, 0x2D }, + { PI_TREF_F2, 0x920 }, + { PI_TDFI_WRLVL_WW_F0, 0x2E }, + { PI_TDFI_WRLVL_WW_F1, 0x2E }, + { PI_TDFI_WRLVL_WW_F2, 0x2E }, + { PI_TDFI_CALVL_CAPTURE_F2, 0x21 }, + { PI_TDFI_CALVL_CC_F2, 0x47 }, + { PI_TVRCG_DISABLE_F2, 0x3D }, + { PI_TVRCG_ENABLE_F2, 0x79 }, + { PI_TXP_F2, 0x08 }, + { PI_TMRWCKEL_F2, 0x0A }, + { PI_TCKEHDQS_F2, 0x14 }, + { PI_TFC_F2, 0x96 }, + { PI_TDFI_WDQLVL_RW_F2, 0x0B }, + { PI_TDFI_WDQLVL_WR_F2, 0x15 }, + { PI_MBIST_TWCKENL_RD_ADJ_F2, 0x18 }, + { PI_MBIST_RDLAT_ADJ_F2, 0x29 }, + { PI_TWTR_S_F2, 0x08 }, + { PI_TWR_F2, 0x15 }, + { PI_TWTR_F2, 0x08 }, + { PI_TWTR_L_F2, 0x08 }, + { PI_TDFI_CTRLUPD_MAX_F2, 0x1240 }, + { PI_TDFI_CTRLUPD_INTERVAL_F2, 0xB680 }, + { PI_TXSNR_F2, 0x0E9 }, + { PI_ZQRESET_F2, 0x001E }, + { PI_TCBTRTW_F2, 0x06 }, + { PI_SEQ_WAIT_16_F2, 0x000096 }, + { PI_SEQ_WAIT_17_F2, 0x000002 }, + { PI_SEQ_WAIT_18_F2, 0x000008 }, + { PI_SEQ_WAIT_19_F2, 0x000002 }, + { PI_SEQ_WAIT_20_F2, 0x000002 }, + { PI_SEQ_WAIT_21_F2, 0x0004B0 }, + { PI_SEQ_WAIT_22_F2, 0x000002 }, + { PI_SEQ_WAIT_23_F2, 0x000015 }, + { PI_SEQ_WAIT_24_F2, 0x00003D }, + { PI_SEQ_WAIT_25_F2, 0x000079 }, + { PI_SEQ_WAIT_26_F2, 0x000008 }, + { PI_SEQ_WAIT_30_F2, 0x000034 }, + { PI_TINIT_F2, 0x01D4A9 }, + { PI_TINIT1_F2, 0x01D4A9 }, + { PI_TINIT3_F2, 0x124E91 }, + { PI_TINIT4_F2, 0x00001E }, + { PI_TINIT5_F2, 0x0004B0 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_slice_5500[] = { + { PHY_REGULATOR_EN_CNT, 0x1C }, + { PHY_RX_CAL_ALL_DLY, 0x0C }, + { PHY_RDDATA_EN_TSEL_DLY, 0x10 }, + { PHY_RDDATA_EN_OE_DLY, 0x13 }, + { PHY_WRLVL_RESP_WAIT_CNT, 0x37 }, + { PHY_RDLVL_MAX_EDGE, 0x01A3 }, + { PHY_RDDATA_EN_DLY, 0x13 }, + { PHY_RDDQS_LATENCY_ADJUST, 0x06 }, + { PHY_RDDQS_GATE_SLAVE_DELAY, 0x8F }, + { PHY_GTLVL_LAT_ADJ_START, 0x06 }, + { PHY_LP4_BOOT_RX_PCLK_CLK_SEL, 0x00 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_v_5500[] = { + { PHY_ADR_MEAS_DLY_STEP_ENABLE, 0x00 }, + { PHY_ADR_CALVL_DLY_STEP, 0x02 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_pi_5500[] = { + { PI_TDELAY_RDWR_2_BUS_IDLE_F2, 0x71 }, + { PI_RDLAT_ADJ_F2, 0x32 }, + { PI_TREF_F2, 0xA79 }, + { PI_TDFI_WRLVL_WW_F0, 0x30 }, + { PI_TDFI_WRLVL_WW_F1, 0x30 }, + { PI_TDFI_WRLVL_WW_F2, 0x30 }, + { PI_TDFI_CALVL_CAPTURE_F2, 0x23 }, + { PI_TDFI_CALVL_CC_F2, 0x49 }, + { PI_TVRCG_DISABLE_F2, 0x46 }, + { PI_TVRCG_ENABLE_F2, 0x8B }, + { PI_TMRWCKEL_F2, 0x0B }, + { PI_TCKEHDQS_F2, 0x15 }, + { PI_TFC_F2, 0xAD }, + { PI_TDFI_WDQLVL_RW_F2, 0x0C }, + { PI_TDFI_WDQLVL_WR_F2, 0x17 }, + { PI_MBIST_TWCKENL_RD_ADJ_F2, 0x1C }, + { PI_MBIST_RDLAT_ADJ_F2, 0x2E }, + { PI_TWTR_S_F2, 0x09 }, + { PI_TWR_F2, 0x18 }, + { PI_TWTR_F2, 0x09 }, + { PI_TWTR_L_F2, 0x09 }, + { PI_TDFI_CTRLUPD_MAX_F2, 0x14F2 }, + { PI_TDFI_CTRLUPD_INTERVAL_F2, 0xD174 }, + { PI_TXSNR_F2, 0x10B }, + { PI_ZQRESET_F2, 0x0023 }, + { PI_TCBTRTW_F2, 0x07 }, + { PI_SEQ_WAIT_16_F2, 0x0000AD }, + { PI_SEQ_WAIT_21_F2, 0x000561 }, + { PI_SEQ_WAIT_23_F2, 0x000019 }, + { PI_SEQ_WAIT_24_F2, 0x000046 }, + { PI_SEQ_WAIT_25_F2, 0x00008B }, + { PI_SEQ_WAIT_26_F2, 0x00000A }, + { PI_SEQ_WAIT_30_F2, 0x000038 }, + { PI_TINIT_F2, 0x0219AF }, + { PI_TINIT1_F2, 0x0219AF }, + { PI_TINIT3_F2, 0x1500CF }, + { PI_TINIT4_F2, 0x000023 }, + { PI_TINIT5_F2, 0x000561 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_slice_6000[] = { + { PHY_REGULATOR_EN_CNT, 0x1F }, + { PHY_RDDATA_EN_TSEL_DLY, 0x12 }, + { PHY_RDDATA_EN_OE_DLY, 0x15 }, + { PHY_WRLVL_RESP_WAIT_CNT, 0x3A }, + { PHY_RDLVL_MAX_EDGE, 0x01BD }, + { PHY_RDDATA_EN_DLY, 0x15 }, + { PHY_RDDQS_LATENCY_ADJUST, 0x07 }, + { PHY_RDDQS_GATE_SLAVE_DELAY, 0x1B }, + { PHY_GTLVL_LAT_ADJ_START, 0x06 }, + { PHY_LP4_BOOT_RX_PCLK_CLK_SEL, 0x00 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_v_6000[] = { + { PHY_ADR_MEAS_DLY_STEP_ENABLE, 0x00 }, + { PHY_ADR_CALVL_DLY_STEP, 0x02 } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_pi_6000[] = { + { PI_TDELAY_RDWR_2_BUS_IDLE_F2, 0x75 }, + { PI_RDLAT_ADJ_F2, 0x34 }, + { PI_TREF_F2, 0xB6B }, + { PI_TDFI_WRLVL_WW_F0, 0x31 }, + { PI_TDFI_WRLVL_WW_F1, 0x31 }, + { PI_TDFI_WRLVL_WW_F2, 0x31 }, + { PI_TVRCG_DISABLE_F2, 0x4D }, + { PI_TVRCG_ENABLE_F2, 0x98 }, + { PI_TMRWCKEL_F2, 0x0C }, + { PI_TFC_F2, 0xBC }, + { PI_TDFI_WDQLVL_RW_F2, 0x0C }, + { PI_MBIST_TWCKENL_RD_ADJ_F2, 0x1C }, + { PI_MBIST_RDLAT_ADJ_F2, 0x30 }, + { PI_TWR_F2, 0x1A }, + { PI_TDFI_CTRLUPD_MAX_F2, 0x16D6 }, + { PI_TDFI_CTRLUPD_INTERVAL_F2, 0xE45C }, + { PI_TXSNR_F2, 0x123 }, + { PI_ZQRESET_F2, 0x0026 }, + { PI_SEQ_WAIT_16_F2, 0x0000BC }, + { PI_SEQ_WAIT_21_F2, 0x0005DD }, + { PI_SEQ_WAIT_23_F2, 0x00001B }, + { PI_SEQ_WAIT_24_F2, 0x00004D }, + { PI_SEQ_WAIT_25_F2, 0x000098 }, + { PI_SEQ_WAIT_30_F2, 0x00003A }, + { PI_TINIT_F2, 0x024A16 }, + { PI_TINIT1_F2, 0x024A16 }, + { PI_TINIT3_F2, 0x16E4D8 }, + { PI_TINIT4_F2, 0x000026 }, + { PI_TINIT5_F2, 0x0005DD } +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_slice_mbpsdiv_640 = { + PHY_DATA_DC_CAL_CLK_SEL, 0x05 +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_v_mbpsdiv_640 = { + PHY_CLK_DC_CAL_CLK_SEL, 0x04 +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_g_mbpsdiv_640 = { + PHY_CAL_CLK_SELECT_0, 0x05 +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_slice_mbpsdiv_572 = { + PHY_RX_PCLK_CLK_SEL, 0x3 +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_g_mbpsdiv_572 = { + PHY_PAD_ACS_RX_PCLK_CLK_SEL, 0x03 +}; + +static const struct dbsc5_table_patch dbsc5_table_patch_adr_g_mbpsdiv_400[] = { + { PHY_PLL_CTRL, 0x1542 }, + { PHY_PLL_CTRL_8X, 0x3342 } +}; + +/* Array of addresses for setting PI_DARRAY3_0 in each CS and frequency-set */ +static const u32 PI_DARRAY3_0_CSx_Fx[CS_CNT][3] = { + { PI_DARRAY3_0_CS0_F0, PI_DARRAY3_0_CS0_F1, PI_DARRAY3_0_CS0_F2 }, + { PI_DARRAY3_0_CS1_F0, PI_DARRAY3_0_CS1_F1, PI_DARRAY3_0_CS1_F2 } +}; + +/* Array of addresses for setting PI_DARRAY3_1 in each CS and frequency-set */ +static const u32 PI_DARRAY3_1_CSx_Fx[CS_CNT][3] = { + { PI_DARRAY3_1_CS0_F0, PI_DARRAY3_1_CS0_F1, PI_DARRAY3_1_CS0_F2 }, + { PI_DARRAY3_1_CS1_F0, PI_DARRAY3_1_CS1_F1, PI_DARRAY3_1_CS1_F2 } +}; + +/* DBSC registers */ +#define DBSC_DBSYSCONF0 0x0 +#define DBSC_DBSYSCONF1 0x0 +#define DBSC_DBSYSCONF1A 0x4 +#define DBSC_DBSYSCONF2 0x4 +#define DBSC_DBPHYCONF0 0x8 +#define DBSC_DBSYSCONF2A 0x8 +#define DBSC_DBMEMKIND 0x20 +#define DBSC_DBMEMKINDA 0x20 +#define DBSC_DBMEMCONF(ch, cs) (0x30 + (0x2000 * ((ch) & 0x2)) + (0x10 * ((ch) & 0x1)) + (0x4 * (cs))) +#define DBSC_DBMEMCONFA(ch, cs) (0x30 + (0x4000 * ((ch) & 0x2)) + (0x10 * ((ch) & 0x1)) + (0x4 * (cs))) +#define DBSC_DBSYSCNT0 0x100 +#define DBSC_DBSYSCNT0A 0x100 +#define DBSC_DBACEN 0x200 +#define DBSC_DBRFEN 0x204 +#define DBSC_DBCMD 0x208 +#define DBSC_DBWAIT 0x210 +#define DBSC_DBBL 0x400 +#define DBSC_DBBLA 0x400 +#define DBSC_DBRFCNF1 0x414 +#define DBSC_DBRFCNF2 0x418 +#define DBSC_DBCALCNF 0x424 +#define DBSC_DBDBICNT 0x518 +#define DBSC_DBDFIPMSTRCNF 0x520 +#define DBSC_DBDFICUPDCNF 0x540 +#define DBSC_DBBCAMDIS 0x9FC +#define DBSC_DBSCHRW1 0x1024 +#define DBSC_DBSCHTR0 0x1030 +#define DBSC_DBTR(x) (0x300 + (0x4 * (x))) +#define DBSC_DBRNK(x) (0x430 + (0x4 * (x))) +#define DBSC_DBDFISTAT(ch) (0x600 + (0x2000 * ((ch) & 0x2)) + (0x40 * ((ch) & 0x1))) +#define DBSC_DBDFICNT(ch) (0x604 + (0x2000 * ((ch) & 0x2)) + (0x40 * ((ch) & 0x1))) +#define DBSC_DBPDCNT2(ch) (0x618 + (0x2000 * ((ch) & 0x2)) + (0x40 * ((ch) & 0x1))) +#define DBSC_DBPDLK(ch) (0x620 + (0x2000 * ((ch) & 0x2)) + (0x40 * ((ch) & 0x1))) +#define DBSC_DBPDRGA(ch) (0x624 + (0x2000 * ((ch) & 0x2)) + (0x40 * ((ch) & 0x1))) +#define DBSC_DBPDRGD(ch) (0x628 + (0x2000 * ((ch) & 0x2)) + (0x40 * ((ch) & 0x1))) +#define DBSC_DBPDRGM(ch) (0x62C + (0x2000 * ((ch) & 0x2)) + (0x40 * ((ch) & 0x1))) +#define DBSC_DBPDSTAT0(ch) (0x630 + (0x2000 * ((ch) & 0x2)) + (0x40 * ((ch) & 0x1))) +#define DBSC_DBPDSTAT1(ch) (0x634 + (0x2000 * ((ch) & 0x2)) + (0x40 * ((ch) & 0x1))) +#define DBSC_DBSCHFCTST0 0x1040 +#define DBSC_DBSCHFCTST1 0x1044 + +/* CPG PLL3 registers */ +#define CPG_CPGWPR 0x0 +#define CPG_FRQCRD0 0x80C +#define CPG_PLLECR 0x820 +#define CPG_PLL3CR0 0x83C +#define CPG_PLL3CR1 0x8C0 +#define CPG_FSRCHKCLRR4 0x590 +#define CPG_FSRCHKSETR4 0x510 +#define CPG_FSRCHKRA4 0x410 +#define CPG_SRCR4 0x2C10 +#define CPG_SRSTCLR4 0x2C90 + +#define CPG_FRQCRD_KICK_BIT BIT(31) +#define CPG_PLL3CR0_KICK_BIT BIT(31) +#define CPG_PLLECR_PLL3ST_BIT BIT(11) + +#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; + + /* The board parameter structure of the board */ + const struct renesas_dbsc5_board_config *dbsc5_board_config; + + /* The board clock frequency */ + u32 brd_clk; + u32 brd_clkdiv; + u32 brd_clkdiva; + + /* The Mbps of Bus */ + u32 bus_clk; + u32 bus_clkdiv; + + /* The Mbps of DDR */ + u32 ddr_mbps; + u32 ddr_mbpsdiv; + + /* DDR memory multiplier setting value */ + u32 ddr_mul; + u32 ddr_mul_nf; + u32 ddr_mul_low; + u32 ddr_mul_reg; + + /* Value indicating the enabled channel */ + u32 ddr_phyvalid; + + /* The tccd value of DDR */ + u32 ddr_tccd; + + /* Memory capacity in each channel and each CS */ + u8 ddr_density[DRAM_CH_CNT][CS_CNT]; + /* Channels used for each memory rank */ + u32 ch_have_this_cs[CS_CNT]; + /* The maximum memory capacity */ + u32 max_density; + + /* Index of jedec spec1 setting table you use */ + u32 js1_ind; + /* Array of jedec spec2 setting table */ + u32 js2[JS2_CNT]; + /* Read latency */ + u32 RL; + /* Write latency */ + u32 WL; + + /* Array for DDR PI Slice settings */ + u32 DDR_PI_REGSET[DDR_PI_REGSET_NUM_V4H]; + /* Array for DDRPHY Slice settings */ + u32 DDR_PHY_SLICE_REGSET[DDR_PHY_SLICE_REGSET_NUM_V4H]; + /* Array for DDRPHY ADRRESS VALUE Slice settings */ + u32 DDR_PHY_ADR_V_REGSET[DDR_PHY_SLICE_REGSET_NUM_V4H]; + /* Array for DDRPHY ADRRESS CONTROL Slice settings */ + u32 DDR_PHY_ADR_G_REGSET[DDR_PHY_SLICE_REGSET_NUM_V4H]; +}; + +static const struct renesas_dbsc5_board_config renesas_v4h_dbsc5_board_config = { + /* RENESAS V4H White Hawk (64Gbit 1rank) */ + .bdcfg_phyvalid = 0xF, + .bdcfg_vref_r = 0x0, + .bdcfg_vref_w = 0x0, + .bdcfg_vref_ca = 0x0, + .bdcfg_rfm_chk = true, + .ch = { + [0] = { + .bdcfg_ddr_density = { 0x06, 0xFF }, + .bdcfg_ca_swap = 0x04506132, + .bdcfg_dqs_swap = 0x01, + .bdcfg_dq_swap = { 0x26147085, 0x12306845 }, + .bdcfg_dm_swap = { 0x03, 0x07 }, + .bdcfg_cs_swap = 0x10 + }, + [1] = { + .bdcfg_ddr_density = { 0x06, 0xFF }, + .bdcfg_ca_swap = 0x02341065, + .bdcfg_dqs_swap = 0x10, + .bdcfg_dq_swap = { 0x56782314, 0x71048365 }, + .bdcfg_dm_swap = { 0x00, 0x02 }, + .bdcfg_cs_swap = 0x10 + }, + [2] = { + .bdcfg_ddr_density = { 0x06, 0xFF }, + .bdcfg_ca_swap = 0x02150643, + .bdcfg_dqs_swap = 0x10, + .bdcfg_dq_swap = { 0x58264071, 0x41207536 }, + .bdcfg_dm_swap = { 0x03, 0x08 }, + .bdcfg_cs_swap = 0x10 + }, + [3] = { + .bdcfg_ddr_density = { 0x06, 0xFF }, + .bdcfg_ca_swap = 0x01546230, + .bdcfg_dqs_swap = 0x01, + .bdcfg_dq_swap = { 0x45761328, 0x62801745 }, + .bdcfg_dm_swap = { 0x00, 0x03 }, + .bdcfg_cs_swap = 0x10 + } + } +}; + +/** + * r_vch_nxt() - Macro for channel selection loop + * + * Return the ID of the channel to be used. Check for valid channels + * between the value of posn and the maximum number of CHs. If a valid + * channel is found, returns the value of that channel. + */ +static u32 r_vch_nxt(struct udevice *dev, u32 pos) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + int posn; + + for (posn = pos; posn < DRAM_CH_CNT; posn++) + if (priv->ddr_phyvalid & BIT(posn)) + break; + + return posn; +} + +/* Select only valid channels in all channels from CH0. */ +#define r_foreach_vch(dev, ch) \ +for ((ch) = r_vch_nxt((dev), 0); (ch) < DRAM_CH_CNT; (ch) = r_vch_nxt((dev), (ch) + 1)) + +/* All channels are selected. */ +#define r_foreach_ech(ch) \ +for (ch = 0; ch < DRAM_CH_CNT; ch++) + +/** + * dbsc5_clk_cpg_write_32() - Write clock control register + * + * Write the complement value of setting value to the CPG_CPGWPR register + * for releaseing the protect. Write setting value to destination address. + */ +static void dbsc5_clk_cpg_write_32(struct udevice *dev, void __iomem *a, u32 v) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + + writel(~v, priv->cpg_regs + CPG_CPGWPR); + writel(v, a); +} + +enum dbsc5_clk_pll3_mode { + PLL3_LOW_FREQUENCY_MODE = 0, + PLL3_HIGH_FREQUENCY_MODE, + PLL3_HIGH_FREQUENCY_MODE_LOAD_REGISTER +}; + +/** + * dbsc5_clk_pll3_control() - Set PLL3 + * @dev: DBSC5 device + * @mode: PLL3 frequency mode + * + * Determine the set value according to the frequency mode of the argument. + * Write the set value to CPG_FRQCRD0 register and CPG_FRQCRD0 one. + * Reflect settings + */ +static void dbsc5_clk_pll3_control(struct udevice *dev, u32 mode) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + u32 data_div, data_mul, data_nf, ssmode, val; + int ret; + + /* + * PLL3VCO = EXTAL * priv->ddr_mul * 1/2 + * clk_ctlr_sync = PLL3VCO * pll3_div + * priv->ddr_mul = (NI[7:0] + 1) * 2 + NF[24:0] / 2^24 + */ + + switch (mode) { + case PLL3_LOW_FREQUENCY_MODE: + /* Low frequency mode (50MHz) */ + data_mul = (priv->ddr_mul_low / 2) - 1; /* PLL3VCO = 1600MHz */ + data_div = 0x9; /* div = 32 */ + data_nf = 0x0; + ssmode = 0x0; + break; + case PLL3_HIGH_FREQUENCY_MODE: + /* High frequency mode */ + data_mul = (priv->ddr_mul / 2) - 1; + data_div = 0x0; /* div = 2 */ + data_nf = priv->ddr_mul_nf; + ssmode = 0x4; + break; + case PLL3_HIGH_FREQUENCY_MODE_LOAD_REGISTER: + /* High frequency mode for loading to DDRPHY registers */ + data_mul = (priv->ddr_mul_reg / 2) - 1; + data_div = 0x0; /* div = 2 */ + data_nf = 0x0; + ssmode = 0x4; + break; + default: + printf("%s Mode %d not supported\n", __func__, mode); + hang(); + } + + data_mul = (data_mul << 20) | (ssmode << 16); + data_nf = data_nf << 21; + + if (((readl(priv->cpg_regs + CPG_PLL3CR0) & 0x3FFFFF7F) != data_mul) || + (readl(priv->cpg_regs + CPG_PLL3CR1) != data_nf)) { + /* PLL3CR0 multiplie set */ + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_PLL3CR0, data_mul); + /* PLL3CR1 multiplie set */ + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_PLL3CR1, data_nf); + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_PLL3CR0, + readl(priv->cpg_regs + CPG_PLL3CR0) | + CPG_PLL3CR0_KICK_BIT); + + ret = readl_poll_timeout(priv->cpg_regs + CPG_PLLECR, val, + (val & CPG_PLLECR_PLL3ST_BIT), + 1000000); + if (ret < 0) { + printf("%s CPG_PLLECR bit CPG_PLLECR_PLL3ST_BIT timeout\n", __func__); + hang(); + } + } + + /* PLL3 DIV set(Target value) */ + ret = readl_poll_timeout(priv->cpg_regs + CPG_FRQCRD0, val, + ((val & CPG_FRQCRD_KICK_BIT) == 0), + 1000000); + if (ret < 0) { + printf("%s CPG_FRQCRD0 bit CPG_FRQCRD_KICK_BIT div set timeout\n", __func__); + hang(); + } + + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_FRQCRD0, + (readl(priv->cpg_regs + CPG_FRQCRD0) & 0xFFFFFFF0) | + data_div); + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_FRQCRD0, + readl(priv->cpg_regs + CPG_FRQCRD0) | + CPG_FRQCRD_KICK_BIT); + ret = readl_poll_timeout(priv->cpg_regs + CPG_FRQCRD0, val, + ((val & CPG_FRQCRD_KICK_BIT) == 0), + 1000000); + if (ret < 0) { + printf("%s CPG_FRQCRD0 bit CPG_FRQCRD_KICK_BIT timeout\n", __func__); + hang(); + } +} + +/** + * dbsc5_clk_wait_freqchgreq() - Training handshake functions + * + * Check the value of the argument req_assert. If req_assert is 1, wait until + * FREQCHGREQ of all channels is 1 before time expires. If req_assert is 0, + * wait until FREQCHGREQ of all channels is 0 before time expires. Return the + * result of whether time has expired or not as a return value. + */ +static u32 dbsc5_clk_wait_freqchgreq(struct udevice *dev, u32 req_assert) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; + u32 count = 0xFFFFFF; + u32 ch, reg; + + do { + reg = !!req_assert; + r_foreach_vch(dev, ch) + reg &= readl(regs_dbsc_d + DBSC_DBPDSTAT0(ch)); + count = count - 1; + } while (((reg & 0x1) != !!req_assert) && (count != 0)); + + return count == 0x0; +} + +/** + * dbsc5_clk_set_freqchgack() - Training handshake functions + * @dev: DBSC5 device + * @ack_assert: Select DBSC_DBPDCNT2 content + * + * Check the value of the argument ackassert. If the value of ackassert + * is greater than or equal to 0, write 0xCF01 to DBSC_DBPDCNT2. + * If the value of ackassert is 0, write 0x0 to DBSC_DBPDCNT2. + */ +static void dbsc5_clk_set_freqchgack(struct udevice *dev, u32 ack_assert) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; + const u32 reg = ack_assert ? 0xcf01 : 0x0; + u32 ch; + + r_foreach_vch(dev, ch) + writel(reg, regs_dbsc_d + DBSC_DBPDCNT2(ch)); +} + +/** + * dbsc5_clk_wait_dbpdstat1() - Wait for status register update + * @dev: DBSC5 device + * @status: Expected status + * + * Read value the DBSC_DBPDSTAT1(ch) register. Wait until the contents + * of the status register are the same as status. + */ +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; + + for (i = 0; i < 2; i++) { + do { + reg = status; + r_foreach_vch(dev, ch) + reg &= readl(regs_dbsc_d + DBSC_DBPDSTAT1(ch)); + } while (reg != status); + } +} + +/** + * dbsc5_clk_pll3_freq() - Set up the pll3 frequency + * @dev: DBSC5 device + * + * Wait for frequency change request. DBSC_DBPDSTAT0 value determines whether + * dbsc5_clk_pll3_control is called in low frequency mode or high frequency + * mode. Call dbsc5_clk_set_freqchgack(1) function. Check update completion until + * timeout. Call dbsc5_clk_set_freqchgack(0) function. If timed out, return with + * error log Wait for status register update. + */ +static int dbsc5_clk_pll3_freq(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; + u32 fsel, timeout; + + dbsc5_clk_wait_freqchgreq(dev, 1); + + fsel = (readl(regs_dbsc_d + DBSC_DBPDSTAT0(0)) & 0x300) >> 8; + dbsc5_clk_pll3_control(dev, fsel ? PLL3_HIGH_FREQUENCY_MODE : + PLL3_LOW_FREQUENCY_MODE); + + dbsc5_clk_set_freqchgack(dev, 1); + timeout = dbsc5_clk_wait_freqchgreq(dev, 0); + dbsc5_clk_set_freqchgack(dev, 0); + + if (timeout) { + printf("Time out\n"); + return -ETIMEDOUT; + } + + dbsc5_clk_wait_dbpdstat1(dev, 0x7); + + return 0; +} + +/** + * dbsc5_reg_write() - Write DBSC register + * @addr: Destination address + * @data: Setting value to be written + * + * Write 32bit value @data to register at @addr . + */ +static void dbsc5_reg_write(void __iomem *addr, u32 data) +{ + writel(data, addr); + + if (((uintptr_t)addr & 0x000A0000) == 0x000A0000) + writel(data, addr + 0x4000); + else + writel(data, addr + 0x8000); +} + +/** + * dbsc5_reg_write() - DRAM Command Write Access + * @dev: DBSC5 device + * @cmd DRAM command. + * + * First, execute the dummy read to DBSC_DBCMD. + * Confirm that no DBSC command operation is in progress 0. + * Write the contents of the command to be sent to DRAM. + */ +static void dbsc5_send_dbcmd2(struct udevice *dev, u32 cmd) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; + u32 val; + int ret; + + /* dummy read */ + readl(regs_dbsc_d + DBSC_DBCMD); + + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBWAIT, val, ((val & BIT(0)) == 0), 1000000); + if (ret < 0) { + printf("%s DBWAIT bit 0 timeout\n", __func__); + hang(); + } + + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBWAIT + 0x4000, val, ((val & BIT(0)) == 0), 1000000); + if (ret < 0) { + printf("%s DBWAIT + 0x4000 bit 0 timeout\n", __func__); + hang(); + } + + dbsc5_reg_write(regs_dbsc_d + DBSC_DBCMD, cmd); +} + +/** + * dbsc5_reg_ddrphy_read() - Read setting from DDR PHY register + * @dev: DBSC5 device + * @ch: Target channel + * @regadd: Destination address + * + * Write matching values to DBPDRGA register and read value out of DBSC_DBPDRGD. + * Wait until the write process completed in each step. + */ +static u32 dbsc5_reg_ddrphy_read(struct udevice *dev, u32 ch, u32 regadd) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; + u32 val; + int ret; + + writel(regadd | BIT(14), regs_dbsc_d + DBSC_DBPDRGA(ch)); + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBPDRGA(ch), val, (val == (regadd | BIT(15) | BIT(14))), 1000000); + if (ret < 0) { + printf("%s regs_dbsc_d + DBSC_DBPDRGA timeout\n", __func__); + hang(); + } + + val = readl(regs_dbsc_d + DBSC_DBPDRGA(ch)); + + writel(regadd | BIT(15), regs_dbsc_d + DBSC_DBPDRGA(ch)); + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBPDRGA(ch), val, (val == regadd), 1000000); + if (ret < 0) { + printf("%s regs_dbsc_d + DBSC_DBPDRGA | BIT(15) timeout\n", __func__); + hang(); + } + + writel(regadd | BIT(15), regs_dbsc_d + DBSC_DBPDRGA(ch)); + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBPDRGA(ch), val, (val == regadd), 1000000); + if (ret < 0) { + printf("%s regs_dbsc_d + DBSC_DBPDRGA | BIT(15) again timeout\n", __func__); + hang(); + } + + return readl(regs_dbsc_d + DBSC_DBPDRGD(ch)); +} + +/** + * dbsc5_reg_ddrphy_write(dev, ) - Write setting to DDR PHY register + * @dev: DBSC5 device + * @ch: Target channel + * @regadd: Destination address + * @regdata: Value to be written + * + * Write matching values to DBPDRGA, DBPDRGD, DBPDRGA, DBPDRGA registers. + * Wait until the write process completed in each step. + */ +static void dbsc5_reg_ddrphy_write(struct udevice *dev, u32 ch, u32 regadd, u32 regdata) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; + u32 val; + int ret; + + writel(regadd, regs_dbsc_d + DBSC_DBPDRGA(ch)); + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBPDRGA(ch), val, (val == regadd), 1000000); + if (ret < 0) { + printf("%s regs_dbsc_d + DBSC_DBPDRGA timeout\n", __func__); + hang(); + } + + writel(regdata, regs_dbsc_d + DBSC_DBPDRGD(ch)); + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBPDRGA(ch), val, (val == (regadd | BIT(15))), 1000000); + if (ret < 0) { + printf("%s regs_dbsc_d + DBSC_DBPDRGD timeout\n", __func__); + hang(); + } + + writel(regadd | BIT(15), regs_dbsc_d + DBSC_DBPDRGA(ch)); + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBPDRGA(ch), val, (val == regadd), 1000000); + if (ret < 0) { + printf("%s regs_dbsc_d + DBSC_DBPDRGA | BIT(15) timeout\n", __func__); + hang(); + } + + writel(regadd, regs_dbsc_d + DBSC_DBPDRGA(ch)); +} + +/* + * dbsc5_reg_ddrphy_write_all() - Write setting from DDR PHY register for all channels + * @dev: DBSC5 device + * @regadd: Destination address + * @regdata: Value to be written + * + * Wrapper around dbsc5_reg_ddrphy_write() for all channels. + */ +static void dbsc5_reg_ddrphy_write_all(struct udevice *dev, u32 regadd, u32 regdata) +{ + u32 ch; + + r_foreach_vch(dev, ch) + dbsc5_reg_ddrphy_write(dev, ch, regadd, regdata); +} + +/** + * dbsc5_reg_ddrphy_masked_write() - Write setting to DDR PHY register with mask + * @dev: DBSC5 device + * @ch: Target channel + * @regadd: Destination address + * @regdata: Value to be written + * @msk: Register mask + * + * Wrapper around dbsc5_reg_ddrphy_write() with DBPDRGM set. + */ +static void dbsc5_reg_ddrphy_masked_write(struct udevice *dev, u32 ch, u32 regadd, u32 regdata, u32 msk) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; + u32 val; + int ret; + + writel(msk, regs_dbsc_d + DBSC_DBPDRGM(ch)); + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBPDRGM(ch), val, (val == msk), 1000000); + if (ret < 0) { + printf("%s regs_dbsc_d + DBSC_DBPDRGM timeout\n", __func__); + hang(); + } + + dbsc5_reg_ddrphy_write(dev, ch, regadd, regdata); + + writel(0, regs_dbsc_d + DBSC_DBPDRGM(ch)); + ret = readl_poll_timeout(regs_dbsc_d + DBSC_DBPDRGM(ch), val, (val == 0), 1000000); + if (ret < 0) { + printf("%s regs_dbsc_d + DBSC_DBPDRGM != 0 timeout\n", __func__); + hang(); + } +} + +/** + * dbsc5_ddr_setval_slice() - Write setting to DDR PHY hardware + * @dev: DBSC5 device + * @ch: Target channel + * @slice: Target slice + * @regdef: Encoded PHY/PI register and bitfield + * @val: Value to be written + * + * Calculate the bit field in which to write the setting value + * from encoded register and bitfield @regdef parameter. Call + * dbsc5_reg_ddrphy_masked_write() to write the value to hardware. + */ +static void dbsc5_ddr_setval_slice(struct udevice *dev, u32 ch, u32 slice, u32 regdef, u32 val) +{ + const u32 adr = DDR_REGDEF_ADR(regdef) + (0x100 * slice); + const u32 len = DDR_REGDEF_LEN(regdef); + const u32 lsb = DDR_REGDEF_LSB(regdef); + const u32 msk = (len == 32) ? 0xffffffff : ((BIT(len) - 1) << lsb); + const u32 dms = ~((!!(msk & BIT(24)) << 3) | (!!(msk & BIT(16)) << 2) | + (!!(msk & BIT(8)) << 1) | !!(msk & BIT(0))) & 0xf; + + dbsc5_reg_ddrphy_masked_write(dev, ch, adr, val << lsb, dms); +} + +/* + * dbsc5_ddr_setval() - Write setting from DDR PHY hardware slice 0 + * @dev: DBSC5 device + * @ch: Target channel + * @regdef: Encoded PHY/PI register and bitfield + * @val: Value to be written + * + * Wrapper around dbsc5_ddr_setval_slice() for slice 0. + */ +static void dbsc5_ddr_setval(struct udevice *dev, u32 ch, u32 regdef, u32 val) +{ + dbsc5_ddr_setval_slice(dev, ch, 0, regdef, val); +} + +/* + * dbsc5_ddr_setval_all_ch_slice() - Write setting from DDR PHY hardware for all channels and one slice + * @dev: DBSC5 device + * @slice: Target slice + * @regdef: Encoded PHY/PI register and bitfield + * @val: Value to be written + * + * Wrapper around dbsc5_ddr_setval_slice() for slice 0. + */ +static void dbsc5_ddr_setval_all_ch_slice(struct udevice *dev, u32 slice, u32 regdef, u32 val) +{ + u32 ch; + + r_foreach_vch(dev, ch) + dbsc5_ddr_setval_slice(dev, ch, slice, regdef, val); +} + +/* + * dbsc5_ddr_setval_all_ch() - Write setting from DDR PHY hardware for all channels and slice 0 + * @dev: DBSC5 device + * @regdef: Encoded PHY/PI register and bitfield + * @val: Value to be written + * + * Wrapper around dbsc5_ddr_setval_all_ch_slice() for slice 0. + */ +static void dbsc5_ddr_setval_all_ch(struct udevice *dev, u32 regdef, u32 val) +{ + dbsc5_ddr_setval_all_ch_slice(dev, 0, regdef, val); +} + +/* + * dbsc5_ddr_setval_all_ch_all_slice() - Write setting from DDR PHY hardware for all channels and all slices + * @dev: DBSC5 device + * @regdef: Encoded PHY/PI register and bitfield + * @val: Value to be written + * + * Wrapper around dbsc5_ddr_setval_all_ch_slice() for slice 0. + */ +static void dbsc5_ddr_setval_all_ch_all_slice(struct udevice *dev, u32 regdef, u32 val) +{ + u32 slice; + + for (slice = 0; slice < SLICE_CNT; slice++) + dbsc5_ddr_setval_all_ch_slice(dev, slice, regdef, val); +} + +/** + * dbsc5_ddr_getval_slice() - Read setting from DDR PHY/PI hardware + * @dev: DBSC5 device + * @ch: Target channel + * @slice: Target slice + * @regdef: Encoded PHY/PI register and bitfield + * + * Calculate the address and the bit-field from "regdef" value. + * Call dbsc5_reg_ddrphy_read() to read value from the target address. + */ +static u32 dbsc5_ddr_getval_slice(struct udevice *dev, u32 ch, u32 slice, u32 regdef) +{ + const u32 adr = DDR_REGDEF_ADR(regdef) + (0x100 * slice); + const u32 len = DDR_REGDEF_LEN(regdef); + const u32 lsb = DDR_REGDEF_LSB(regdef); + const u32 msk = (len == 32) ? 0xffffffff : (BIT(len) - 1); + + return (dbsc5_reg_ddrphy_read(dev, ch, adr) >> lsb) & msk; +} + +/** + * dbsc5_ddr_getval() - Read setting from DDR PHY/PI hardware slice 0 + * @dev: DBSC5 device + * @ch: Target channel + * @regdef: Encoded PHY/PI register and bitfield + * + * Wrapper around dbsc5_ddr_getval_slice() for slice 0. + */ +static u32 dbsc5_ddr_getval(struct udevice *dev, u32 ch, u32 regdef) +{ + return dbsc5_ddr_getval_slice(dev, ch, 0, regdef); +} + +/** + * dbsc5_table_patch_set() - Modify DDR PHY/PI settings table + * @tbl: DDR PHY/PI setting table pointer + * @adrmsk_pi: Use wider address mask for PI register + * @patch: List of modifications to the settings table + * @patchlen: Length of the list of modifications to the settings table + * + * Calculate the target index of settings table, calculate the bit-field + * to write the setting value, and write the setting value to the target + * bit-field in the index. + */ +static void dbsc5_table_patch_set(u32 *tbl, const bool adrmsk_pi, + const struct dbsc5_table_patch *patch, + int patchlen) +{ + const u32 adrmsk = adrmsk_pi ? 0x7FF : 0xFF; + u32 adr, len, lsb, msk; + int i; + + for (i = 0; i < patchlen; i++) { + adr = DDR_REGDEF_ADR(patch[i].reg); + len = DDR_REGDEF_LEN(patch[i].reg); + lsb = DDR_REGDEF_LSB(patch[i].reg); + msk = (len == 32) ? 0xffffffff : ((BIT(len) - 1) << lsb); + + tbl[adr & adrmsk] &= ~msk; + tbl[adr & adrmsk] |= (patch[i].val << lsb) & msk; + } +} + +/** + * dbsc5_ddrtbl_getval() - Read setting from DDR PHY/PI settings table + * @tbl: DDR PHY/PI setting table pointer + * @regdef: Encoded PHY/PI register and bitfield + * @adrmsk_pi: Use wider address mask for PI register + * + * Calculate the target index of *tbl and the bit-field to read the + * setting value and read and return the setting value from the target + * bit-field in the index. + */ +static u32 dbsc5_ddrtbl_getval(const u32 *tbl, u32 regdef, bool adrmsk_pi) +{ + const u32 adrmsk = adrmsk_pi ? 0x7FF : 0xFF; + const u32 adr = DDR_REGDEF_ADR(regdef); + const u32 len = DDR_REGDEF_LEN(regdef); + const u32 lsb = DDR_REGDEF_LSB(regdef); + const u32 msk = (len == 32) ? 0xffffffff : (BIT(len) - 1); + + return (tbl[adr & adrmsk] >> lsb) & msk; +} + +/** + * dbsc5_f_scale() - Calculate the best value for DBSC timing setting + * @priv: Driver private data + * @frac: Perform fractional rounding + * @ps Optimal setting value in pico second + * @cyc Optimal setting value in cycle count + * + * Convert the optimal value in pico second to in cycle count. Optionally, if @frac is true, + * perform fractional rounding. Compare the value of the result of the conversion with the + * value of the argument @cyc and return the larger value. + */ +static u32 dbsc5_f_scale(struct renesas_dbsc5_dram_priv *priv, const bool frac, u32 ps, u32 cyc) +{ + const u32 mul = frac ? 8 : 800000; + const u32 tmp = DIV_ROUND_UP(ps, 10UL) * priv->ddr_mbps; + const u32 f_scale_div = DIV_ROUND_UP(tmp, mul * priv->ddr_mbpsdiv); + + return (f_scale_div > cyc) ? f_scale_div : cyc; +} + +/** + * dbsc5_f_scale_js2() - Select optimal settings based on jedec_spec2 + * @priv: Driver private data + * + * Calculate and assign each setting value of jedec_spec2 by "dbsc5_f_scale" function. + * Only the following array elements are calculated using different formulas from those + * described above -- JS2_tRRD/JS2_tFAW/JS2_tZQCALns/JS2_tRCpb/JS2_tRCab. + */ +static void dbsc5_f_scale_js2(struct renesas_dbsc5_dram_priv *priv) +{ + const int derate = 0; + int i; + + for (i = 0; i < JS2_TBLCNT; i++) { + priv->js2[i] = dbsc5_f_scale(priv, false, + jedec_spec2[derate][i].ps, + jedec_spec2[derate][i].cyc); + } + + priv->js2[JS2_tZQCALns] = dbsc5_f_scale(priv, false, + jedec_spec2[derate][JS2_tZQCALns].ps * 1000UL, 0); + priv->js2[JS2_tDQ72DQns] = dbsc5_f_scale(priv, false, + jedec_spec2[derate][JS2_tDQ72DQns].ps * 1000UL, 0); + priv->js2[JS2_tCAENTns] = dbsc5_f_scale(priv, false, + jedec_spec2[derate][JS2_tCAENTns].ps * 1000UL, 0); + priv->js2[JS2_tRCpb] = priv->js2[JS2_tRAS] + priv->js2[JS2_tRPpb]; + priv->js2[JS2_tRCab] = priv->js2[JS2_tRAS] + priv->js2[JS2_tRPab]; + priv->js2[JS2_tRFCab] = dbsc5_f_scale(priv, false, + jedec_spec2_tRFC_ab[priv->max_density] * 1000UL, 0); + + priv->js2[JS2_tRBTP] = dbsc5_f_scale(priv, false, 7500, 2) - 2; + priv->js2[JS2_tXSR] = priv->js2[JS2_tRFCab] + + dbsc5_f_scale(priv, false, 7500, 2); + priv->js2[JS2_tPDN] = dbsc5_f_scale(priv, false, 10000, 0) + 1; + priv->js2[JS2_tPDN_DSM] = dbsc5_f_scale(priv, true, + jedec_spec2[derate][JS2_tPDN_DSM].ps * 10UL, 0); + priv->js2[JS2_tXSR_DSM] = dbsc5_f_scale(priv, true, + jedec_spec2[derate][JS2_tXSR_DSM].ps * 10UL, 0); + priv->js2[JS2_tXDSM_XP] = dbsc5_f_scale(priv, true, + jedec_spec2[derate][JS2_tXDSM_XP].ps * 10UL, 0); + priv->js2[JS2_tWLWCKOFF] = dbsc5_f_scale(priv, false, 14000, 5); +} + +/** + * dbsc5_ddrtbl_calc() - Calculate JS1/JS2 + * @priv: Driver private data + * + * Determine jedec_spec1 configuration table based on priv->ddr_mbps + * and priv->ddr_mbpsdiv. Calculate the value of the jedec_spec2 + * configuration table from priv->ddr_mbps and priv->ddr_mbpsdiv. + */ +static void dbsc5_ddrtbl_calc(struct renesas_dbsc5_dram_priv *priv) +{ + int i; + + /* Search jedec_spec1 index */ + for (i = JS1_USABLEC_SPEC_LO; i < JS1_FREQ_TBL_NUM - 1; i++) + if (js1[i].fx3 * 2 * priv->ddr_mbpsdiv >= priv->ddr_mbps * 3) + break; + + priv->js1_ind = max(i, JS1_USABLEC_SPEC_HI); + + priv->RL = js1[priv->js1_ind].RLset1; + priv->WL = js1[priv->js1_ind].WLsetA; + + /* Calculate jedec_spec2 */ + dbsc5_f_scale_js2(priv); +}; + +/** + * dbsc5_ddrtbl_load() Load table data into DDR registers + * @dev: DBSC5 device + * + * Copy the base configuration table to a local array. Change PI register table + * settings to match priv->ddr_mbps and priv->ddr_mbpsdiv. + * + * If the set value vref_r is not 0, change the "Read Vref (SoC side) Training range" + * setting in the configuration table. + * + * If the set value vref_w is not 0, change the "Write Vref (MR14, MR15) Training range" + * setting in the configuration table. + * + * If the set value vref_ca is not 0, change the "CA Vref (MR12) Training range" + * setting in the configuration table. + * + * If priv->ddr_mbps/priv->ddr_mbpsdiv is less than 5120, + * change the contents of the PHY register setting table. + * If priv->ddr_mbps/priv->ddr_mbpsdiv is less than 4576, + * change the contents of the PHY register setting table. + * + * Reflect the contents of the configuration table in the register. + */ +static void dbsc5_ddrtbl_load(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const struct dbsc5_table_patch dbsc5_table_patch_adr_g_mbps = { + PHY_CAL_INTERVAL_COUNT_0, 10000 * priv->ddr_mbps / priv->ddr_mbpsdiv / 8 / 256, + }; + + const struct dbsc5_table_patch dbsc5_table_patch_pi_js[] = { + { PI_WRLAT_F2, priv->WL }, + { PI_TWCKENL_WR_ADJ_F2, (js1[priv->js1_ind].WCKENLW * 4) + 4 }, + { PI_TWCKENL_RD_ADJ_F2, (js1[priv->js1_ind].WCKENLR * 4) + 4 }, + { PI_TWCKPRE_STATIC_F2, (js1[priv->js1_ind].WCKPRESTA * 4) }, + { PI_TWCKPRE_TOGGLE_RD_F2, (js1[priv->js1_ind].WCKPRETGLR) * 4 }, + { PI_CASLAT_F2, priv->RL }, + { PI_TWCKENL_FS_ADJ_F2, (js1[priv->js1_ind].WCKENLF * 4) + 4 }, + { PI_TRFC_F2, priv->js2[JS2_tRFCab] }, + { PI_WRLVL_WCKOFF_F2, (priv->js2[JS2_tWLWCKOFF]) + 3 }, + { PI_WRLAT_ADJ_F2, (priv->WL * 4) + 2 }, + { PI_TCAENT_F2, priv->js2[JS2_tCAENTns] }, + { PI_TVREF_LONG_F2, (priv->js2[JS2_tCAENTns]) + 1 }, + { PI_TVREF_SHORT_F2, (priv->js2[JS2_tCAENTns]) + 1 }, + { PI_TRCD_F2, priv->js2[JS2_tRCD] }, + { PI_TRP_F2, priv->js2[JS2_tRPab] }, + { PI_TRTP_F2, js1[priv->js1_ind].nRBTP }, + { PI_TRAS_MIN_F2, priv->js2[JS2_tRAS] }, + { PI_TMRD_F2, (priv->js2[JS2_tMRD]) + 1 }, + { PI_TSR_F2, priv->js2[JS2_tSR] }, + { PI_TZQCAL_F2, priv->js2[JS2_tZQCALns] }, + { PI_TZQLAT_F2, priv->js2[JS2_tZQLAT] }, + { PI_TDQ72DQ_F2, priv->js2[JS2_tDQ72DQns] }, + { PI_MC_TRFC_F2, priv->js2[JS2_tRFCab] }, + }; + + const u32 vref_r = priv->dbsc5_board_config->bdcfg_vref_r; + const struct dbsc5_table_patch dbsc5_table_patch_slice_vref_r[] = { + { PHY_VREF_INITIAL_START_POINT, vref_r & 0xFF }, + { PHY_VREF_INITIAL_STOP_POINT, (vref_r & 0xFF00) >> 8 }, + { PHY_VREF_INITIAL_STEPSIZE, (vref_r & 0xFF0000) >> 16 } + }; + + const u32 vref_w = priv->dbsc5_board_config->bdcfg_vref_w; + const struct dbsc5_table_patch dbsc5_table_patch_pi_vref_w[] = { + { PI_WDQLVL_VREF_INITIAL_START_POINT_F0, vref_w & 0xff }, + { PI_WDQLVL_VREF_INITIAL_START_POINT_F1, vref_w & 0xff }, + { PI_WDQLVL_VREF_INITIAL_START_POINT_F2, vref_w & 0xff }, + { PI_WDQLVL_VREF_INITIAL_STOP_POINT_F0, (vref_w & 0xff00) >> 8 }, + { PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1, (vref_w & 0xff00) >> 8 }, + { PI_WDQLVL_VREF_INITIAL_STOP_POINT_F2, (vref_w & 0xff00) >> 8 } + }; + + const u32 vref_ca = priv->dbsc5_board_config->bdcfg_vref_ca; + const struct dbsc5_table_patch dbsc5_table_patch_pi_vref_ca[] = { + { PI_CALVL_VREF_INITIAL_START_POINT_F0, vref_ca & 0xff }, + { PI_CALVL_VREF_INITIAL_START_POINT_F1, vref_ca & 0xff }, + { PI_CALVL_VREF_INITIAL_START_POINT_F2, vref_ca & 0xff }, + { PI_CALVL_VREF_INITIAL_STOP_POINT_F0, (vref_ca & 0xff00) >> 8 }, + { PI_CALVL_VREF_INITIAL_STOP_POINT_F1, (vref_ca & 0xff00) >> 8 }, + { PI_CALVL_VREF_INITIAL_STOP_POINT_F2, (vref_ca & 0xff00) >> 8 } + }; + + int i, cs, slice; + u32 adr; + + /* Prepare register tables */ + memcpy(priv->DDR_PHY_SLICE_REGSET, DDR_PHY_SLICE_REGSET_V4H, sizeof(DDR_PHY_SLICE_REGSET_V4H)); + memcpy(priv->DDR_PHY_ADR_V_REGSET, DDR_PHY_ADR_V_REGSET_V4H, sizeof(DDR_PHY_ADR_V_REGSET_V4H)); + memcpy(priv->DDR_PHY_ADR_G_REGSET, DDR_PHY_ADR_G_REGSET_V4H, sizeof(DDR_PHY_ADR_G_REGSET_V4H)); + memcpy(priv->DDR_PI_REGSET, DDR_PI_REGSET_V4H, sizeof(DDR_PI_REGSET_V4H)); + + /* Adjust PI parameters */ + dbsc5_table_patch_set(priv->DDR_PHY_ADR_G_REGSET, false, + &dbsc5_table_patch_adr_g_mbps, 1); + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_js, + ARRAY_SIZE(dbsc5_table_patch_pi_js)); + + if (priv->ddr_mbps < (3201 * priv->ddr_mbpsdiv)) { + /* 2751-3200 */ + dbsc5_table_patch_set(priv->DDR_PHY_SLICE_REGSET, false, + dbsc5_table_patch_slice_3200, + ARRAY_SIZE(dbsc5_table_patch_slice_3200)); + dbsc5_table_patch_set(priv->DDR_PHY_ADR_V_REGSET, false, + dbsc5_table_patch_adr_v_3200, + ARRAY_SIZE(dbsc5_table_patch_adr_v_3200)); + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_3200, + ARRAY_SIZE(dbsc5_table_patch_pi_3200)); + } else if (priv->ddr_mbps < (3734 * priv->ddr_mbpsdiv)) { + /* 3201-3733 */ + dbsc5_table_patch_set(priv->DDR_PHY_SLICE_REGSET, false, + dbsc5_table_patch_slice_3733, + ARRAY_SIZE(dbsc5_table_patch_slice_3733)); + dbsc5_table_patch_set(priv->DDR_PHY_ADR_V_REGSET, false, + dbsc5_table_patch_adr_v_3733, + ARRAY_SIZE(dbsc5_table_patch_adr_v_3733)); + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_3733, + ARRAY_SIZE(dbsc5_table_patch_pi_3733)); + } else if (priv->ddr_mbps < (4268 * priv->ddr_mbpsdiv)) { + /* 3734-4267 */ + dbsc5_table_patch_set(priv->DDR_PHY_SLICE_REGSET, false, + dbsc5_table_patch_slice_4266, + ARRAY_SIZE(dbsc5_table_patch_slice_4266)); + dbsc5_table_patch_set(priv->DDR_PHY_ADR_V_REGSET, false, + dbsc5_table_patch_adr_v_4266, + ARRAY_SIZE(dbsc5_table_patch_adr_v_4266)); + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_4266, + ARRAY_SIZE(dbsc5_table_patch_pi_4266)); + } else if (priv->ddr_mbps < (4801 * priv->ddr_mbpsdiv)) { + /* 4269-4800 */ + dbsc5_table_patch_set(priv->DDR_PHY_SLICE_REGSET, false, + dbsc5_table_patch_slice_4800, + ARRAY_SIZE(dbsc5_table_patch_slice_4800)); + dbsc5_table_patch_set(priv->DDR_PHY_ADR_V_REGSET, false, + dbsc5_table_patch_adr_v_4800, + ARRAY_SIZE(dbsc5_table_patch_adr_v_4800)); + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_4800, + ARRAY_SIZE(dbsc5_table_patch_pi_4800)); + } else if (priv->ddr_mbps < (5501 * priv->ddr_mbpsdiv)) { + /* 4801 - 5500 */ + dbsc5_table_patch_set(priv->DDR_PHY_SLICE_REGSET, false, + dbsc5_table_patch_slice_5500, + ARRAY_SIZE(dbsc5_table_patch_slice_5500)); + dbsc5_table_patch_set(priv->DDR_PHY_ADR_V_REGSET, false, + dbsc5_table_patch_adr_v_5500, + ARRAY_SIZE(dbsc5_table_patch_adr_v_5500)); + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_5500, + ARRAY_SIZE(dbsc5_table_patch_pi_5500)); + } else if (priv->ddr_mbps < (6001 * priv->ddr_mbpsdiv)) { + /* 5501 - 6000 */ + dbsc5_table_patch_set(priv->DDR_PHY_SLICE_REGSET, false, + dbsc5_table_patch_slice_6000, + ARRAY_SIZE(dbsc5_table_patch_slice_6000)); + dbsc5_table_patch_set(priv->DDR_PHY_ADR_V_REGSET, false, + dbsc5_table_patch_adr_v_6000, + ARRAY_SIZE(dbsc5_table_patch_adr_v_6000)); + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_6000, + ARRAY_SIZE(dbsc5_table_patch_pi_6000)); + } + + for (cs = 0; cs < CS_CNT; cs++) { + struct dbsc5_table_patch dbsc5_table_patch_pi_mr12[] = { + { PI_DARRAY3_0_CSx_Fx[cs][2], js1[priv->js1_ind].MR1 }, + { PI_DARRAY3_1_CSx_Fx[cs][2], js1[priv->js1_ind].MR2 }, + }; + + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_mr12, + ARRAY_SIZE(dbsc5_table_patch_pi_mr12)); + } + + /* Read Vref (SoC side) Training range */ + if (priv->dbsc5_board_config->bdcfg_vref_r) { + dbsc5_table_patch_set(priv->DDR_PHY_SLICE_REGSET, false, + dbsc5_table_patch_slice_vref_r, + ARRAY_SIZE(dbsc5_table_patch_slice_vref_r)); + } + + /* Write Vref (MR14, MR15) Training range */ + if (priv->dbsc5_board_config->bdcfg_vref_w) { + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_vref_w, + ARRAY_SIZE(dbsc5_table_patch_pi_vref_w)); + } + + /* CA Vref (MR12) Training range */ + if (priv->dbsc5_board_config->bdcfg_vref_ca) { + dbsc5_table_patch_set(priv->DDR_PI_REGSET, true, + dbsc5_table_patch_pi_vref_ca, + ARRAY_SIZE(dbsc5_table_patch_pi_vref_ca)); + } + + /* Low Freq setting */ + if (priv->ddr_mbps < (8 * 640 * priv->ddr_mbpsdiv)) { + /* CAL_CLK(10-20MHz) */ + dbsc5_table_patch_set(priv->DDR_PHY_SLICE_REGSET, false, + &dbsc5_table_patch_slice_mbpsdiv_640, 1); + dbsc5_table_patch_set(priv->DDR_PHY_ADR_V_REGSET, false, + &dbsc5_table_patch_adr_v_mbpsdiv_640, 1); + dbsc5_table_patch_set(priv->DDR_PHY_ADR_G_REGSET, false, + &dbsc5_table_patch_adr_g_mbpsdiv_640, 1); + } + + if (priv->ddr_mbps < (8 * 572 * priv->ddr_mbpsdiv)) { + /* CAL_CLK(10-20MHz) */ + dbsc5_table_patch_set(priv->DDR_PHY_SLICE_REGSET, false, + &dbsc5_table_patch_slice_mbpsdiv_572, 1); + dbsc5_table_patch_set(priv->DDR_PHY_ADR_G_REGSET, false, + &dbsc5_table_patch_adr_g_mbpsdiv_572, 1); + } + + if (priv->ddr_mbps < (8 * 401 * priv->ddr_mbpsdiv)) { + dbsc5_table_patch_set(priv->DDR_PHY_ADR_G_REGSET, false, + dbsc5_table_patch_adr_g_mbpsdiv_400, + ARRAY_SIZE(dbsc5_table_patch_adr_g_mbpsdiv_400)); + } + + /* SET DATA SLICE TABLE */ + for (slice = 0; slice < SLICE_CNT; slice++) { + adr = DDR_PHY_SLICE_REGSET_OFS_V4H + (DDR_PHY_SLICE_REGSET_SIZE_V4H * slice); + for (i = 0; i < DDR_PHY_SLICE_REGSET_NUM_V4H; i++) + dbsc5_reg_ddrphy_write_all(dev, adr + i, priv->DDR_PHY_SLICE_REGSET[i]); + } + + /* SET ADR SLICE TABLE */ + for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM_V4H; i++) + dbsc5_reg_ddrphy_write_all(dev, DDR_PHY_ADR_V_REGSET_OFS_V4H + i, priv->DDR_PHY_ADR_V_REGSET[i]); + + /* SET ADRCTRL SLICE TABLE */ + for (i = 0; i < DDR_PHY_ADR_G_REGSET_NUM_V4H; i++) + dbsc5_reg_ddrphy_write_all(dev, DDR_PHY_ADR_G_REGSET_OFS_V4H + i, priv->DDR_PHY_ADR_G_REGSET[i]); + + /* SET PI REGISTERS */ + for (i = 0; i < DDR_PI_REGSET_NUM_V4H; i++) + dbsc5_reg_ddrphy_write_all(dev, DDR_PI_REGSET_OFS_V4H + i, priv->DDR_PI_REGSET[i]); +} + +/** + * dbsc5_ddr_config() - Configure DDR registers + * @dev: DBSC5 device + * + * Set up wiring for DQ and DM pins and VREF_DRIVING. Set the CA pin wiring + * and ADR_CALVL_SWIZZLE settings. Make wiring settings for the CS pin. When + * memory rank is 1, set RANK setting to 1 to disable CS training. Configure + * the DATA_BYTE_SWAP setting. + */ +static void dbsc5_ddr_config(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + u32 ca_swap, cs_swap, dqs_swap; + u32 ch, slice; + + r_foreach_vch(dev, ch) { + /* Board settings (DQ, DM, VREF_DRIVING) */ + dqs_swap = priv->dbsc5_board_config->ch[ch].bdcfg_dqs_swap; + for (slice = 0; slice < SLICE_CNT; slice++) { + dbsc5_ddr_setval_slice(dev, ch, slice, PHY_DQ_DM_SWIZZLE0, + priv->dbsc5_board_config->ch[ch].bdcfg_dq_swap[slice]); + dbsc5_ddr_setval_slice(dev, ch, slice, PHY_DQ_DM_SWIZZLE1, + priv->dbsc5_board_config->ch[ch].bdcfg_dm_swap[slice]); + dbsc5_ddr_setval_slice(dev, ch, slice, PHY_CALVL_VREF_DRIVING_SLICE, + !((dqs_swap >> (4 * slice)) & 1)); + } + dbsc5_ddr_setval(dev, ch, PHY_DATA_BYTE_ORDER_SEL, + priv->dbsc5_board_config->ch[ch].bdcfg_dqs_swap | 0x76543200); + + /* Board settings (CA, ADDR_MUX) */ + ca_swap = priv->dbsc5_board_config->ch[ch].bdcfg_ca_swap; + + /* ADDR_MUX */ + dbsc5_ddr_setval(dev, ch, PI_ADDR_MUX_0, ca_swap & 0xf); + ca_swap >>= 4; + dbsc5_ddr_setval(dev, ch, PI_ADDR_MUX_1, ca_swap & 0xf); + ca_swap >>= 4; + dbsc5_ddr_setval(dev, ch, PI_ADDR_MUX_2, ca_swap & 0xf); + ca_swap >>= 4; + dbsc5_ddr_setval(dev, ch, PI_ADDR_MUX_3, ca_swap & 0xf); + ca_swap >>= 4; + dbsc5_ddr_setval(dev, ch, PI_ADDR_MUX_4, ca_swap & 0xf); + ca_swap >>= 4; + dbsc5_ddr_setval(dev, ch, PI_ADDR_MUX_5, ca_swap & 0xf); + ca_swap >>= 4; + dbsc5_ddr_setval(dev, ch, PI_ADDR_MUX_6, ca_swap & 0xf); + ca_swap >>= 4; + + /* ADR_CALVL_SWIZZLE */ + ca_swap = priv->dbsc5_board_config->ch[ch].bdcfg_ca_swap; + dbsc5_ddr_setval(dev, ch, PHY_ADR_CALVL_SWIZZLE0, ca_swap & 0x0fffffff); + + /* Board settings (CS) */ + /* CKE_MUX */ + /* SoC CKE -> DRAM CS */ + cs_swap = priv->dbsc5_board_config->ch[ch].bdcfg_cs_swap; + dbsc5_ddr_setval(dev, ch, PI_CKE_MUX_0, (cs_swap & 0xf) + 2); + dbsc5_ddr_setval(dev, ch, PI_CKE_MUX_1, ((cs_swap >> 4) & 0xf) + 2); + dbsc5_ddr_setval(dev, ch, PHY_CS_ACS_ALLOCATION_BIT2_2, (cs_swap & 0xf) + 1); + dbsc5_ddr_setval(dev, ch, PHY_CS_ACS_ALLOCATION_BIT3_2, ((cs_swap >> 4) & 0xf) + 1); + + /* Mask CS_MAP if RANK1 is not found */ + if (!(priv->ch_have_this_cs[1] & BIT(ch))) { + dbsc5_ddr_setval(dev, ch, PHY_ADR_CALVL_RANK_CTRL, 0x0); + for (slice = 0; slice < SLICE_CNT; slice++) + dbsc5_ddr_setval_slice(dev, ch, slice, PHY_PER_CS_TRAINING_EN, 0x0); + } + } + + r_foreach_vch(dev, ch) { + /* DATA_BYTE_SWAP */ + dqs_swap = priv->dbsc5_board_config->ch[ch].bdcfg_dqs_swap; + + dbsc5_ddr_setval(dev, ch, PI_DATA_BYTE_SWAP_EN, 0x1); + dbsc5_ddr_setval(dev, ch, PI_DATA_BYTE_SWAP_SLICE0, dqs_swap & 0xf); + dbsc5_ddr_setval(dev, ch, PI_DATA_BYTE_SWAP_SLICE1, (dqs_swap >> 4) & 0xf); + + if (!(priv->ch_have_this_cs[1] & BIT(ch))) + dbsc5_ddr_setval(dev, ch, PI_CS_MAP, 0x1); + } +} + +/** + * dbsc5_dbsc_regset_pre() - Configure primary DDR registers + * @dev: DBSC5 device + * + * Set SDRAM type, Burst length, and PHY type. Frequency mode setting. + * Write SDRAM configuration contents to registers. + */ +static void dbsc5_dbsc_regset_pre(struct udevice *dev) +{ +#define DBMEMCONF_REG(d3, row, bg, bank, col, dw) \ + (((d3) << 30) | ((row) << 24) | ((bg) << 20) | ((bank) << 16) | ((col) << 8) | (dw)) +#define DBMEMCONF_REGD(density) /* 16bit */ \ + DBMEMCONF_REG(((density) % 2), ((((density) + 1) / 2) + (28 - 2 - 2 - 10 - 1)), 2, 2, 10, 1) + + 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; + u32 density; + u32 ch, cs; + + /* Primary settings */ + /* LPDDR5, BL=16, DFI interface */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBMEMKIND, 0xC); + dbsc5_reg_write(regs_dbsc_a + DBSC_DBMEMKINDA, 0xC); + dbsc5_reg_write(regs_dbsc_d + DBSC_DBBL, 0x2); + dbsc5_reg_write(regs_dbsc_a + DBSC_DBBLA, 0x2); + dbsc5_reg_write(regs_dbsc_d + DBSC_DBPHYCONF0, 0x1); + + dbsc5_reg_write(regs_dbsc_a + DBSC_DBSYSCONF0, 0x1); + + /* FREQRATIO=2 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBSYSCONF1, 0x20000); + dbsc5_reg_write(regs_dbsc_a + DBSC_DBSYSCONF1A, 0x0); + + dbsc5_reg_write(regs_dbsc_d + DBSC_DBSYSCONF2, 0x1); + dbsc5_reg_write(regs_dbsc_a + DBSC_DBSYSCONF2A, 0x241); + + r_foreach_ech(ch) { + for (cs = 0; cs < CS_CNT; cs++) { + if (priv->ddr_density[ch][cs] == 0xFF) { + writel(0x00, regs_dbsc_d + DBSC_DBMEMCONF(ch, cs)); + writel(0x00, regs_dbsc_a + DBSC_DBMEMCONFA(ch, cs)); + } else { + density = priv->ddr_density[ch][cs]; + writel(DBMEMCONF_REGD(density), + regs_dbsc_d + DBSC_DBMEMCONF(ch, cs)); + writel(DBMEMCONF_REGD(density), + regs_dbsc_a + DBSC_DBMEMCONFA(ch, cs)); + } + } + } +} + +/** + * dbsc5_dbsc_regset() - Set DBSC timing parameters + * @dev: DBSC5 device + * + * Set the timing registers of the DBSC. + * Configure Scheduler settings. + */ +static void dbsc5_dbsc_regset(struct udevice *dev) +{ + 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; + u32 tmp[4]; + + /* DBTR0.CL : RL */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(0), priv->RL); + + /* DBTR1.CWL : WL */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(1), priv->WL); + + /* DBTR2.AL = 0 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(2), 0x0); + + /* DBTR3.TRCD: tRCD */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(3), priv->js2[JS2_tRCD]); + + /* DBTR4.TRPA,TRP: tRPab,tRPpb */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(4), (priv->js2[JS2_tRPab] << 16) | + priv->js2[JS2_tRPpb]); + + /* DBTR5.TRC : tRCpb */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(5), priv->js2[JS2_tRCpb]); + + /* DBTR6.TRAS : tRAS */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(6), priv->js2[JS2_tRAS]); + + /* DBTR7.TRRD : tRRD */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(7), ((priv->js2[JS2_tRRD] - 1) << 16) | + (priv->js2[JS2_tRRD] - 1)); + + /* DBTR8.TFAW : tFAW */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(8), priv->js2[JS2_tFAW] - 1); + + /* DBTR9.TRDPR: nRBTP */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(9), js1[priv->js1_ind].nRBTP); + + /* DBTR10.TWR : nWR */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(10), js1[priv->js1_ind].nWR); + + /* + * DBTR11.TRDWR : RL + BL/n_max + RU(tWCK2DQO(max)/tCK) + + * RD(tRPST/tCK) - ODTLon - RD(tODTon(min)/tCK) + 1 + feature + */ + 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]); + + /* DBTR12.TWRRD_S : WL + BL/2 + tWTR_S, TWRRD_L : WL + BL + tWTR_L */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(12), + ((priv->WL + 2 + priv->js2[JS2_tWTR_S]) << 16) | + (priv->WL + 4 + priv->js2[JS2_tWTR_L])); + + /* DBTR13.TRFCAB : tRFCab */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(13), priv->js2[JS2_tRFCab]); + + /* DBTR14.TCSCAL,TCKEHDLL,tCKEH : tCSCAL,tXP,tXP */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(14), (priv->js2[JS2_tCSCAL] << 24) | + (priv->js2[JS2_tXP] << 16) | + priv->js2[JS2_tXP]); + + /* DBTR15.TESPD,TCKESR,TCKEL : tESPD = 2,tSR,tSR */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(15), (0x02 << 24) | + (priv->js2[JS2_tSR] << 16) | + priv->js2[JS2_tSR]); + + /* DBTR16 */ + /* wdql(tphy_wrlat + tphy_wrdata) */ + tmp[0] = (priv->WL * 4) - 1 + 5; + /* dqenltcy(tphy_wrlat) */ + tmp[1] = (priv->WL * 4) - 2 - 2 + 5; + /* dql(tphy_rdlat + trddata_en) RL * 4 + phy_rptr_update + phy_rddqs_latency_adjust + 39 */ + tmp[2] = (priv->RL * 4) + + dbsc5_ddrtbl_getval(priv->DDR_PHY_SLICE_REGSET, PHY_RPTR_UPDATE, false) + + dbsc5_ddrtbl_getval(priv->DDR_PHY_SLICE_REGSET, PHY_RDDQS_LATENCY_ADJUST, false) + + 39; + /* dqienltncy(trddata_en) RL * 4 - phy_rddata_en_dly_X + 4 * phy_wck_freq_ratio_X */ + tmp[3] = (priv->RL * 4) + 4 - + dbsc5_ddrtbl_getval(priv->DDR_PHY_SLICE_REGSET, PHY_RDDATA_EN_DLY, false); + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(16), (tmp[3] << 24) | (tmp[2] << 16) | + (tmp[1] << 8) | tmp[0]); + + /* DBTR17.TMODRD,TMOD: tMRR,tMRW */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(17), (priv->js2[JS2_tMRR] << 24) | + (priv->js2[JS2_tMRW] << 16)); + + /* DBTR18. RODTL, RODTA = 0 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(18), 0x0); + + /* DBTR19. TZQCL, TZQCS = 0 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(19), 0x0); + + /* DBTR20.TXSDLL, TXS : tXSR,tXSR */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(20), ((priv->js2[JS2_tXSR]) << 16) | + priv->js2[JS2_tXSR]); + + /* DBTR21.TCCD */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(21), (priv->ddr_tccd << 16) | + (priv->ddr_tccd * 2)); + + /* DBTR22.TZQCAL,TZQLAT : tZQCAL,tZQLAT */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(22), (priv->js2[JS2_tZQCALns] << 16) | priv->js2[JS2_tZQLAT]); + + /* DBTR23. RRSPC = 0 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(23), 0x0); + + /* DBTR24 */ + /* WRCSLAT(tphy_wrcslat) */ + tmp[0] = (priv->WL * 4) - 2; + /* WRCSGAP(tphy_wrcsgap) */ + tmp[1] = 0x0C; + /* RDCSLAT(tphy_rdcslat) */ + tmp[2] = priv->RL * 4; + /* RDCSGAP(tphy_rdcsgap) */ + tmp[3] = 0x0C; + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(24), (tmp[3] << 24) | (tmp[2] << 16) | + (tmp[1] << 8) | tmp[0]); + + /* DBTR25. TWDQLVLDIS = 0 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(25), 0x0); + + /* DBTR26. TWCK2DQOOSC,TDQSOSC : WCK2DQI interval timer run time, WCK2DQO interval timer run time */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(26), 0x0); + + /* DBTR27.TPDN : tPDN */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(27), priv->js2[JS2_tPDN]); + + /* DBTR28.txsrdsm : tXSR_DSM */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(28), priv->js2[JS2_tXSR_DSM]); + + /* DBTR29.tdsmxp : tXDSM_XP */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(29), priv->js2[JS2_tXDSM_XP]); + + /* DBTR30.TCMDPD : tCMDPD = 3 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(30), 0x3); + + /* DBTR31.TWCK2DQOMAX,TWCK2DQIMAX : tWCK2DQI/O_HF/LF */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(31), (priv->js2[JS2_tWCK2DQO_HF] << 4) | + priv->js2[JS2_tWCK2DQI_HF]); + + /* DBTR32 */ + /* twckenr */ + tmp[0] = (js1[priv->js1_ind].WCKENLR * 4) + 4 - 1; + /* twckenw */ + tmp[1] = (js1[priv->js1_ind].WCKENLW * 4) + 4 - 1; + /* twckenlf */ + tmp[2] = (js1[priv->js1_ind].WCKENLF * 4) + 4; + /* twckpresta */ + tmp[3] = js1[priv->js1_ind].WCKPRESTA * 4; + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(32), (tmp[3] << 24) | (tmp[2] << 16) | + (tmp[1] << 8) | tmp[0]); + + /* DBTR33 */ + /* TWCKTGL */ + tmp[0] = 4; + /* TWCKDIS (RL+ bl/n_max) * 4 + RU(tWCKPST/tWCK) : tWCKPST = 2.5(MR10[3:2]) */ + tmp[1] = ((priv->RL + 4) * 4) + 3; + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(33), (tmp[1] << 8) | tmp[0]); + + /* DBTR34 */ + /* TWCKSUS = 4 */ + tmp[0] = 4; + /* TWCKPST RU(tWCKPST/tCK) : tWCKPST=2.5(MR10[3:2]) */ + tmp[1] = 1; + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(34), (tmp[1] << 8) | tmp[0]); + + /* DBTR35 */ + /* TRD2WCKOFF RL + BL/n_max + RD(tWCKPST/tCK) + 1 */ + tmp[0] = priv->RL + 4 + 0 + 1; + /* TWR2WCKOFF WL + BL/n_max + RD(tWCKPST/tCK) + 1 */ + tmp[1] = priv->WL + 4 + 0 + 1; + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(35), (tmp[1] << 16) | tmp[0]); + + /* DBTR36 */ + /* TWSSUSWRX : CAS(WCKSUS)WRX */ + tmp[0] = 3; + /* TWSOFFWRX : CAS(WS_OFF)WRX */ + tmp[1] = 3; + /* TWSFSWRX : CAS(WS_FS)WRX */ + tmp[2] = 2; + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(36), (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]); + + /* DBTR37 */ + /* tOSCO */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(37), priv->js2[JS2_tOSCODQI]); + + /* DBRNK2 */ + /* RNKRR = 12 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBRNK(2), 0xCC); + + /* DBRNK3 */ + /* RNKRW = 6 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBRNK(3), 0x66); + + /* DBRNK4 */ + /* RNKWR = 6 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBRNK(4), 0x66); + + /* DBRNK5 */ + /* RNKWW = 14 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBRNK(5), 0xEE); + + /* Timing registers for Scheduler */ + /* SCFCTST0 */ + /* SCPREACT */ + tmp[0] = priv->js2[JS2_tRPpb] * priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv; + /* SCACTRDWR */ + tmp[1] = (priv->WL + 2 + 1 + js1[priv->js1_ind].nWR + priv->js2[JS2_tRPpb]) * + priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv; + /* SCRDACRT */ + tmp[2] = ((js1[priv->js1_ind].nRBTP + 2) + priv->js2[JS2_tRPpb]) * + priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv; + /* SCACTACT */ + tmp[3] = priv->js2[JS2_tRCpb] * priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv; + dbsc5_reg_write(regs_dbsc_a + DBSC_DBSCHFCTST0, (tmp[3] << 24) | (tmp[2] << 16) | + (tmp[1] << 8) | tmp[0]); + + /* SCFCTST1 */ + /* SCASYNCOFS */ + tmp[0] = 12; + /* SCACTRDWR */ + tmp[1] = priv->js2[JS2_tRCD] * priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv; + /* SCWRRD */ + tmp[2] = (readl(regs_dbsc_d + DBSC_DBTR(12)) & 0xFF) * priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv; + /* SCRDWR */ + tmp[3] = (readl(regs_dbsc_d + DBSC_DBTR(11)) & 0xFF) * priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv; + dbsc5_reg_write(regs_dbsc_a + DBSC_DBSCHFCTST1, (tmp[3] << 24) | (tmp[2] << 16) | + (tmp[1] << 8) | tmp[0]); + + /* DBSCHRW1 */ + /* SCTRFCAB */ + tmp[0] = (priv->js2[JS2_tRFCab] + priv->js2[JS2_tZQLAT]) * + priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv; + dbsc5_reg_write(regs_dbsc_a + DBSC_DBSCHRW1, tmp[0]); + + /* DBSCHTR0 */ + /* SCDT0 */ + tmp[0] = (4 * priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv) - 1; + /* SCDT1 */ + tmp[1] = (8 * priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv) - 1; + /* SCDT2 */ + tmp[2] = (12 * priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv) - 1; + /* SCDT3 */ + tmp[3] = (16 * priv->bus_clk * priv->ddr_mbpsdiv * 8UL / + priv->ddr_mbps / priv->bus_clkdiv) - 1; + dbsc5_reg_write(regs_dbsc_a + DBSC_DBSCHTR0, (tmp[3] << 24) | (tmp[2] << 16) | + (tmp[1] << 8) | tmp[0]); + + /* QOS and CAM */ + dbsc5_reg_write(regs_dbsc_a + DBSC_DBBCAMDIS, 0x1); +} + +/** + * dbsc5_dbsc_regset_post() - Set DBSC registers + * @dev: DBSC5 device + * + * If memory rank is 2, CS_TRAINING_EN is set to the other side. + * Configure DBI read/write settings. Execute DRAM refresh settings. + * Set WTmode of DFI PHY to OFF. Set up PHY Periodic Write DQ training. + * Set WTmode of DFI PHY to ON. Calibration settings for PHY PAD. + * Set SDRAM calibration. Make DFI Control Update Setting settings. + * In the case of WARM_BOOT, cancel the self-refresh setting. + * Enable SDRAM auto refresh. Set up PHY Periodic Write DQ training. + * Enable access to SDRAM. + */ +static void dbsc5_dbsc_regset_post(struct udevice *dev) +{ + 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; + /* Average periodic refresh interval/Average Refresh Interval [ns] */ + const u32 dbsc_refint = 1920; + /* 0: Average interval is REFINT, 1: Average interval is 1/2 REFINT */ + const u32 dbsc_refints = 0; + /* Periodic-WriteDQ/ReadDQ Training Interval [us] */ + const u32 periodic_training_interval = 20000; + u32 phymster_req_interval; + u32 ch, slice; + u32 clk_count; + u32 refcycle; + u32 ctrl_clk; + u32 reg; + + if ((renesas_get_cpu_rev_integer() < 3) && priv->ch_have_this_cs[1]) { + r_foreach_vch(dev, ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + dbsc5_ddr_setval_slice(dev, ch, slice, + PHY_PER_CS_TRAINING_EN, + 0x0); + } + } + } + + dbsc5_reg_write(regs_dbsc_d + DBSC_DBDBICNT, 0x3); + + /* set REFCYCLE */ + refcycle = dbsc_refint * priv->ddr_mbps / 8000 / priv->ddr_mbpsdiv; + /* refpmax=8 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBRFCNF1, (refcycle & 0xFFFF) | BIT(19)); + /* refpmin=1 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBRFCNF2, dbsc_refints | BIT(16)); + + dbsc5_reg_write(regs_dbsc_d + DBSC_DBDFIPMSTRCNF, 0x0); + + /* Periodic-WriteDQ Training setting */ + dbsc5_ddr_setval_all_ch(dev, PI_WDQLVL_EN_F2, 0x3); + dbsc5_ddr_setval_all_ch(dev, PI_WDQLVL_VREF_EN, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_DATA_DC_WDQLVL_ENABLE, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_WDQLVL_PERIODIC, 0x1); + + /* Periodic-ReadDQ Training setting */ + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_EN_F2, 0x3); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_VREF_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDLVL_DLY_STEP, 0x4); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_PERIODIC, 0x1); + + /* DFI_PHYMSTR_ACK , WTmode = b'01 */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBDFIPMSTRCNF, 0x11); + + /* periodic SoC zqcal enable */ + reg = dbsc5_ddrtbl_getval(priv->DDR_PHY_ADR_G_REGSET, PHY_CAL_MODE_0, false); + dbsc5_ddr_setval_all_ch(dev, PHY_CAL_MODE_0, reg | BIT(1)); + + /* Periodic dram zqcal enable */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBCALCNF, 0x1000010); + + /* Periodic phy ctrl update enable */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBDFICUPDCNF, 0x504C0001); + + /* Set Auto Refresh */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBRFEN, 0x1); + + /* Periodic-WriteDQ/ReadDQ Training Interval setting */ + phymster_req_interval = periodic_training_interval - 3000; + clk_count = 1024 - (dbsc5_ddrtbl_getval(priv->DDR_PI_REGSET, PI_LONG_COUNT_MASK, true) * 32); + ctrl_clk = priv->ddr_mbps / priv->ddr_mbpsdiv / 8; + reg = phymster_req_interval * ctrl_clk / clk_count; + + dbsc5_ddr_setval_all_ch(dev, PI_WDQLVL_INTERVAL, reg); + + /* DRAM access enable */ + dbsc5_reg_write(regs_dbsc_a + DBSC_DBACEN, 0x1); +} + +/** + * dbsc5_pi_training() - Training by PI + * @dev: DBSC5 device + * + * Enable WCK signal training and read gate training. Start PI training. + * After DFI initialization for all channels is once turned off, turned + * on all chennels of it. Power down the DRAM device once and then release + * the power down mode. Perform training in low frequency mode and training + * in high frequency mode. Wait for the DFI training completion status + * bit to stand until the time limit. Turn off DFI initialization for all + * channels. Turn off WTMODE of DFI PHY. Check if CA/CS Training has failed. + * Check if Wrlvl training is in error. If an error can be confirmed from + * the check result, the result is returned as a return value. Clear the + * status register for PI training. + */ +static u32 dbsc5_pi_training(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; + const int retry_max = 0x10000; + u32 ca_training_ng = 0; + u32 wr_training_ng = 0; + u32 phytrainingok = 0; + u32 complete_ng = 0; + bool frqchg_req; + u32 ch, reg; + int retry; + int ret; + + /* Init start */ + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_GATE_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_WRDCM_LVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_WDQLVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_DFS_INITIALIZATION_SEQ_9, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_DFS_INITIALIZATION_SEQ_10, 0x0); + + /* PI_START */ + dbsc5_ddr_setval_all_ch(dev, PI_START, 0x1); + + r_foreach_vch(dev, ch) + writel(0x20, regs_dbsc_d + DBSC_DBDFICNT(ch)); + + r_foreach_vch(dev, ch) + writel(0x21, regs_dbsc_d + DBSC_DBDFICNT(ch)); + + /* Dummy PDE */ + dbsc5_send_dbcmd2(dev, 0x8840000); + + /* PDX */ + dbsc5_send_dbcmd2(dev, 0x8840001); + + /* Wait init_complete */ + for (retry = 0; retry < retry_max; retry++) { + frqchg_req = false; + for (ch = 0; ch < DRAM_CH_CNT; ch++) { + if (!((~phytrainingok & priv->ddr_phyvalid) & BIT(ch))) + continue; + + if (!(readl(regs_dbsc_d + DBSC_DBPDSTAT0(ch)) & BIT(0))) + continue; + + frqchg_req = true; + break; + } + + if (frqchg_req) { + ret = dbsc5_clk_pll3_freq(dev); + if (ret) + break; + } else { + r_foreach_vch(dev, ch) { + if (readl(regs_dbsc_d + DBSC_DBDFISTAT(ch)) & BIT(0)) + phytrainingok |= BIT(ch); + } + + if (phytrainingok == priv->ddr_phyvalid) + break; + } + } + + /* + * dbdficnt0: + * dfi_dram_clk_disable=0 + * dfi_frequency = 0 + * freq_ratio = 10 (4:1) + * init_start =0 + */ + r_foreach_vch(dev, ch) + writel(0x20, regs_dbsc_d + DBSC_DBDFICNT(ch)); + + /* DFI_PHYMSTR_ACK */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBDFIPMSTRCNF, 0x1); + + /* Error check */ + r_foreach_vch(dev, ch) { + /* CA/CS Training Error Check */ + /* PI_CALVL_ERROR_BIT */ + reg = dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(4); + /* Error on decrement/increment pass */ + reg |= dbsc5_ddr_getval(dev, ch, PHY_ADR_CALVL_OBS1) & (0x3 << 30); + /* Start outside of initial search range */ + reg |= dbsc5_ddr_getval(dev, ch, PHY_ADR_CALVL_OBS2) & (0x3 << 24); + /* CSlvl error */ + reg |= dbsc5_ddr_getval(dev, ch, PHY_CSLVL_OBS1) & (0xF << 28); + if (reg) { + ca_training_ng |= BIT(ch); + printf("%s pi_training_error:1\n", __func__); + } + + /* Wrlvl Error Check */ + /* PI_WRLVL_ERROR_BIT */ + reg = dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(3); + /* SLICE0 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 0, PHY_WRLVL_STATUS_OBS) & BIT(12); + /* SLICE1 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 1, PHY_WRLVL_STATUS_OBS) & BIT(12); + /* SLICE0 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 0, PHY_WRLVL_ERROR_OBS); + /* SLICE1 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 1, PHY_WRLVL_ERROR_OBS); + if (reg) { + wr_training_ng |= BIT(ch); + printf("%s pi_training_error:2\n", __func__); + } + } + + complete_ng = (wr_training_ng | ca_training_ng); + if (complete_ng) + return ~complete_ng; + + /* PI_INT_ACK assert */ + r_foreach_vch(dev, ch) { + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_0, 0xFFFFFFFF); + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_1, 0x7); + } + + return phytrainingok; +} + +/** + * dbsc5_write_leveling_adjust() - Write Leveling Cycle Adjust + * @dev: DBSC5 device + * + * Get delay value from the result write leveling of slice 0 and 1. + * Calculate latency of dfi_wrdata_en / dfi_wrdata / dfi_wrdata_mask + * signals based on delay values. + */ +static void dbsc5_write_leveling_adjust(struct udevice *dev) +{ + u32 result_hard0, result_hard1; + u32 avg, avg_frac, avg_cycle; + u32 ch; + + r_foreach_vch(dev, ch) { + /* SLICE0 */ + result_hard0 = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_WRLVL_HARD0_DELAY_OBS); + result_hard1 = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_WRLVL_HARD1_DELAY_OBS); + + avg = result_hard0 + result_hard1; + if (result_hard0 > result_hard1) + avg += 0x400; + avg /= 2; + + avg_frac = avg & 0xFF; + avg_cycle = (avg >> 8) & 0x3; + + if (avg_cycle == 0x3) { + dbsc5_ddr_setval_slice(dev, ch, 0, PHY_WRITE_PATH_LAT_DEC, 0x1); + dbsc5_ddr_setval_slice(dev, ch, 0, PHY_WRITE_PATH_LAT_ADD, 0x0); + } else { + dbsc5_ddr_setval_slice(dev, ch, 0, PHY_WRITE_PATH_LAT_DEC, 0x0); + dbsc5_ddr_setval_slice(dev, ch, 0, PHY_WRITE_PATH_LAT_ADD, avg_cycle); + } + dbsc5_ddr_setval_slice(dev, ch, 0, PHY_WRITE_PATH_LAT_FRAC, avg_frac); + + /* SLICE1 */ + result_hard0 = dbsc5_ddr_getval_slice(dev, ch, 1, PHY_WRLVL_HARD0_DELAY_OBS); + result_hard1 = dbsc5_ddr_getval_slice(dev, ch, 1, PHY_WRLVL_HARD1_DELAY_OBS); + + avg = result_hard0 + result_hard1; + if (result_hard0 >= result_hard1) + avg += 0x400; + avg /= 2; + avg_frac = avg & 0xFF; + avg_cycle = (avg >> 8) & 0x3; + + if (avg_cycle == 0x3) { + dbsc5_ddr_setval_slice(dev, ch, 1, PHY_WRITE_PATH_LAT_DEC, 0x1); + dbsc5_ddr_setval_slice(dev, ch, 1, PHY_WRITE_PATH_LAT_ADD, 0x0); + } else { + dbsc5_ddr_setval_slice(dev, ch, 1, PHY_WRITE_PATH_LAT_DEC, 0x0); + dbsc5_ddr_setval_slice(dev, ch, 1, PHY_WRITE_PATH_LAT_ADD, avg_cycle); + } + dbsc5_ddr_setval_slice(dev, ch, 1, PHY_WRITE_PATH_LAT_FRAC, avg_frac); + } + + dbsc5_ddr_setval_all_ch_all_slice(dev, SC_PHY_WCK_CALC, 0x1); +} + +/** + * dbsc5_wl_gt_training() - Re-run Write Leveling & Read Gate Training + * @dev: DBSC5 device + * + * Set CA leveling OFF, read gate leveling ON, write gate leveling ON, + * PI dram wck training ON. Perform PI_DFS configuration. Start PI + * frequency training in manual mode. Perform training in high-frequency + * mode. Check for Write leveling Error and Gate leveling Error. If an + * error is identified, the resulting value is inverted and returned. + * Clear the PI status register. + */ +static u32 dbsc5_wl_gt_training(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const int retry_max = 0x10000; + u32 gt_training_ng = 0; + u32 wr_training_ng = 0; + u32 phytrainingok = 0; + u32 complete_ng = 0; + int retry, ret; + u32 ch, reg; + + dbsc5_ddr_setval_all_ch(dev, PI_CALVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_GATE_EN_F2, 0x1); + + dbsc5_ddr_setval_all_ch(dev, PI_DFS_ENTRY_SEQ_0, 0x181F0000); + dbsc5_ddr_setval_all_ch(dev, PI_DFS_INITIALIZATION_SEQ_1, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_TRAIN_ALL_FREQ_REQ, 0x1); + + /* Freq Change High to High*/ + ret = dbsc5_clk_pll3_freq(dev); + if (ret) + return ret; + + for (retry = 0; retry < retry_max; retry++) { + r_foreach_vch(dev, ch) + if (dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(0)) + phytrainingok |= BIT(ch); + + if (phytrainingok == priv->ddr_phyvalid) + break; + } + + /* Error Check */ + r_foreach_vch(dev, ch) { + /* Wrlvl Error Check */ + /* PI_WRLVL_ERROR_BIT */ + reg = dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(3); + /* SLICE0 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 0, PHY_WRLVL_STATUS_OBS) & BIT(12); + /* SLICE1 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 1, PHY_WRLVL_STATUS_OBS) & BIT(12); + /* SLICE0 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 0, PHY_WRLVL_ERROR_OBS); + /* SLICE1 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 1, PHY_WRLVL_ERROR_OBS); + if (reg) { + wr_training_ng |= BIT(ch); + printf("%s wl_gt_training_error:1\n", __func__); + } + + /* Gtlvl Error Check */ + /* PI_RDLVL_GATE_ERROR_BIT */ + reg = dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(2); + /* SLICE0 delay setup error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 0, PHY_GTLVL_STATUS_OBS) & (0x3 << 7); + /* SLICE1 delay setup error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 1, PHY_GTLVL_STATUS_OBS) & (0x3 << 7); + if (reg) { + gt_training_ng |= BIT(ch); + printf("%s wl_gt_training_error:2\n", __func__); + } + } + + complete_ng = (wr_training_ng | gt_training_ng); + if (complete_ng) + return ~complete_ng; + + /* PI_INT_ACK assert */ + r_foreach_vch(dev, ch) { + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_0, 0xFFFFFFFF); + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_1, 0x7); + } + + return phytrainingok; +} + +/** + * dbsc5_pi_int_ack_0_assert() - Training handshake functions + * @dev: DBSC5 device + * @bit: Status bit to poll + * + * Wait for the status bit specified in the argument to become 1 until the + * time limit. After checking status bits on all channels, clear the target + * status bits and returns the result of the check as the return value. + */ +static u32 dbsc5_pi_int_ack_0_assert(struct udevice *dev, u32 bit) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const int retry_max = 0x10000; + u32 ch, phytrainingok = 0; + int retry; + + for (retry = 0; retry < retry_max; retry++) { + r_foreach_vch(dev, ch) + if (dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(bit)) + phytrainingok |= BIT(ch); + + if (phytrainingok == priv->ddr_phyvalid) + break; + } + + if (phytrainingok != priv->ddr_phyvalid) + return phytrainingok; + + r_foreach_vch(dev, ch) + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_0, BIT(bit)); + + return phytrainingok; +} + +/** + * dbsc5_write_dca() - Write DCA Training + * @dev: DBSC5 device + * + * Get DCA Training CS0 Flip-0 training results for RANK0. + * Get DCA Training CS1 Flip-0 training results for RANK0. + * Calculate DRAMDCA settings from training results and write + * them to registers. Set DRAM DCA in MR30. Ensure that the + * training has been successfully completed. Clear CA status + * to 0. + */ +static void dbsc5_write_dca(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const int retry_max = 0x10000; + u32 phytrainingok = 0; + u32 ch, reg; + int retry; + + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_DATA_DC_CAL_START, 0x1); + + for (retry = 0; retry < retry_max; retry++) { + r_foreach_vch(dev, ch) { + reg = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_DATA_DC_CAL_START) | + dbsc5_ddr_getval_slice(dev, ch, 1, PHY_DATA_DC_CAL_START); + if (!reg) + phytrainingok |= BIT(ch); + } + + if (phytrainingok == priv->ddr_phyvalid) + break; + } +} + +/** + * dbsc5_dramdca_training() - DRAM DCA Training and Calculations + * @dev: DBSC5 device + * + * Get DCA Training CS0 Flip-0 training results for RANK0. + * Get DCA Training CS1 Flip-0 training results for RANK0. + * Calculate DRAMDCA settings from training results and write + * them to registers. Set DRAM DCA in MR30. Ensure that the + * training has been successfully completed. Clear CA status + * to 0. + */ +static u32 dbsc5_dramdca_training(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const u32 rank = priv->ch_have_this_cs[1] ? 0x3 : 0x1; + const u32 mr30_conv[16] = { + 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, + 0x0, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF + }; + u32 dca_result_l_0[DRAM_CH_CNT][CS_CNT]; + u32 dca_result_u_0[DRAM_CH_CNT][CS_CNT]; + u32 dca_result_l_1[DRAM_CH_CNT][CS_CNT]; + u32 dca_result_u_1[DRAM_CH_CNT][CS_CNT]; + u32 ch, phytrainingok, reg; + u32 tempu, templ; + + /* Run DRAM DCA Training for Flip-0 */ + dbsc5_ddr_setval_all_ch(dev, PI_DCMLVL_CS_SW, rank); + + /* DRAMDCA go */ + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_REQ, 0x1); + + /* PI_INT_ACK assert */ + phytrainingok = dbsc5_pi_int_ack_0_assert(dev, 28); + if (phytrainingok != priv->ddr_phyvalid) + return phytrainingok; + + /* Result for DRAMDCA flip-0 */ + r_foreach_vch(dev, ch) { + reg = dbsc5_ddr_getval(dev, ch, PI_DARRAY3_20_CS0_F2); + dca_result_u_0[ch][0] = mr30_conv[reg >> 4]; + dca_result_l_0[ch][0] = mr30_conv[reg & 0xF]; + if (!(rank & 0x2)) + continue; + + reg = dbsc5_ddr_getval(dev, ch, PI_DARRAY3_20_CS1_F2); + dca_result_u_0[ch][1] = mr30_conv[reg >> 4]; + dca_result_l_0[ch][1] = mr30_conv[reg & 0xF]; + } + + /* Run DRAM DCA Training for Flip-1 */ + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_FLIP_MASK, 0x1); + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_ACTIVE_SEQ_2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_ACTIVE_SEQ_3, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_ACTIVE_SEQ_4, 0x0); + + /* DRAMDCA go */ + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_REQ, 0x1); + + /* PI_INT_ACK assert */ + phytrainingok = dbsc5_pi_int_ack_0_assert(dev, 28); + if (phytrainingok != priv->ddr_phyvalid) + return phytrainingok; + + /* Result for DRAMDCA flip-1 */ + r_foreach_vch(dev, ch) { + reg = dbsc5_ddr_getval(dev, ch, PI_DARRAY3_20_CS0_F2); + dca_result_u_1[ch][0] = mr30_conv[reg >> 4]; + dca_result_l_1[ch][0] = mr30_conv[reg & 0xF]; + if (!(rank & 0x2)) + continue; + + reg = dbsc5_ddr_getval(dev, ch, PI_DARRAY3_20_CS1_F2); + dca_result_u_1[ch][1] = mr30_conv[reg >> 4]; + dca_result_l_1[ch][1] = mr30_conv[reg & 0xF]; + } + + /* Calculate and set DRAMDCA value */ + r_foreach_vch(dev, ch) { + /* CS0 */ + tempu = (dca_result_u_0[ch][0] + dca_result_u_1[ch][0]) / 2; + templ = (dca_result_l_0[ch][0] + dca_result_l_1[ch][0]) / 2; + reg = (mr30_conv[tempu] << 4) | mr30_conv[templ]; + dbsc5_ddr_setval(dev, ch, PI_DARRAY3_20_CS0_F2, reg); + if (!(rank & 0x2)) + continue; + + /* CS1 */ + tempu = (dca_result_u_0[ch][1] + dca_result_u_1[ch][1]) / 2; + templ = (dca_result_l_0[ch][1] + dca_result_l_1[ch][1]) / 2; + reg = (mr30_conv[tempu] << 4) | mr30_conv[templ]; + dbsc5_ddr_setval(dev, ch, PI_DARRAY3_20_CS1_F2, reg); + } + + /* Set DRAMDCA value in MR30 */ + dbsc5_ddr_setval_all_ch(dev, PI_SW_SEQ_0, 0x1A11E14); + dbsc5_ddr_setval_all_ch(dev, PI_SW_SEQ_1, 0x1F0000); + dbsc5_ddr_setval_all_ch(dev, PI_SEQ_DEC_SW_CS, rank); + dbsc5_ddr_setval_all_ch(dev, PI_SW_SEQ_START, 0x1); + + /* PI_INT_ACK assert */ + phytrainingok = dbsc5_pi_int_ack_0_assert(dev, 19); + if (phytrainingok != priv->ddr_phyvalid) + return phytrainingok; + + dbsc5_ddr_setval_all_ch(dev, PI_SEQ_DEC_SW_CS, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_FLIP_MASK, 0x2); + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_ACTIVE_SEQ_2, 0x1101FC); + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_ACTIVE_SEQ_3, 0x211A00); + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_ACTIVE_SEQ_4, 0x51500); + + return phytrainingok; +} + +/** + * dbsc5_write_leveling() - Re-run Write Leveling + * @dev: DBSC5 device + * + * CALVL training is set to OFF, WRDCM training is set to OFF, and DRAMDCA + * training is set to OFF. Set the memory rank for the Write leveling target + * and start leveling. Wait until leveling is complete. + * + * Check for Write leveling errors. If an error is confirmed to have occurred, + * the result is returned as a return value. Clear the PI status bit. + */ +static u32 dbsc5_write_leveling(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const u32 rank = priv->ch_have_this_cs[1] ? 0x3 : 0x1; + const int retry_max = 0x10000; + u32 wr_training_ng = 0; + u32 phytrainingok = 0; + u32 ch, reg; + int retry; + + dbsc5_ddr_setval_all_ch(dev, PI_CALVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_WRDCM_LVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_DRAMDCA_LVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_WRLVL_CS_SW, rank); + dbsc5_ddr_setval_all_ch(dev, PI_WRLVL_REQ, 0x1); + + for (retry = 0; retry < retry_max; retry++) { + r_foreach_vch(dev, ch) + if (dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(29)) + phytrainingok |= BIT(ch); + + if (phytrainingok == priv->ddr_phyvalid) + break; + } + + /* Error check */ + r_foreach_vch(dev, ch) { + /* Wrlvl Error Check */ + /* PI_WRLVL_ERROR_BIT */ + reg = dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(3); + /* SLICE0 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 0, PHY_WRLVL_STATUS_OBS) & BIT(12); + /* SLICE1 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 1, PHY_WRLVL_STATUS_OBS) & BIT(12); + /* SLICE0 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 0, PHY_WRLVL_ERROR_OBS); + /* SLICE1 wrlvl error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 1, PHY_WRLVL_ERROR_OBS); + if (reg) { + wr_training_ng |= BIT(ch); + printf("%s write_leveling_error:1\n", __func__); + } + } + + if (wr_training_ng) + return ~wr_training_ng; + + /* PI_INT_ACK assert */ + r_foreach_vch(dev, ch) { + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_0, 0xFFFFFFFF); + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_1, 0x7); + } + + return phytrainingok; +} + +/** + * dbsc5_manual_write_dca() - Manual Write DCA Training + * @dev: DBSC5 device + * + * Write DCA training according to memory rank. + */ +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 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; + const int retry_max = 0x10000; + const u8 ratio_min_div = 0xA; + const u8 ratio_max_div = 0x2; + const u8 ratio_min = 0x6; + const u8 ratio_max = 0x3; + u32 ch, cs, slice, tmp; + u32 complete = 0; + int i, retry; + + r_foreach_vch(dev, ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + phy_dcc_code_min[ch][slice] = 0x7F; + phy_dcc_code_max[ch][slice] = 0x0; + } + } + + for (cs = 0; cs < rank; cs++) { + 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; + } + } + } + + 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]; + } 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]; + } + } + } + + for (i = 0; i <= 0x7F; i++) { + r_foreach_vch(dev, ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + if (slv_dly_max[ch][slice] < (slv_dly_min[ch][slice] + i)) { + complete |= BIT(ch) << (8 * slice); + } else { + /* CS0/1 same setting, Need masked write */ + dbsc5_ddr_setval_slice(dev, ch, slice, + PHY_CLK_WRDQS_SLAVE_DELAY, + slv_dly_min[ch][slice] + i); + dbsc5_ddr_setval_slice(dev, ch, slice, SC_PHY_WCK_CALC, 0x1); + dbsc5_ddr_setval(dev, ch, SC_PHY_MANUAL_UPDATE, 0x1); + } + } + } + + if (complete == (priv->ddr_phyvalid | (priv->ddr_phyvalid << 8))) + break; + + /* Execute write dca */ + r_foreach_vch(dev, ch) + for (slice = 0; slice < SLICE_CNT; slice++) + if (!(((complete >> (8 * slice)) >> ch) & 0x1)) + dbsc5_ddr_setval_slice(dev, ch, slice, PHY_DATA_DC_CAL_START, 0x1); + + r_foreach_vch(dev, ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + if (!(((complete >> (8 * slice)) >> ch) & 0x1)) { + for (retry = 0; retry < retry_max; retry++) { + tmp = dbsc5_ddr_getval_slice(dev, ch, slice, + PHY_DATA_DC_CAL_START); + if (!tmp) + break; + } + } + } + } + + r_foreach_vch(dev, ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + if ((slv_dly_min[ch][slice] + i) > slv_dly_max[ch][slice]) + continue; + + tmp = (dbsc5_ddr_getval_slice(dev, ch, slice, PHY_DATA_DC_DQS_CLK_ADJUST)); + if ((tmp >> 6) == 0x1) + tmp = 0x0; + else if ((tmp >> 6) == 0x2) + tmp = 0x3F; + + if (tmp < phy_dcc_code_min[ch][slice]) + phy_dcc_code_min[ch][slice] = tmp; + + if (phy_dcc_code_max[ch][slice] < tmp) + phy_dcc_code_max[ch][slice] = tmp; + } + } + } + + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_PER_CS_TRAINING_MULTICAST_EN, 0x0); + for (cs = 0; cs < rank; cs++) { + 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++) { + dbsc5_ddr_setval_slice(dev, ch, slice, + PHY_CLK_WRDQS_SLAVE_DELAY, + slv_dly_center[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_PER_CS_TRAINING_MULTICAST_EN, 0x1); + + r_foreach_vch(dev, ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + phy_dcc_code_mid = (phy_dcc_code_min[ch][slice] + + phy_dcc_code_max[ch][slice]) / 2; + dbsc5_ddr_setval_slice(dev, ch, slice, + PHY_DATA_DC_DQS_CLK_ADJUST, + phy_dcc_code_mid); + } + } +} + +/** + * dbsc5_read_gate_training() - Re-run read gate training by PI + * @dev: DBSC5 device + * + * Write leveling set to OFF, read gate leveling set to ON. Set memory rank + * for leveling target, turn on read gate leveling. Wait for leveling to be + * completed until the time limit. Check for errors during gate leveling. + * + * If an error is confirmed to have occurred, the result is returned as a + * return value. Clear the PI status register. + */ +static u32 dbsc5_read_gate_training(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const u32 rank = priv->ch_have_this_cs[1] ? 0x3 : 0x1; + const int retry_max = 0x10000; + u32 gt_training_ng = 0; + u32 phytrainingok = 0; + u32 ch, reg; + int retry; + + dbsc5_ddr_setval_all_ch(dev, PI_WRLVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_GATE_EN_F2, 0x1); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_CS_SW, rank); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_GATE_REQ, 0x1); + + for (retry = 0; retry < retry_max; retry++) { + r_foreach_vch(dev, ch) + if (dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(24)) + phytrainingok |= BIT(ch); + + if (phytrainingok == priv->ddr_phyvalid) + break; + } + + /* Error Check */ + r_foreach_vch(dev, ch) { + /* Gtlvl Error Check */ + /* PI_RDLVL_GATE_ERROR_BIT */ + reg = (dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(2)); + /* SLICE0 delay setup error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 0, PHY_GTLVL_STATUS_OBS) & (0x3 << 7); + /* SLICE1 delay setup error */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 1, PHY_GTLVL_STATUS_OBS) & (0x3 << 7); + if (reg) { + gt_training_ng |= BIT(ch); + printf("%s read_gate_training_error\n", __func__); + } + } + + if (gt_training_ng) + return ~gt_training_ng; + + /* PI_INT_ACK assert */ + r_foreach_vch(dev, ch) { + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_0, 0xFFFFFFFF); + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_1, 0x7); + } + + return phytrainingok; +} + +/** + * dbsc5_read_vref_training() - Read Data Training with VREF Training + * @dev: DBSC5 device + * + * Set reading leveling to ON and Vref leveling of reading to OFF. + * Set Vref reading training to OFF. Get start value, end value and + * number of steps for Vref training. Determine the optimal VREFSEL + * value while increasing the Vref training setpoint by the starting + * value+step value. + */ +static u32 dbsc5_read_vref_training(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const u32 rank = priv->ch_have_this_cs[1] ? 0x3 : 0x1; + u32 best_dvw_min_byte0, best_dvw_min_byte1; + u32 dvw_min_byte0_table[DRAM_CH_CNT][128]; + u32 dvw_min_byte1_table[DRAM_CH_CNT][128]; + u32 dvw_min_byte0[DRAM_CH_CNT] = { 0 }; + u32 dvw_min_byte1[DRAM_CH_CNT] = { 0 }; + u32 best_lower_vref, best_upper_vref; + u32 best_vref_byte0, best_vref_byte1; + u32 vref_start, vref_stop, vref_step; + u32 best_vref_byte0_index = 0; + u32 best_vref_byte1_index = 0; + const int retry_max = 0x10000; + u32 win_byte0, win_byte1; + u32 phytrainingok = 0; + u32 vref_stop_index; + u32 temple, tempte; + u32 best_thrshld; + u32 vref_outlier; + u32 outlier_cnt; + u32 curr_rank; + int i, retry; + u32 obs_sel; + u32 ch, reg; + + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_EN_F2, 0x3); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_VREF_EN_F0, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_VREF_EN_F1, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_VREF_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_VREF_TRAINING_CTRL, 0x0); + + /* ch0 vref_point */ + vref_start = dbsc5_ddr_getval(dev, 0, PHY_VREF_INITIAL_START_POINT); + vref_stop = dbsc5_ddr_getval(dev, 0, PHY_VREF_INITIAL_STOP_POINT); + vref_step = dbsc5_ddr_getval(dev, 0, PHY_VREF_INITIAL_STEPSIZE); + vref_stop_index = (vref_stop - vref_start) / vref_step; + + if (vref_stop_index > 0x80) + return 0; + + for (i = 0; i <= vref_stop_index; i++) { + r_foreach_vch(dev, ch) { + reg = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_PAD_VREF_CTRL_DQ); + reg &= 0xF << 10; + dbsc5_ddr_setval_slice(dev, ch, 0, PHY_PAD_VREF_CTRL_DQ, + reg | BIT(9) | (vref_start + (vref_step * i))); + reg = dbsc5_ddr_getval_slice(dev, ch, 1, PHY_PAD_VREF_CTRL_DQ); + reg &= 0xF << 10; + dbsc5_ddr_setval_slice(dev, ch, 1, PHY_PAD_VREF_CTRL_DQ, + reg | BIT(9) | (vref_start + (vref_step * i))); + } + + for (curr_rank = 0; curr_rank < rank; curr_rank++) { + /* All ch Read Training Start */ + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_CS_SW, BIT(curr_rank)); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_REQ, 0x1); + + phytrainingok = 0; + for (retry = 0; retry < retry_max; retry++) { + r_foreach_vch(dev, ch) + if (dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(25)) + phytrainingok |= BIT(ch); + + if (phytrainingok == priv->ddr_phyvalid) + break; + } + + /* Read Training End */ + dbsc5_ddr_setval_all_ch(dev, PI_INT_ACK_0, BIT(25)); + + r_foreach_vch(dev, ch) { + /* minimum Data Valid Window for each VREF */ + dvw_min_byte0[ch] = 0xFFFFFFFF; + dvw_min_byte1[ch] = 0xFFFFFFFF; + for (obs_sel = 0x0; obs_sel < 0x19; obs_sel++) { + if (!((obs_sel < 0x11) || (obs_sel == 0x18))) + continue; + + dbsc5_ddr_setval_slice(dev, ch, 0, + PHY_RDLVL_RDDQS_DQ_OBS_SELECT, + obs_sel); + dbsc5_ddr_setval_slice(dev, ch, 1, + PHY_RDLVL_RDDQS_DQ_OBS_SELECT, + obs_sel); + + temple = dbsc5_ddr_getval_slice(dev, ch, 0, + PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS); + tempte = dbsc5_ddr_getval_slice(dev, ch, 0, + PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS); + if (tempte > temple) + win_byte0 = tempte - temple; + else + win_byte0 = 0; + + temple = dbsc5_ddr_getval_slice(dev, ch, 1, + PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS); + tempte = dbsc5_ddr_getval_slice(dev, ch, 1, + PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS); + if (tempte > temple) + win_byte1 = tempte - temple; + else + win_byte1 = 0; + + if (dvw_min_byte0[ch] > win_byte0) + dvw_min_byte0[ch] = win_byte0; + + if (dvw_min_byte1[ch] > win_byte1) + dvw_min_byte1[ch] = win_byte1; + } + } + } + + r_foreach_vch(dev, ch) { + dvw_min_byte0_table[ch][i] = dvw_min_byte0[ch]; + dvw_min_byte1_table[ch][i] = dvw_min_byte1[ch]; + } + } + + r_foreach_vch(dev, ch) { + /* Search best VREF byte0 */ + best_vref_byte0 = vref_start; + best_vref_byte0_index = 0; + best_dvw_min_byte0 = dvw_min_byte0_table[ch][0]; + + for (i = 0; i <= vref_stop_index; i++) { + if (best_dvw_min_byte0 >= dvw_min_byte0_table[ch][i]) + continue; + + best_vref_byte0 = vref_start + (vref_step * i); + best_vref_byte0_index = i; + best_dvw_min_byte0 = dvw_min_byte0_table[ch][i]; + } + + /* Search best_lower VREF byte0 */ + reg = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_RDLVL_DLY_STEP); + if (reg == 0) + reg = 1; + best_thrshld = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_RDLVL_BEST_THRSHLD) * reg; + + vref_outlier = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_RDLVL_VREF_OUTLIER); + best_lower_vref = best_vref_byte0; + outlier_cnt = vref_outlier; + for (i = best_vref_byte0_index; i >= 0; i--) { + if (dvw_min_byte0_table[ch][i] <= 0) + break; + + if (dvw_min_byte0_table[ch][i] >= (best_dvw_min_byte0 - best_thrshld)) { + best_lower_vref = vref_start + (vref_step * i); + } else { + if (outlier_cnt > 0) + outlier_cnt--; + else + break; + } + + if (i == 0) + break; + } + + /* Search best_upper VREF byte0 */ + vref_outlier = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_RDLVL_VREF_OUTLIER); + best_upper_vref = best_vref_byte0; + outlier_cnt = vref_outlier; + for (i = best_vref_byte0_index; i <= vref_stop_index; i++) { + if (dvw_min_byte0_table[ch][i] <= 0) + break; + + if (dvw_min_byte0_table[ch][i] >= (best_dvw_min_byte0 - best_thrshld)) { + best_upper_vref = vref_start + (vref_step * i); + } else { + if (outlier_cnt > 0) + outlier_cnt--; + else + break; + } + } + + /* Calculate center of best vref range byte0 */ + best_vref_byte0 = (best_lower_vref + best_upper_vref) / 2; + + /* Search best VREF byte1 */ + best_vref_byte1 = vref_start; + best_vref_byte1_index = 0; + best_dvw_min_byte1 = dvw_min_byte1_table[ch][0]; + for (i = 0; i <= vref_stop_index; i++) { + if (best_dvw_min_byte1 >= dvw_min_byte1_table[ch][i]) + continue; + + best_vref_byte1 = vref_start + (vref_step * i); + best_vref_byte1_index = i; + best_dvw_min_byte1 = dvw_min_byte1_table[ch][i]; + } + + /* Search best_lower VREF byte1 */ + reg = dbsc5_ddr_getval_slice(dev, ch, 1, PHY_RDLVL_DLY_STEP); + if (reg == 0) + reg = 1; + best_thrshld = dbsc5_ddr_getval_slice(dev, ch, 1, PHY_RDLVL_BEST_THRSHLD) * reg; + + vref_outlier = dbsc5_ddr_getval_slice(dev, ch, 1, PHY_RDLVL_VREF_OUTLIER); + best_lower_vref = best_vref_byte1; + outlier_cnt = vref_outlier; + for (i = best_vref_byte1_index; i >= 0; i--) { + if (dvw_min_byte1_table[ch][i] <= 0) + break; + + if (dvw_min_byte1_table[ch][i] >= (best_dvw_min_byte1 - best_thrshld)) { + best_lower_vref = vref_start + (vref_step * i); + } else { + if (outlier_cnt > 0) + outlier_cnt--; + else + break; + } + + if (i == 0) + break; + } + + /* Search best_upper VREF byte1 */ + vref_outlier = dbsc5_ddr_getval_slice(dev, ch, 1, PHY_RDLVL_VREF_OUTLIER); + best_upper_vref = best_vref_byte1; + outlier_cnt = vref_outlier; + for (i = best_vref_byte1_index; i <= vref_stop_index; i++) { + if (dvw_min_byte1_table[ch][i] <= 0) + break; + + if (dvw_min_byte1_table[ch][i] >= (best_dvw_min_byte1 - best_thrshld)) { + best_upper_vref = vref_start + (vref_step * i); + } else { + if (outlier_cnt > 0) + outlier_cnt--; + else + break; + } + } + + /* Calculate center of best vref range byte1 */ + best_vref_byte1 = (best_lower_vref + best_upper_vref) / 2; + + reg = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_PAD_VREF_CTRL_DQ); + reg &= 0xF << 10; + dbsc5_ddr_setval_slice(dev, ch, 0, PHY_PAD_VREF_CTRL_DQ, + reg | BIT(9) | best_vref_byte0); + reg = dbsc5_ddr_getval_slice(dev, ch, 1, PHY_PAD_VREF_CTRL_DQ); + reg &= 0xF << 10; + dbsc5_ddr_setval_slice(dev, ch, 1, PHY_PAD_VREF_CTRL_DQ, + reg | BIT(9) | best_vref_byte1); + } + + return phytrainingok; +} + +/** + * dbsc5_read_write_training() - Read Data & RDDQ Training with best VREF & Write DQ VREF Training + * @dev: DBSC5 device + * + * Set read DQS/RDQS slave delay setting to 0. Write leveling set to OFF, + * read gate leveling set to OFF. Turn on read and write leveling. Start + * frequency training. Training in high-frequency mode. Wait until training + * is complete. Check for errors in write dq leveling and read leveling. + + * If an error is confirmed to have occurred, return the inverted result + * value. Clear the PI status register. + */ +static u32 dbsc5_read_write_training(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const int retry_max = 0x10000; + u32 wdq_training_ng = 0; + u32 rd_training_ng = 0; + u32 phytrainingok = 0; + u32 complete_ng = 0; + int retry, ret; + u32 ch, reg; + + /* RDDQ_SLAVE_DELAY Set 0x0050 -> 0x0000 */ + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDDQ0_SLAVE_DELAY, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDDQ1_SLAVE_DELAY, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDDQ2_SLAVE_DELAY, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDDQ3_SLAVE_DELAY, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDDQ4_SLAVE_DELAY, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDDQ5_SLAVE_DELAY, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDDQ6_SLAVE_DELAY, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDDQ7_SLAVE_DELAY, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_RDDM_SLAVE_DELAY, 0x0); + + dbsc5_ddr_setval_all_ch(dev, PI_WRLVL_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_GATE_EN_F2, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_EN_F2, 0x3); + dbsc5_ddr_setval_all_ch(dev, PI_WDQLVL_EN_F2, 0x3); + + dbsc5_ddr_setval_all_ch(dev, PI_TRAIN_ALL_FREQ_REQ, 0x1); + + /* Freq Change High to High*/ + ret = dbsc5_clk_pll3_freq(dev); + if (ret) + return ret; + + for (retry = 0; retry < retry_max; retry++) { + r_foreach_vch(dev, ch) + if (dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(0)) + phytrainingok |= BIT(ch); + + if (phytrainingok == priv->ddr_phyvalid) + break; + } + + /* Error Check */ + r_foreach_vch(dev, ch) { + /* Rdlvl Error Check */ + /* PI_RDLVL_ERROR_BIT */ + reg = dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(1); + if (reg) { + rd_training_ng |= BIT(ch); + printf("%s read_write_training_error:1\n", __func__); + } + + /* Wdqlvl Error Check */ + /* PI_WDQLVL_ERROR_BIT */ + reg = dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(5); + /* SLICE0 wdqlvl_fail_dqZ */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 0, PHY_WDQLVL_STATUS_OBS) & (0x1FF << 18); + /* SLICE1 wdqlvl_fail_dqZ */ + reg |= dbsc5_ddr_getval_slice(dev, ch, 1, PHY_WDQLVL_STATUS_OBS) & (0x1FF << 18); + if (reg) { + wdq_training_ng |= BIT(ch); + printf("%s read_write_training_error:2\n", __func__); + } + } + + complete_ng = wdq_training_ng | rd_training_ng; + if (complete_ng) + return ~complete_ng; + + /* PI_INT_ACK assert */ + r_foreach_vch(dev, ch) { + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_0, 0xFFFFFFFF); + dbsc5_ddr_setval(dev, ch, PI_INT_ACK_1, 0x7); + } + + return phytrainingok; +} + +/** + * dbsc5_read_training() - Correct RDDQ Training result & Re-Run Read Data Training + * @dev: DBSC5 device + * + * Set the Read DQ correction value and its upper limit from the board + * settings. Check DDR memory ranks. Add the offset value to the current + * Read DQ value and write it to the register. Write the setting value + * to PI_RDLVL_TRAIN_SEQ_x. Start the Read training. PI_INT_ACK assert. + * Execute the Rdlvl Error Check. Confirm that training has been successfully + * completed. Return the result of the confirmation as the return value. + */ +static u32 dbsc5_read_training(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + const u32 rank = priv->ch_have_this_cs[1] ? 0x3 : 0x1; + const u32 rddq_delay_offset_ps = 0x19; + const u32 rddq_delay_max_ps = 0x67; + const u32 rddq_delay_addr[] = { + PHY_RDDQ0_SLAVE_DELAY, PHY_RDDQ1_SLAVE_DELAY, PHY_RDDQ2_SLAVE_DELAY, + PHY_RDDQ3_SLAVE_DELAY, PHY_RDDQ4_SLAVE_DELAY, PHY_RDDQ5_SLAVE_DELAY, + PHY_RDDQ6_SLAVE_DELAY, PHY_RDDQ7_SLAVE_DELAY, PHY_RDDM_SLAVE_DELAY + }; + const u32 rddq_delay_offset = rddq_delay_offset_ps * priv->ddr_mbps * 256 / + (priv->ddr_mbpsdiv * 2 * 1000000); + const u32 rddq_delay_max = rddq_delay_max_ps * priv->ddr_mbps * 256 / + (priv->ddr_mbpsdiv * 2 * 1000000); + u32 rd_training_ng = 0; + u32 ch, reg, slice; + u32 phytrainingok; + int i; + + r_foreach_vch(dev, ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (i = 0; i < 9; i++) { + reg = dbsc5_ddr_getval_slice(dev, ch, slice, + rddq_delay_addr[i]) + + rddq_delay_offset; + if (reg > rddq_delay_max) + reg = rddq_delay_max; + dbsc5_ddr_setval_slice(dev, ch, slice, rddq_delay_addr[i], reg); + } + } + } + + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_TRAIN_SEQ_1, 0x89080); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_TRAIN_SEQ_2, 0x811C0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_TRAIN_SEQ_3, 0x40811C0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_TRAIN_SEQ_4, 0x2000000); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_TRAIN_SEQ_5, 0x0); + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_CS_SW, rank); + + /* Read training go */ + dbsc5_ddr_setval_all_ch(dev, PI_RDLVL_REQ, 0x1); + + /* PI_INT_ACK assert */ + phytrainingok = dbsc5_pi_int_ack_0_assert(dev, 25); + if (phytrainingok != priv->ddr_phyvalid) + return phytrainingok; + + /* Error Check */ + r_foreach_vch(dev, ch) { + /* Rdlvl Error Check */ + /* PI_RDLVL_ERROR_BIT */ + reg = dbsc5_ddr_getval(dev, ch, PI_INT_STATUS) & BIT(1); + if (reg) { + rd_training_ng |= BIT(ch); + printf("%s read_training_error\n", __func__); + } + } + + if (rd_training_ng) + return ~rd_training_ng; + + return phytrainingok; +} + +/** + * dbsc5_ddr_register_set() - DDR mode register setting + * @dev: DBSC5 device + * + * Set the mode register 28 of the SDRAM. + * ZQ Mode: Command-Based ZQ Calibration + * ZQ interval: Background Cal Interval < 64ms + */ +static void dbsc5_ddr_register_set(struct udevice *dev) +{ + dbsc5_send_dbcmd2(dev, 0xE841C24); +} + +/** + * dbsc5_ddr_register_read() - DDR mode register read + * @dev: DBSC5 device + * + * Set the mode register 27 and 57 of the SDRAM. + */ +static void dbsc5_ddr_register_read(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + + if (!priv->dbsc5_board_config->bdcfg_rfm_chk) + return; + + /* MR27 rank0 */ + dbsc5_send_dbcmd2(dev, 0xF801B00); + /* MR57 rank0 */ + dbsc5_send_dbcmd2(dev, 0xF803900); + + if (!priv->ch_have_this_cs[1]) + return; + + /* MR27 rank1 */ + dbsc5_send_dbcmd2(dev, 0xF811B00); + /* MR57 rank1 */ + dbsc5_send_dbcmd2(dev, 0xF813900); +} + +/** + * dbsc5_init_ddr() - Initialize DDR + * @dev: DBSC5 device + * + * Status monitor and perform reset and software reset for DDR. + * Disable DDRPHY software reset. Unprotect the DDRPHY register. + * Perform pre-setting of DBSC registers. Configure the ddrphy + * registers. Process ddr backup. Set DBSC registers. + * + * Initialize DFI and perform PI training. Setup DDR mode registers + * pre-traning. Adjust number of write leveling cycles. Perform PI + * training in manual mode. Perform DRAM DCA training. Perform write + * leveling. Execute phydca training. Execute read gate training. + * + * Perform Vref training on read gate. Read DQ Write DQ Execute. + * Frequency selection change (F1->F2). Disable the FREQ_SEL_MULTICAST & + * PER_CS_TRAINING_MULTICAST. Start setting DDR mode registers. Set DBSC + * registers after training is completed. Set write protection for PHY + * registers. + */ +static u32 dbsc5_init_ddr(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; + u32 phytrainingok; + u32 ch, val; + int ret; + + /* PLL3 initialization setting */ + /* Reset Status Monitor clear */ + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_FSRCHKCLRR4, 0x600); + /* Reset Status Monitor set */ + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_FSRCHKSETR4, 0x600); + /* ddrphy soft reset assert */ + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_SRCR4, readl(priv->cpg_regs + CPG_SRCR4) | 0x600); + /* Wait reset FB */ + ret = readl_poll_timeout(priv->cpg_regs + CPG_FSRCHKRA4, val, ((val & 0x600) == 0), 1000000); + if (ret < 0) { + printf("%s CPG_FSRCHKRA4 Wait reset FB timeout\n", __func__); + hang(); + } + /* Reset Status Monitor clear */ + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_FSRCHKCLRR4, 0x600); + + /* Initialize PLL3 setting */ + dbsc5_clk_pll3_control(dev, PLL3_HIGH_FREQUENCY_MODE_LOAD_REGISTER); + + /* DDRPHY soft reset negate */ + dbsc5_clk_cpg_write_32(dev, priv->cpg_regs + CPG_SRSTCLR4, 0x600); + ret = readl_poll_timeout(priv->cpg_regs + CPG_SRCR4, val, ((val & 0x600) == 0), 1000000); + if (ret < 0) { + printf("%s CPG_SRCR4 DDRPHY soft reset negate timeout\n", __func__); + hang(); + } + + /* Unlock PHY */ + /* Unlock DDRPHY register */ + r_foreach_vch(dev, ch) + writel(0xA55A, regs_dbsc_d + DBSC_DBPDLK(ch)); + + /* DBSC register pre-setting */ + dbsc5_dbsc_regset_pre(dev); + + /* Load DDRPHY registers */ + dbsc5_ddrtbl_calc(priv); + dbsc5_ddrtbl_load(dev); + + /* Configure ddrphy registers */ + dbsc5_ddr_config(dev); + + /* DDR backupmode end */ + + /* DBSC register set */ + dbsc5_dbsc_regset(dev); + + /* Frequency selection change (F1->F2) */ + dbsc5_ddr_setval_all_ch(dev, PHY_FREQ_SEL_INDEX, 0x1); + dbsc5_ddr_setval_all_ch(dev, PHY_FREQ_SEL_MULTICAST_EN, 0x0); + + /* dfi_init_start (start ddrphy) & execute pi_training */ + phytrainingok = dbsc5_pi_training(dev); + if (priv->ddr_phyvalid != phytrainingok) { + printf("%s init_ddr_error:1\n", __func__); + return phytrainingok; + } + + /* Write leveling cycle adjust */ + dbsc5_write_leveling_adjust(dev); + + /* Execute write leveling & read gate training */ + phytrainingok = dbsc5_wl_gt_training(dev); + if (priv->ddr_phyvalid != phytrainingok) { + printf("%s init_ddr_error:2\n", __func__); + return phytrainingok; + } + + /* Execute write dca training */ + dbsc5_write_dca(dev); + + /* Execute dram dca training */ + phytrainingok = dbsc5_dramdca_training(dev); + + if (priv->ddr_phyvalid != phytrainingok) { + printf("%s init_ddr_error:3\n", __func__); + return phytrainingok; + } + + /* Execute write leveling */ + phytrainingok = dbsc5_write_leveling(dev); + + if (priv->ddr_phyvalid != phytrainingok) { + printf("%s init_ddr_error:4\n", __func__); + return phytrainingok; + } + + /* Execute manual write dca training */ + dbsc5_manual_write_dca(dev); + + /* Execute read gate training */ + phytrainingok = dbsc5_read_gate_training(dev); + + if (priv->ddr_phyvalid != phytrainingok) { + printf("%s init_ddr_error:5\n", __func__); + return phytrainingok; + } + + /* Execute read vref training */ + phytrainingok = dbsc5_read_vref_training(dev); + + if (priv->ddr_phyvalid != phytrainingok) { + printf("%s init_ddr_error:6\n", __func__); + return phytrainingok; + } + + /* Execute read dq & write dq training with best vref */ + phytrainingok = dbsc5_read_write_training(dev); + if (priv->ddr_phyvalid != phytrainingok) { + printf("%s init_ddr_error:7\n", __func__); + return phytrainingok; + } + + /* correct rddq training result & Execute read dq training */ + phytrainingok = dbsc5_read_training(dev); + + if (priv->ddr_phyvalid != phytrainingok) { + printf("%s init_ddr_error:8\n", __func__); + return phytrainingok; + } + + /* PER_CS_TRAINING_MULTICAST SET (disable) */ + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_PER_CS_TRAINING_MULTICAST_EN, 0x0); + + /* setup DDR mode registers */ + /* MRS */ + dbsc5_ddr_register_set(dev); + + /* MRR */ + dbsc5_ddr_register_read(dev); + + /* training complete, setup DBSC */ + dbsc5_dbsc_regset_post(dev); + + /* Lock PHY */ + /* Lock DDRPHY register */ + r_foreach_vch(dev, ch) + writel(0x0, regs_dbsc_d + DBSC_DBPDLK(ch)); + + return phytrainingok; +} + +/** + * dbsc5_get_board_data() - Obtain board specific DRAM configuration + * + * Return board specific DRAM configuration structure pointer. + */ +__weak const struct renesas_dbsc5_board_config *dbsc5_get_board_data(void) +{ + return &renesas_v4h_dbsc5_board_config; +} + +/** + * renesas_dbsc5_dram_probe() - DDR Initialize entry + * @dev: DBSC5 device + * + * Remove write protection on DBSC register. Read DDR configuration + * information from driver data. Calculate board clock frequency and + * operating frequency from DDR configuration information. Call the + * main function of DDR initialization. Perform DBSC write protection + * after initialization is complete. + */ +static int renesas_dbsc5_dram_probe(struct udevice *dev) +{ +#define RST_MODEMR0 0x0 +#define RST_MODEMR1 0x4 + 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); + 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; + u32 ch, cs; + + /* Get board data */ + priv->dbsc5_board_config = dbsc5_get_board_data(); + priv->ddr_phyvalid = (u32)(priv->dbsc5_board_config->bdcfg_phyvalid); + priv->max_density = 0; + priv->cpg_regs = (void __iomem *)ofnode_get_addr(cnode); + + for (cs = 0; cs < CS_CNT; cs++) + priv->ch_have_this_cs[cs] = 0; + + r_foreach_ech(ch) + for (cs = 0; cs < CS_CNT; cs++) + priv->ddr_density[ch][cs] = 0xFF; + + r_foreach_vch(dev, ch) { + for (cs = 0; cs < CS_CNT; cs++) { + priv->ddr_density[ch][cs] = priv->dbsc5_board_config->ch[ch].bdcfg_ddr_density[cs]; + + if (priv->ddr_density[ch][cs] == 0xFF) + continue; + + if (priv->ddr_density[ch][cs] > priv->max_density) + priv->max_density = priv->ddr_density[ch][cs]; + + priv->ch_have_this_cs[cs] |= BIT(ch); + } + } + + /* Decode board clock frequency from MD[14:13] pins */ + priv->brd_clkdiv = 3; + + breg = (modemr0 >> 13) & 0x3; + if (breg == 0) { + priv->brd_clk = 50; /* 16.66 MHz */ + priv->bus_clk = priv->brd_clk * 0x18; + priv->bus_clkdiv = priv->brd_clkdiv; + } else if (breg == 1) { + priv->brd_clk = 60; /* 20 MHz */ + priv->bus_clk = priv->brd_clk * 0x14; + priv->bus_clkdiv = priv->brd_clkdiv; + } else if (breg == 3) { + priv->brd_clk = 100; /* 33.33 MHz */ + priv->bus_clk = priv->brd_clk * 0x18; + priv->bus_clkdiv = priv->brd_clkdiv * 2; + } else { + printf("MD[14:13] setting 0x%x not supported!", breg); + hang(); + } + + priv->brd_clkdiva = !!(modemr0 & BIT(14)); /* MD14 */ + + /* Decode DDR operating frequency from MD[37:36,19,17] pins */ + md = ((modemr0 & BIT(19)) >> 18) | ((modemr0 & BIT(17)) >> 17); + 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) { + priv->ddr_mbps = 4800; + priv->ddr_mbpsdiv = 1; + } + + priv->ddr_mul = CLK_DIV(priv->ddr_mbps, priv->ddr_mbpsdiv * 2, + priv->brd_clk, priv->brd_clkdiv * (priv->brd_clkdiva + 1)); + priv->ddr_mul_low = CLK_DIV(6400, 2, priv->brd_clk, + priv->brd_clkdiv * (priv->brd_clkdiva + 1)); + + priv->ddr_mul_reg = priv->ddr_mul_low; + if (sscg != 0) + priv->ddr_mul_reg -= 2; + + priv->ddr_mul_nf = ((8 * priv->ddr_mbps * priv->brd_clkdiv * (priv->brd_clkdiva + 1)) / + (priv->ddr_mbpsdiv * priv->brd_clk * 2)) - (8 * (priv->ddr_mul / 2) * 2); + + /* Adjust tccd */ + priv->ddr_tccd = 2; + + /* Initialize DDR */ + dbsc5_reg_write(regs_dbsc_d + DBSC_DBSYSCNT0, 0x1234); + dbsc5_reg_write(regs_dbsc_a + DBSC_DBSYSCNT0A, 0x1234); + + reg = dbsc5_init_ddr(dev); + + dbsc5_reg_write(regs_dbsc_d + DBSC_DBSYSCNT0, 0x0); + dbsc5_reg_write(regs_dbsc_a + DBSC_DBSYSCNT0A, 0x0); + + return reg != priv->ddr_phyvalid; +} + +/** + * renesas_dbsc5_dram_of_to_plat() - Convert OF data to plat data + * @dev: DBSC5 device + * + * Extract DBSC5 address from DT and store it in driver data. + */ +static int renesas_dbsc5_dram_of_to_plat(struct udevice *dev) +{ + struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); + + priv->regs = dev_read_addr_ptr(dev); + if (!priv->regs) + return -EINVAL; + + return 0; +} + +/** + * renesas_dbsc5_dram_get_info() - Return RAM size + * @dev: DBSC5 device + * @info: Output RAM info + * + * Return size of the RAM managed by this RAM driver. + */ +static int renesas_dbsc5_dram_get_info(struct udevice *dev, + struct ram_info *info) +{ + info->base = 0x40000000; + info->size = 0; + + return 0; +} + +static const struct ram_ops renesas_dbsc5_dram_ops = { + .get_info = renesas_dbsc5_dram_get_info, +}; + +U_BOOT_DRIVER(renesas_dbsc5_dram) = { + .name = "dbsc5_dram", + .id = UCLASS_RAM, + .of_to_plat = renesas_dbsc5_dram_of_to_plat, + .ops = &renesas_dbsc5_dram_ops, + .probe = renesas_dbsc5_dram_probe, + .priv_auto = sizeof(struct renesas_dbsc5_dram_priv), +}; diff --git a/drivers/ram/renesas/dbsc5/qos.c b/drivers/ram/renesas/dbsc5/qos.c new file mode 100644 index 00000000000..56a60b987af --- /dev/null +++ b/drivers/ram/renesas/dbsc5/qos.c @@ -0,0 +1,636 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include <hang.h> +#include <linux/sizes.h> +#include <ram.h> +#include "dbsc5.h" + +/* AXMM */ +#define AXMM_ADSPLCR0 0x4008 +#define AXMM_ADSPLCR1 0x400C +#define AXMM_ADSPLCR2 0x4010 +#define AXMM_ADSPLCR3 0x4014 +#define AXMM_MMCR 0x4300 +#define AXMM_TR0CR0 0x51000 +#define AXMM_TR1CR0 0x51004 +#define AXMM_TR2CR0 0x51008 +#define AXMM_TR3CR 0x5100C +#define AXMM_TR3CR0 0x5100C +#define AXMM_TR0CR1 0x51100 +#define AXMM_TR1CR1 0x51104 +#define AXMM_TR2CR1 0x51108 +#define AXMM_TR3CR1 0x5110C +#define AXMM_TR0CR2 0x51200 +#define AXMM_TR1CR2 0x51204 +#define AXMM_TR2CR2 0x51208 +#define AXMM_TR3CR2 0x5120C + +#define ACTEXT_RT0_R 0xFFC50800 +#define ACTEXT_RT0_W 0xFFC51800 +#define ACTEXT_IR0_R 0xFF890800 +#define ACTEXT_IR0_W 0xFF891800 +#define ACTEXT_IR1_R 0xFF892800 +#define ACTEXT_IR1_W 0xFF893800 +#define SI0_RW_MAX 0xF1201110 +#define SI1_RW_MAX 0xF1202110 + +/* DBSC */ +#define DBSC_A_CH_OFFSET 0x8000 +#define DBSC_D_CH_OFFSET 0x4000 + +#define DBSC_SYSCNT0 0x0100 +#define DBSC_SYSCNT1 0x0104 +#define DBSC_FCPRSCTRL 0x0110 +#define DBSC_DBBUS0CNF2 0x0808 +#define DBSC_DBCAM0CNF1 0x0904 +#define DBSC_DBCAM0CNF2 0x0908 +#define DBSC_DBCAM0CNF3 0x090C +#define DBSC_DBCAMDIS 0x09FC +#define DBSC_DBSCHCNT0 0x1000 +#define DBSC_DBSCHSZ0 0x1010 +#define DBSC_DBSCHRW0 0x1020 +#define DBSC_SCFCTST2 0x1048 +#define DBSC_DBSCHQOS_0_0 0x1100 +#define DBSC_DBSCHQOS_0_1 0x1104 +#define DBSC_DBSCHQOS_0_2 0x1108 +#define DBSC_DBSCHQOS_0_3 0x110C +#define DBSC_DBSCHQOS_4_0 0x1140 +#define DBSC_DBSCHQOS_4_1 0x1144 +#define DBSC_DBSCHQOS_4_2 0x1148 +#define DBSC_DBSCHQOS_4_3 0x114C +#define DBSC_DBSCHQOS_9_0 0x1190 +#define DBSC_DBSCHQOS_9_1 0x1194 +#define DBSC_DBSCHQOS_9_2 0x1198 +#define DBSC_DBSCHQOS_9_3 0x119C +#define DBSC_DBSCHQOS_12_0 0x11C0 +#define DBSC_DBSCHQOS_12_1 0x11C4 +#define DBSC_DBSCHQOS_12_2 0x11C8 +#define DBSC_DBSCHQOS_12_3 0x11CC +#define DBSC_DBSCHQOS_13_0 0x11D0 +#define DBSC_DBSCHQOS_13_1 0x11D4 +#define DBSC_DBSCHQOS_13_2 0x11D8 +#define DBSC_DBSCHQOS_13_3 0x11DC +#define DBSC_DBSCHQOS_14_0 0x11E0 +#define DBSC_DBSCHQOS_14_1 0x11E4 +#define DBSC_DBSCHQOS_14_2 0x11E8 +#define DBSC_DBSCHQOS_14_3 0x11EC +#define DBSC_DBSCHQOS_15_0 0x11F0 +#define DBSC_DBSCHQOS_15_1 0x11F4 +#define DBSC_DBSCHQOS_15_2 0x11F8 +#define DBSC_DBSCHQOS_15_3 0x11FC + +/* CCI */ +#define CCIQOS00 0xC020 +#define CCIQOS01 0xC024 +#define CCIQOS10 0xD000 +#define CCIQOS11 0xD004 + +/* QOS */ +#define QOS_FIX_QOS_BANK0 0x0 +#define QOS_FIX_QOS_BANK1 0x1000 +#define QOS_BE_QOS_BANK0 0x2000 +#define QOS_BE_QOS_BANK1 0x3000 +#define QOS_SL_INIT 0x8000 +#define QOS_REF_ARS 0x8004 +#define QOS_STATQC 0x8008 +#define QOS_REF_ENBL 0x8044 +#define QOS_BWG 0x804C +#define QOS_RAS 0x10000 +#define QOS_FSS 0x10048 +#define QOS_RAEN 0x10018 +#define QOS_DANN_LOW 0x10030 +#define QOS_DANN_HIGH 0x10034 +#define QOS_DANT 0x10038 +#define QOS_EMS_LOW 0x10040 +#define QOS_EMS_HIGH 0x10044 +#define QOS_INSFC 0x10050 +#define QOS_EARLYR 0x10060 +#define QOS_RACNT0 0x10080 +#define QOS_STATGEN0 0x10088 + +#define QOSWT_FIX_QOS_BANK0 0x800 +#define QOSWT_FIX_QOS_BANK1 0x1800 +#define QOSWT_BE_QOS_BANK0 0x2800 +#define QOSWT_BE_QOS_BANK1 0x3800 +#define QOSWT_WTEN 0x8030 +#define QOSWT_WTREF 0x8034 +#define QOSWT_WTSET0 0x8038 +#define QOSWT_WTSET1 0x803C + +static const struct { + u64 fix; + u64 be; +} g_qosbw_tbl[] = { + { 0x000C04010000FFFF, 0x00200030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00200030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00200030004FFC01 }, + { 0x000C04010000FFFF, 0x0000000000000000 }, + { 0x000C04080000FFFF, 0x00200030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00200030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04100000FFFF, 0x00100030004FFC01 }, + { 0x000C04100000FFFF, 0x00100030004FFC01 }, + { 0x000C04100000FFFF, 0x0000000000000000 }, + { 0x000C08140000FFFF, 0x00100030004FFC01 }, + { 0x000C08140000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFF0, 0x0000000000000000 }, + { 0x000C04100000FFFF, 0x00100030004FFC01 }, + { 0x000C04100000FFFF, 0x00100030004FFC01 }, + { 0x000C04100000FFFF, 0x0000000000000000 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C08140000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x001404080000FFFF, 0x00100030004FFC01 }, + { 0x001404080000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x001000F0004FFC01 }, + { 0x000C04010000FFFF, 0x001000F0004FFC01 }, + { 0x000C04010000FFFF, 0x002000F0004FFC01 }, + { 0x000C04010000FFFF, 0x002000F0004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000C04200000FFFF, 0x00100030004FFC01 }, + { 0x000C04100000FFFF, 0x00100030004FFC01 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000C144F0000FFFF, 0x00100030004FFC01 }, + { 0x000C0C4F0000FFFF, 0x00100030004FFC01 }, + { 0x000C0C4F0000FFFF, 0x00100030004FFC01 }, + { 0x001404080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x001424870000FFFF, 0x00100030004FFC01 }, + { 0x001424870000FFFF, 0x00100030004FFC01 }, + { 0x000C149E0000FFFF, 0x00100030004FFC01 }, + { 0x000C149E0000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x00140C050000FFFF, 0x00100030004FFC01 }, + { 0x0014450E0000FFFF, 0x00100030004FFC01 }, + { 0x001424870000FFFF, 0x00100030004FFC01 }, + { 0x0014289E0000FFFF, 0x00000000000FFC00 }, + { 0x0014289E0000FFFF, 0x00000000000FFC00 }, + { 0x0014149E0000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x001004080000FFFF, 0x0000000000000000 }, + { 0x001004080000FFFF, 0x0000000000000000 }, + { 0x001004080000FFFF, 0x0000000000000000 }, + { 0x000C00000000FFFF, 0x001000F0004FFC01 }, + { 0x000C00000000FFFF, 0x001000F0004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x001404080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000C04080000FFFF, 0x00100030004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C04010000FFFF, 0x001001D0004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C04010000FFFF, 0x001001D0004FFC01 }, + { 0x000000000000FFFF, 0x0000000000000000 }, + { 0x000C04010000FFFF, 0x001001D0004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x001001D0004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x000C04010000FFFF, 0x00100030004FFC01 }, + { 0x001404010000FFFF, 0x00100030004FFC01 } +}; + +static const struct { + u64 fix; + u64 be; +} g_qoswt_tbl[] = { + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x000C04050000FFFF, 0x0000000000000000 }, + { 0x000C080C0000FFFF, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x000C04050000C001, 0x0000000000000000 }, + { 0x000C080C0000C001, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x001424870000C001, 0x0000000000000000 }, + { 0x001424870000C001, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x001424870000FFFF, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 }, + { 0x0000000000000000, 0x0000000000000000 } +}; + +struct renesas_dbsc5_qos_priv { + void __iomem *regs; +}; + +static int dbsc5_qos_dbsc_setting(struct udevice *dev) +{ + struct renesas_dbsc5_qos_priv *priv = dev_get_priv(dev); + void __iomem *regs_dbsc_a, *regs_dbsc_d; + unsigned int ch, nch; + + if (IS_ENABLED(CONFIG_R8A779G0) && + renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A779G0) + nch = 2; + else if (IS_ENABLED(CONFIG_R8A779H0) && + renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A779H0) + nch = 1; + else + return -EINVAL; + + for (ch = 0; ch < nch; ch++) { + regs_dbsc_a = priv->regs + DBSC5_DBSC_A_OFFSET + ch * DBSC_A_CH_OFFSET; + regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET + ch * DBSC_D_CH_OFFSET; + + /* DBSC CAM, Scheduling Setting */ + writel(0x1234, regs_dbsc_d + DBSC_SYSCNT0); + writel(0x1234, regs_dbsc_a + DBSC_SYSCNT0); + writel(0x48218, regs_dbsc_a + DBSC_DBCAM0CNF1); + writel(0x1C4, regs_dbsc_a + DBSC_DBCAM0CNF2); + writel(0x3, regs_dbsc_a + DBSC_DBCAM0CNF3); + + if (IS_ENABLED(CONFIG_R8A779G0) && + renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A779G0 && + (renesas_get_cpu_rev_integer() < 2 || + (renesas_get_cpu_rev_integer() == 2 && + renesas_get_cpu_rev_fraction() <= 1))) { + /* OTLINT-5579: V4H <= rev2.1 DBSC W/A-3 */ + writel(0x11, regs_dbsc_a + DBSC_DBCAMDIS); + } else { + writel(0x10, regs_dbsc_a + DBSC_DBCAMDIS); + } + + writel(0xF0037, regs_dbsc_a + DBSC_DBSCHCNT0); + writel(0x1, regs_dbsc_a + DBSC_DBSCHSZ0); + writel(0xF7311111, regs_dbsc_a + DBSC_DBSCHRW0); + writel(0x111F1FFF, regs_dbsc_a + DBSC_SCFCTST2); + + /* OTLINT-5579: V4H DBSC WA3 */ + writel(0x7, regs_dbsc_a + DBSC_DBBUS0CNF2); + + /* DBSC QoS Setting */ + writel(0xFFFF, regs_dbsc_a + DBSC_DBSCHQOS_0_0); + writel(0x480, regs_dbsc_a + DBSC_DBSCHQOS_0_1); + writel(0x300, regs_dbsc_a + DBSC_DBSCHQOS_0_2); + writel(0x180, regs_dbsc_a + DBSC_DBSCHQOS_0_3); + writel(0x400, regs_dbsc_a + DBSC_DBSCHQOS_4_0); + writel(0x300, regs_dbsc_a + DBSC_DBSCHQOS_4_1); + writel(0x200, regs_dbsc_a + DBSC_DBSCHQOS_4_2); + writel(0x100, regs_dbsc_a + DBSC_DBSCHQOS_4_3); + writel(0x300, regs_dbsc_a + DBSC_DBSCHQOS_9_0); + writel(0x240, regs_dbsc_a + DBSC_DBSCHQOS_9_1); + writel(0x180, regs_dbsc_a + DBSC_DBSCHQOS_9_2); + writel(0xC0, regs_dbsc_a + DBSC_DBSCHQOS_9_3); + writel(0x40, regs_dbsc_a + DBSC_DBSCHQOS_12_0); + writel(0x30, regs_dbsc_a + DBSC_DBSCHQOS_12_1); + writel(0x20, regs_dbsc_a + DBSC_DBSCHQOS_12_2); + writel(0x10, regs_dbsc_a + DBSC_DBSCHQOS_12_3); + writel(0x300, regs_dbsc_a + DBSC_DBSCHQOS_13_0); + writel(0x240, regs_dbsc_a + DBSC_DBSCHQOS_13_1); + writel(0x180, regs_dbsc_a + DBSC_DBSCHQOS_13_2); + writel(0xC0, regs_dbsc_a + DBSC_DBSCHQOS_13_3); + writel(0x200, regs_dbsc_a + DBSC_DBSCHQOS_14_0); + writel(0x180, regs_dbsc_a + DBSC_DBSCHQOS_14_1); + writel(0x100, regs_dbsc_a + DBSC_DBSCHQOS_14_2); + writel(0x80, regs_dbsc_a + DBSC_DBSCHQOS_14_3); + writel(0x100, regs_dbsc_a + DBSC_DBSCHQOS_15_0); + writel(0xC0, regs_dbsc_a + DBSC_DBSCHQOS_15_1); + writel(0x80, regs_dbsc_a + DBSC_DBSCHQOS_15_2); + writel(0x40, regs_dbsc_a + DBSC_DBSCHQOS_15_3); + + /* Target register is only DBSC0 side. */ + if (ch == 0) + writel(0x1, regs_dbsc_a + DBSC_FCPRSCTRL); + + writel(0x1, regs_dbsc_a + DBSC_SYSCNT1); + writel(0x0, regs_dbsc_d + DBSC_SYSCNT0); + writel(0x0, regs_dbsc_a + DBSC_SYSCNT0); + } + + return 0; +} + +static int dbsc5_qos_settings_init(struct udevice *dev) +{ + struct renesas_dbsc5_qos_priv *priv = dev_get_priv(dev); + void __iomem *regs_axmm = priv->regs + DBSC5_AXMM_OFFSET; + void __iomem *regs_cci = priv->regs + DBSC5_CCI_OFFSET; + void __iomem *regs_qos = priv->regs + DBSC5_QOS_OFFSET; + int i; + + if (IS_ENABLED(CONFIG_R8A779G0) && + renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A779G0) { + /* Address Split 2ch */ + writel(0x0, regs_axmm + AXMM_ADSPLCR0); + writel(0xFF1B0C, regs_axmm + AXMM_ADSPLCR1); + writel(0x0, regs_axmm + AXMM_ADSPLCR2); + writel(0x0, regs_axmm + AXMM_ADSPLCR3); + + writel(0x8000000, regs_cci + CCIQOS00); + writel(0x8000000, regs_cci + CCIQOS01); + + if (renesas_get_cpu_rev_integer() >= 2) { + writel(0x1, regs_cci + CCIQOS10); + writel(0x1, regs_cci + CCIQOS11); + } else { + writel(0x0, regs_cci + CCIQOS10); + writel(0x0, regs_cci + CCIQOS11); + } + + /* Resource Alloc setting */ + writel(0x48, regs_qos + QOS_RAS); + } else if (IS_ENABLED(CONFIG_R8A779H0) && + renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A779H0) { + /* Resource Alloc setting */ + writel(0x30, regs_qos + QOS_RAS); + } else { + return -EINVAL; + } + + writel(0x2020201, regs_qos + QOS_DANN_LOW); + writel(0x4040200, regs_qos + QOS_DANN_HIGH); + writel(0x181008, regs_qos + QOS_DANT); + writel(0x0, regs_qos + QOS_EMS_LOW); + writel(0x0, regs_qos + QOS_EMS_HIGH); + writel(0xA, regs_qos + QOS_FSS); + writel(0x30F0001, regs_qos + QOS_INSFC); + writel(0x0, regs_qos + QOS_EARLYR); + writel(0x50003, regs_qos + QOS_RACNT0); + writel(0x0, regs_qos + QOS_STATGEN0); + + /* QoS MSTAT setting */ + writel(0x70120, regs_qos + QOS_SL_INIT); + writel(0x11B0000, regs_qos + QOS_REF_ARS); + writel(0x12, regs_qos + QOS_REF_ENBL); + writel(0x4, regs_qos + QOS_BWG); + + if (IS_ENABLED(CONFIG_R8A779G0) && + renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A779G0 && + (renesas_get_cpu_rev_integer() < 2 || + (renesas_get_cpu_rev_integer() == 2 && + renesas_get_cpu_rev_fraction() <= 1))) { + /* OTLINT-5579: V4H <= rev2.1 DBSC W/A-3 */ + writel(0x0, regs_axmm + AXMM_MMCR); + } else { + writel(0x10000, regs_axmm + AXMM_MMCR); + } + + writel(0x3, ACTEXT_RT0_R); + writel(0x3, ACTEXT_RT0_W); + + /* + * This may be necessary, but this IP is powered off at this point: + * writel(0x3, ACTEXT_IR0_R); + * writel(0x3, ACTEXT_IR0_W); + * writel(0x3, ACTEXT_IR1_R); + * writel(0x3, ACTEXT_IR1_W); + */ + + if (IS_ENABLED(CONFIG_R8A779G0) && + renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A779G0) { + writel(0x10000, regs_axmm + AXMM_TR3CR); + + if (renesas_get_cpu_rev_integer() >= 2) { + /* WA1 patch for IPL CA76 hang-up issue, REL_TRI_DN-7592 */ + writel(0x38, SI0_RW_MAX); + writel(0x38, SI1_RW_MAX); + } + } + + if (IS_ENABLED(CONFIG_R8A779H0) && + renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A779H0) { + writel(0x0, regs_axmm + AXMM_TR0CR0); + writel(0x0, regs_axmm + AXMM_TR1CR0); + writel(0x0, regs_axmm + AXMM_TR2CR0); + writel(0x0, regs_axmm + AXMM_TR3CR0); + writel(0x70707070, regs_axmm + AXMM_TR0CR1); + writel(0x70707070, regs_axmm + AXMM_TR1CR1); + writel(0x70707070, regs_axmm + AXMM_TR2CR1); + writel(0x70707070, regs_axmm + AXMM_TR3CR1); + writel(0x70707070, regs_axmm + AXMM_TR0CR2); + writel(0x70707070, regs_axmm + AXMM_TR1CR2); + writel(0x70707070, regs_axmm + AXMM_TR2CR2); + writel(0x70707070, regs_axmm + AXMM_TR3CR2); + } + + for (i = 0U; i < ARRAY_SIZE(g_qosbw_tbl); i++) { + writeq(g_qosbw_tbl[i].fix, regs_qos + QOS_FIX_QOS_BANK0 + (i * 8)); + writeq(g_qosbw_tbl[i].fix, regs_qos + QOS_FIX_QOS_BANK1 + (i * 8)); + writeq(g_qosbw_tbl[i].be, regs_qos + QOS_BE_QOS_BANK0 + (i * 8)); + writeq(g_qosbw_tbl[i].be, regs_qos + QOS_BE_QOS_BANK1 + (i * 8)); + } + + for (i = 0U; i < ARRAY_SIZE(g_qoswt_tbl); i++) { + writeq(g_qoswt_tbl[i].fix, regs_qos + QOSWT_FIX_QOS_BANK0 + (i * 8)); + writeq(g_qoswt_tbl[i].fix, regs_qos + QOSWT_FIX_QOS_BANK1 + (i * 8)); + writeq(g_qoswt_tbl[i].be, regs_qos + QOSWT_BE_QOS_BANK0 + (i * 8)); + writeq(g_qoswt_tbl[i].be, regs_qos + QOSWT_BE_QOS_BANK1 + (i * 8)); + } + + /* QoS SRAM setting */ + writel(0x1, regs_qos + QOS_RAEN); + writel(0x2080208, regs_qos + QOSWT_WTREF); + writel(0xD90050F, regs_qos + QOSWT_WTSET0); + writel(0xD90050F, regs_qos + QOSWT_WTSET1); + writel(0x1, regs_qos + QOSWT_WTEN); + writel(0x101, regs_qos + QOS_STATQC); + + return 0; +} + +static int renesas_dbsc5_qos_probe(struct udevice *dev) +{ + int ret; + + /* Setting the register of DBSC4 for QoS initialize */ + ret = dbsc5_qos_dbsc_setting(dev); + if (ret) + return ret; + + return dbsc5_qos_settings_init(dev); +} + +static int renesas_dbsc5_qos_of_to_plat(struct udevice *dev) +{ + struct renesas_dbsc5_qos_priv *priv = dev_get_priv(dev); + + priv->regs = dev_read_addr_ptr(dev); + if (!priv->regs) + return -EINVAL; + + return 0; +} + +U_BOOT_DRIVER(renesas_dbsc5_qos) = { + .name = "dbsc5_qos", + .id = UCLASS_NOP, + .of_to_plat = renesas_dbsc5_qos_of_to_plat, + .probe = renesas_dbsc5_qos_probe, + .priv_auto = sizeof(struct renesas_dbsc5_qos_priv), +}; diff --git a/drivers/ram/renesas/dbsc5/rtvram.c b/drivers/ram/renesas/dbsc5/rtvram.c new file mode 100644 index 00000000000..6c149284bc6 --- /dev/null +++ b/drivers/ram/renesas/dbsc5/rtvram.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include <ram.h> +#include <linux/sizes.h> + +/* RT-VRAM register base address */ +#define RTVRAM_VBUF_CFG 0x6504 +#define RTVRAM_VBUF_CFG_CACHE_MODE_8WAY (1 << 8) +#define RTVRAM_VBUF_CFG_VBUF_SIZE_28M (6 << 0) +#define RTVRAM_EXT_MODE 0x8500 +#define RTVRAM_EXT_MODE_EXT BIT(0) +#define RTVRAM_VBUF_BADDR 0xC580 + +#define RTVRAM_VBUF_NUM 7 + +#define SDRAM_40BIT_ADDR_TOP 0x0400000000ULL +#define RTVRAM_VBUF_AREA_SIZE SZ_4M + +struct renesas_dbsc5_rtvram_priv { + void __iomem *regs; +}; + +static int renesas_dbsc5_rtvram_probe(struct udevice *dev) +{ + struct renesas_dbsc5_rtvram_priv *priv = dev_get_priv(dev); + u64 addr; + int i; + + /* Set each 4MB from the top of SDRAM as the buffer area of RT-VRAM. */ + for (i = 0; i < RTVRAM_VBUF_NUM; i++) { + addr = (SDRAM_40BIT_ADDR_TOP + (RTVRAM_VBUF_AREA_SIZE * i)) >> 16; + writel(lower_32_bits(addr), priv->regs + (RTVRAM_VBUF_BADDR + (4 * i))); + } + + /* Cache Mode: 8-way, VBF size: 28M */ + setbits_le32(priv->regs + RTVRAM_VBUF_CFG, + RTVRAM_VBUF_CFG_CACHE_MODE_8WAY | RTVRAM_VBUF_CFG_VBUF_SIZE_28M); + + /* Change from Compatible Mode to Extended Mode */ + writel(RTVRAM_EXT_MODE_EXT, priv->regs + RTVRAM_EXT_MODE); + + dsb(); + + return 0; +} + +static int renesas_dbsc5_rtvram_of_to_plat(struct udevice *dev) +{ + struct renesas_dbsc5_rtvram_priv *priv = dev_get_priv(dev); + + priv->regs = dev_read_addr_ptr(dev); + if (!priv->regs) + return -EINVAL; + + return 0; +} + +static int renesas_dbsc5_rtvram_get_info(struct udevice *dev, + struct ram_info *info) +{ + struct renesas_dbsc5_rtvram_priv *priv = dev_get_priv(dev); + + info->base = (phys_addr_t)priv->regs; + info->size = 28 * SZ_1M; + + return 0; +} + +static const struct ram_ops renesas_dbsc5_rtvram_ops = { + .get_info = renesas_dbsc5_rtvram_get_info, +}; + +static const struct udevice_id renesas_dbsc5_rtvram_ids[] = { + { .compatible = "renesas,r8a779g0-rtvram" }, + { .compatible = "renesas,r8a779h0-rtvram" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(renesas_dbsc5_rtvram) = { + .name = "rtvram", + .id = UCLASS_RAM, + .of_match = renesas_dbsc5_rtvram_ids, + .of_to_plat = renesas_dbsc5_rtvram_of_to_plat, + .ops = &renesas_dbsc5_rtvram_ops, + .probe = renesas_dbsc5_rtvram_probe, + .priv_auto = sizeof(struct renesas_dbsc5_rtvram_priv), +};

Describe DBSC5 DRAM controller and RT-VRAM configuration interface as two new DT nodes in R-Car Gen4 R8A779G0 U-Boot DT extras file. This node is used by the U-Boot SPL for R8A779G0 SoC, where the DBSC5 and RT-VRAM drivers bind to these nodes and bring up the DRAM controller and RT-VRAM settings respectively, so U-Boot proper can be loaded into DRAM and started on Cortex A76 core.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org --- Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com Cc: u-boot@lists.denx.de --- arch/arm/dts/r8a779g0-u-boot.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/arch/arm/dts/r8a779g0-u-boot.dtsi b/arch/arm/dts/r8a779g0-u-boot.dtsi index f60eba531e4..42df321178b 100644 --- a/arch/arm/dts/r8a779g0-u-boot.dtsi +++ b/arch/arm/dts/r8a779g0-u-boot.dtsi @@ -15,3 +15,21 @@ &extalr_clk { bootph-all; }; + +&soc { + ram@e6780000 { /* DBSC5 */ + compatible = "renesas,r8a779g0-dbsc"; + reg = <0 0xe6780000 0 0x80000>; + power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; + status = "okay"; + bootph-all; + }; + + ram@ffec0000 { /* RT-VRAM */ + compatible = "renesas,r8a779g0-rtvram"; + reg = <0 0xffec0000 0 0xf000>; + power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; + status = "okay"; + bootph-all; + }; +};
participants (1)
-
Marek Vasut