[U-Boot] [PATCH 11/12] rockchip: add px30 architecture core
Kever Yang
kever.yang at rock-chips.com
Fri Oct 25 02:49:54 UTC 2019
Heiko,
On 2019/10/25 上午7:28, Heiko Stuebner wrote:
> From: Kever Yang <kever.yang at rock-chips.com>
>
> Add core architecture code to support the px30 soc.
> This includes a separate tpl board file due to very limited
> sram size as well as a non-dm sdram driver, as this also has
> to fit into the tiny sram.
Could you leave the sram code and make it possible to use the common
sdram code
I have send out:
https://patchwork.ozlabs.org/cover/1183700/
The sram driver should goes to driver/ram folder instead of arch/arm folder.
>
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> Signed-off-by: Heiko Stuebner <heiko.stuebner at theobroma-systems.com>
> ---
> arch/arm/include/asm/arch-px30/boot0.h | 11 +
> arch/arm/include/asm/arch-px30/gpio.h | 11 +
> .../include/asm/arch-rockchip/sdram_px30.h | 359 +++++
> arch/arm/mach-rockchip/Kconfig | 23 +
> arch/arm/mach-rockchip/Makefile | 2 +
> arch/arm/mach-rockchip/px30-board-tpl.c | 59 +
> arch/arm/mach-rockchip/px30/Kconfig | 48 +
> arch/arm/mach-rockchip/px30/Makefile | 14 +
> arch/arm/mach-rockchip/px30/clk_px30.c | 31 +
> arch/arm/mach-rockchip/px30/px30.c | 248 +++
> .../px30/sdram-px30-ddr3-detect-333.inc | 70 +
> .../px30/sdram-px30-ddr4-detect-333.inc | 73 +
> .../px30/sdram-px30-ddr_skew.inc | 121 ++
> .../px30/sdram-px30-lpddr2-detect-333.inc | 71 +
> .../px30/sdram-px30-lpddr3-detect-333.inc | 72 +
> arch/arm/mach-rockchip/px30/sdram_px30.c | 1405 +++++++++++++++++
> arch/arm/mach-rockchip/px30/syscon_px30.c | 53 +
> 17 files changed, 2671 insertions(+)
> create mode 100644 arch/arm/include/asm/arch-px30/boot0.h
> create mode 100644 arch/arm/include/asm/arch-px30/gpio.h
> create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_px30.h
> create mode 100644 arch/arm/mach-rockchip/px30-board-tpl.c
> create mode 100644 arch/arm/mach-rockchip/px30/Kconfig
> create mode 100644 arch/arm/mach-rockchip/px30/Makefile
> create mode 100644 arch/arm/mach-rockchip/px30/clk_px30.c
> create mode 100644 arch/arm/mach-rockchip/px30/px30.c
> create mode 100644 arch/arm/mach-rockchip/px30/sdram-px30-ddr3-detect-333.inc
> create mode 100644 arch/arm/mach-rockchip/px30/sdram-px30-ddr4-detect-333.inc
> create mode 100644 arch/arm/mach-rockchip/px30/sdram-px30-ddr_skew.inc
> create mode 100644 arch/arm/mach-rockchip/px30/sdram-px30-lpddr2-detect-333.inc
> create mode 100644 arch/arm/mach-rockchip/px30/sdram-px30-lpddr3-detect-333.inc
> create mode 100644 arch/arm/mach-rockchip/px30/sdram_px30.c
> create mode 100644 arch/arm/mach-rockchip/px30/syscon_px30.c
>
> diff --git a/arch/arm/include/asm/arch-px30/boot0.h b/arch/arm/include/asm/arch-px30/boot0.h
> new file mode 100644
> index 0000000000..2e78b074ad
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-px30/boot0.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2019 Rockchip Electronics Co., Ltd
> + */
> +
> +#ifndef __ASM_ARCH_BOOT0_H__
> +#define __ASM_ARCH_BOOT0_H__
> +
> +#include <asm/arch-rockchip/boot0.h>
> +
> +#endif
> diff --git a/arch/arm/include/asm/arch-px30/gpio.h b/arch/arm/include/asm/arch-px30/gpio.h
> new file mode 100644
> index 0000000000..eca79d5159
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-px30/gpio.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2019 Rockchip Electronics Co., Ltd
> + */
> +
> +#ifndef __ASM_ARCH_GPIO_H__
> +#define __ASM_ARCH_GPIO_H__
> +
> +#include <asm/arch-rockchip/gpio.h>
> +
> +#endif
> diff --git a/arch/arm/include/asm/arch-rockchip/sdram_px30.h b/arch/arm/include/asm/arch-rockchip/sdram_px30.h
> new file mode 100644
> index 0000000000..e10eb97b89
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-rockchip/sdram_px30.h
> @@ -0,0 +1,359 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2018 Rockchip Electronics Co., Ltd
> + */
> +
> +#ifndef _ASM_ARCH_SDRAM_PX30_H
> +#define _ASM_ARCH_SDRAM_PX30_H
> +
> +struct ddr_pctl_regs {
> + u32 pctl[30][2];
> +};
> +
> +/* ddr pctl registers define */
> +#define DDR_PCTL2_MSTR 0x0
> +#define DDR_PCTL2_STAT 0x4
> +#define DDR_PCTL2_MSTR1 0x8
> +#define DDR_PCTL2_MRCTRL0 0x10
> +#define DDR_PCTL2_MRCTRL1 0x14
> +#define DDR_PCTL2_MRSTAT 0x18
> +#define DDR_PCTL2_MRCTRL2 0x1c
> +#define DDR_PCTL2_DERATEEN 0x20
> +#define DDR_PCTL2_DERATEINT 0x24
> +#define DDR_PCTL2_PWRCTL 0x30
> +#define DDR_PCTL2_PWRTMG 0x34
> +#define DDR_PCTL2_HWLPCTL 0x38
> +#define DDR_PCTL2_RFSHCTL0 0x50
> +#define DDR_PCTL2_RFSHCTL1 0x54
> +#define DDR_PCTL2_RFSHCTL2 0x58
> +#define DDR_PCTL2_RFSHCTL4 0x5c
> +#define DDR_PCTL2_RFSHCTL3 0x60
> +#define DDR_PCTL2_RFSHTMG 0x64
> +#define DDR_PCTL2_RFSHTMG1 0x68
> +#define DDR_PCTL2_RFSHCTL5 0x6c
> +#define DDR_PCTL2_INIT0 0xd0
> +#define DDR_PCTL2_INIT1 0xd4
> +#define DDR_PCTL2_INIT2 0xd8
> +#define DDR_PCTL2_INIT3 0xdc
> +#define DDR_PCTL2_INIT4 0xe0
> +#define DDR_PCTL2_INIT5 0xe4
> +#define DDR_PCTL2_INIT6 0xe8
> +#define DDR_PCTL2_INIT7 0xec
> +#define DDR_PCTL2_DIMMCTL 0xf0
> +#define DDR_PCTL2_RANKCTL 0xf4
> +#define DDR_PCTL2_CHCTL 0xfc
> +#define DDR_PCTL2_DRAMTMG0 0x100
> +#define DDR_PCTL2_DRAMTMG1 0x104
> +#define DDR_PCTL2_DRAMTMG2 0x108
> +#define DDR_PCTL2_DRAMTMG3 0x10c
> +#define DDR_PCTL2_DRAMTMG4 0x110
> +#define DDR_PCTL2_DRAMTMG5 0x114
> +#define DDR_PCTL2_DRAMTMG6 0x118
> +#define DDR_PCTL2_DRAMTMG7 0x11c
> +#define DDR_PCTL2_DRAMTMG8 0x120
> +#define DDR_PCTL2_DRAMTMG9 0x124
> +#define DDR_PCTL2_DRAMTMG10 0x128
> +#define DDR_PCTL2_DRAMTMG11 0x12c
> +#define DDR_PCTL2_DRAMTMG12 0x130
> +#define DDR_PCTL2_DRAMTMG13 0x134
> +#define DDR_PCTL2_DRAMTMG14 0x138
> +#define DDR_PCTL2_DRAMTMG15 0x13c
> +#define DDR_PCTL2_DRAMTMG16 0x140
> +#define DDR_PCTL2_ZQCTL0 0x180
> +#define DDR_PCTL2_ZQCTL1 0x184
> +#define DDR_PCTL2_ZQCTL2 0x188
> +#define DDR_PCTL2_ZQSTAT 0x18c
> +#define DDR_PCTL2_DFITMG0 0x190
> +#define DDR_PCTL2_DFITMG1 0x194
> +#define DDR_PCTL2_DFILPCFG0 0x198
> +#define DDR_PCTL2_DFILPCFG1 0x19c
> +#define DDR_PCTL2_DFIUPD0 0x1a0
> +#define DDR_PCTL2_DFIUPD1 0x1a4
> +#define DDR_PCTL2_DFIUPD2 0x1a8
> +#define DDR_PCTL2_DFIMISC 0x1b0
> +#define DDR_PCTL2_DFITMG2 0x1b4
> +#define DDR_PCTL2_DFITMG3 0x1b8
> +#define DDR_PCTL2_DFISTAT 0x1bc
> +#define DDR_PCTL2_DBICTL 0x1c0
> +#define DDR_PCTL2_ADDRMAP0 0x200
> +#define DDR_PCTL2_ADDRMAP1 0x204
> +#define DDR_PCTL2_ADDRMAP2 0x208
> +#define DDR_PCTL2_ADDRMAP3 0x20c
> +#define DDR_PCTL2_ADDRMAP4 0x210
> +#define DDR_PCTL2_ADDRMAP5 0x214
> +#define DDR_PCTL2_ADDRMAP6 0x218
> +#define DDR_PCTL2_ADDRMAP7 0x21c
> +#define DDR_PCTL2_ADDRMAP8 0x220
> +#define DDR_PCTL2_ADDRMAP9 0x224
> +#define DDR_PCTL2_ADDRMAP10 0x228
> +#define DDR_PCTL2_ADDRMAP11 0x22c
> +#define DDR_PCTL2_ODTCFG 0x240
> +#define DDR_PCTL2_ODTMAP 0x244
> +#define DDR_PCTL2_SCHED 0x250
> +#define DDR_PCTL2_SCHED1 0x254
> +#define DDR_PCTL2_PERFHPR1 0x25c
> +#define DDR_PCTL2_PERFLPR1 0x264
> +#define DDR_PCTL2_PERFWR1 0x26c
> +#define DDR_PCTL2_DQMAP0 0x280
> +#define DDR_PCTL2_DQMAP1 0x284
> +#define DDR_PCTL2_DQMAP2 0x288
> +#define DDR_PCTL2_DQMAP3 0x28c
> +#define DDR_PCTL2_DQMAP4 0x290
> +#define DDR_PCTL2_DQMAP5 0x294
> +#define DDR_PCTL2_DBG0 0x300
> +#define DDR_PCTL2_DBG1 0x304
> +#define DDR_PCTL2_DBGCAM 0x308
> +#define DDR_PCTL2_DBGCMD 0x30c
> +#define DDR_PCTL2_DBGSTAT 0x310
> +#define DDR_PCTL2_SWCTL 0x320
> +#define DDR_PCTL2_SWSTAT 0x324
> +#define DDR_PCTL2_POISONCFG 0x36c
> +#define DDR_PCTL2_POISONSTAT 0x370
> +#define DDR_PCTL2_ADVECCINDEX 0x374
> +#define DDR_PCTL2_ADVECCSTAT 0x378
> +#define DDR_PCTL2_PSTAT 0x3fc
> +#define DDR_PCTL2_PCCFG 0x400
> +#define DDR_PCTL2_PCFGR_n 0x404
> +#define DDR_PCTL2_PCFGW_n 0x408
> +#define DDR_PCTL2_PCTRL_n 0x490
> +
> +/* PCTL2_MRSTAT */
> +#define MR_WR_BUSY BIT(0)
> +
> +#define PHY_DDR3_RON_RTT_DISABLE (0)
> +#define PHY_DDR3_RON_RTT_451ohm (1)
> +#define PHY_DDR3_RON_RTT_225ohm (2)
> +#define PHY_DDR3_RON_RTT_150ohm (3)
> +#define PHY_DDR3_RON_RTT_112ohm (4)
> +#define PHY_DDR3_RON_RTT_90ohm (5)
> +#define PHY_DDR3_RON_RTT_75ohm (6)
> +#define PHY_DDR3_RON_RTT_64ohm (7)
> +#define PHY_DDR3_RON_RTT_56ohm (16)
> +#define PHY_DDR3_RON_RTT_50ohm (17)
> +#define PHY_DDR3_RON_RTT_45ohm (18)
> +#define PHY_DDR3_RON_RTT_41ohm (19)
> +#define PHY_DDR3_RON_RTT_37ohm (20)
> +#define PHY_DDR3_RON_RTT_34ohm (21)
> +#define PHY_DDR3_RON_RTT_33ohm (22)
> +#define PHY_DDR3_RON_RTT_30ohm (23)
> +#define PHY_DDR3_RON_RTT_28ohm (24)
> +#define PHY_DDR3_RON_RTT_26ohm (25)
> +#define PHY_DDR3_RON_RTT_25ohm (26)
> +#define PHY_DDR3_RON_RTT_23ohm (27)
> +#define PHY_DDR3_RON_RTT_22ohm (28)
> +#define PHY_DDR3_RON_RTT_21ohm (29)
> +#define PHY_DDR3_RON_RTT_20ohm (30)
> +#define PHY_DDR3_RON_RTT_19ohm (31)
> +
> +#define PHY_DDR4_LPDDR3_RON_RTT_DISABLE (0)
> +#define PHY_DDR4_LPDDR3_RON_RTT_480ohm (1)
> +#define PHY_DDR4_LPDDR3_RON_RTT_240ohm (2)
> +#define PHY_DDR4_LPDDR3_RON_RTT_160ohm (3)
> +#define PHY_DDR4_LPDDR3_RON_RTT_120ohm (4)
> +#define PHY_DDR4_LPDDR3_RON_RTT_96ohm (5)
> +#define PHY_DDR4_LPDDR3_RON_RTT_80ohm (6)
> +#define PHY_DDR4_LPDDR3_RON_RTT_68ohm (7)
> +#define PHY_DDR4_LPDDR3_RON_RTT_60ohm (16)
> +#define PHY_DDR4_LPDDR3_RON_RTT_53ohm (17)
> +#define PHY_DDR4_LPDDR3_RON_RTT_48ohm (18)
> +#define PHY_DDR4_LPDDR3_RON_RTT_43ohm (19)
> +#define PHY_DDR4_LPDDR3_RON_RTT_40ohm (20)
> +#define PHY_DDR4_LPDDR3_RON_RTT_37ohm (21)
> +#define PHY_DDR4_LPDDR3_RON_RTT_34ohm (22)
> +#define PHY_DDR4_LPDDR3_RON_RTT_32ohm (23)
> +#define PHY_DDR4_LPDDR3_RON_RTT_30ohm (24)
> +#define PHY_DDR4_LPDDR3_RON_RTT_28ohm (25)
> +#define PHY_DDR4_LPDDR3_RON_RTT_26ohm (26)
> +#define PHY_DDR4_LPDDR3_RON_RTT_25ohm (27)
> +#define PHY_DDR4_LPDDR3_RON_RTT_24ohm (28)
> +#define PHY_DDR4_LPDDR3_RON_RTT_22ohm (29)
> +#define PHY_DDR4_LPDDR3_RON_RTT_21ohm (30)
> +#define PHY_DDR4_LPDDR3_RON_RTT_20ohm (31)
> +
> +struct ddr_phy_regs {
> + u32 phy[5][2];
> +};
> +
> +#define PHY_REG(base, n) ((base) + 4 * (n))
> +
> +/* PHY_REG0 */
> +#define DIGITAL_DERESET BIT(3)
> +#define ANALOG_DERESET BIT(2)
> +#define DIGITAL_RESET (0 << 3)
> +#define ANALOG_RESET (0 << 2)
> +
> +/* PHY_REG1 */
> +#define PHY_DDR2 (0)
> +#define PHY_LPDDR2 (1)
> +#define PHY_DDR3 (2)
> +#define PHY_LPDDR3 (3)
> +#define PHY_DDR4 (4)
> +#define PHY_BL_4 (0 << 2)
> +#define PHY_BL_8 BIT(2)
> +
> +/* PHY_REG2 */
> +#define PHY_DTT_EN BIT(0)
> +#define PHY_DTT_DISB (0 << 0)
> +#define PHY_WRITE_LEVELING_EN BIT(2)
> +#define PHY_WRITE_LEVELING_DISB (0 << 2)
> +#define PHY_SELECT_CS0 (2)
> +#define PHY_SELECT_CS1 (1)
> +#define PHY_SELECT_CS0_1 (0)
> +#define PHY_WRITE_LEVELING_SELECTCS(n) ((n) << 6)
> +#define PHY_DATA_TRAINING_SELECTCS(n) ((n) << 4)
> +
> +struct ddr_phy_skew {
> + u32 a0_a1_skew[15];
> + u32 cs0_dm0_skew[11];
> + u32 cs0_dm1_skew[11];
> + u32 cs0_dm2_skew[11];
> + u32 cs0_dm3_skew[11];
> + u32 cs1_dm0_skew[11];
> + u32 cs1_dm1_skew[11];
> + u32 cs1_dm2_skew[11];
> + u32 cs1_dm3_skew[11];
> +};
> +
> +#define SR_IDLE 93
> +#define PD_IDLE 13
> +
> +/* PMUGRF */
> +#define PMUGRF_OS_REG0 (0x200)
> +#define PMUGRF_OS_REG(n) (PMUGRF_OS_REG0 + (n) * 4)
> +
> +/* DDR GRF */
> +#define DDR_GRF_CON(n) (0 + (n) * 4)
> +#define DDR_GRF_STATUS_BASE (0X100)
> +#define DDR_GRF_STATUS(n) (DDR_GRF_STATUS_BASE + (n) * 4)
> +#define DDR_GRF_LP_CON (0x20)
> +
> +#define SPLIT_MODE_32_L16_VALID (0)
> +#define SPLIT_MODE_32_H16_VALID (1)
> +#define SPLIT_MODE_16_L8_VALID (2)
> +#define SPLIT_MODE_16_H8_VALID (3)
> +
> +#define DDR_GRF_SPLIT_CON (0x8)
> +#define SPLIT_MODE_MASK (0x3)
> +#define SPLIT_MODE_OFFSET (9)
> +#define SPLIT_BYPASS_MASK (1)
> +#define SPLIT_BYPASS_OFFSET (8)
> +#define SPLIT_SIZE_MASK (0xff)
> +#define SPLIT_SIZE_OFFSET (0)
> +
> +/* CRU define */
> +/* CRU_PLL_CON0 */
> +#define PB(n) ((0x1 << (15 + 16)) | ((n) << 15))
> +#define POSTDIV1(n) ((0x7 << (12 + 16)) | ((n) << 12))
> +#define FBDIV(n) ((0xFFF << 16) | (n))
> +
> +/* CRU_PLL_CON1 */
> +#define RSTMODE(n) ((0x1 << (15 + 16)) | ((n) << 15))
> +#define RST(n) ((0x1 << (14 + 16)) | ((n) << 14))
> +#define PD(n) ((0x1 << (13 + 16)) | ((n) << 13))
> +#define DSMPD(n) ((0x1 << (12 + 16)) | ((n) << 12))
> +#define LOCK(n) (((n) >> 10) & 0x1)
> +#define POSTDIV2(n) ((0x7 << (6 + 16)) | ((n) << 6))
> +#define REFDIV(n) ((0x3F << 16) | (n))
> +
> +/* CRU_MODE */
> +#define CLOCK_FROM_XIN_OSC (0)
> +#define CLOCK_FROM_PLL (1)
> +#define CLOCK_FROM_RTC_32K (2)
> +#define DPLL_MODE(n) ((0x3 << (4 + 16)) | ((n) << 4))
> +
> +/* CRU_SOFTRESET_CON1 */
> +#define upctl2_psrstn_req(n) (((0x1 << 6) << 16) | ((n) << 6))
> +#define upctl2_asrstn_req(n) (((0x1 << 5) << 16) | ((n) << 5))
> +#define upctl2_srstn_req(n) (((0x1 << 4) << 16) | ((n) << 4))
> +
> +/* CRU_SOFTRESET_CON2 */
> +#define ddrphy_psrstn_req(n) (((0x1 << 2) << 16) | ((n) << 2))
> +#define ddrphy_srstn_req(n) (((0x1 << 0) << 16) | ((n) << 0))
> +
> +/* CRU register */
> +#define CRU_PLL_CON(pll_id, n) ((pll_id) * 0x20 + (n) * 4)
> +#define CRU_MODE (0xa0)
> +#define CRU_GLB_CNT_TH (0xb0)
> +#define CRU_CLKSEL_CON_BASE 0x100
> +#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON_BASE + ((i) * 4))
> +#define CRU_CLKGATE_CON_BASE 0x200
> +#define CRU_CLKGATE_CON(i) (CRU_CLKGATE_CON_BASE + ((i) * 4))
> +#define CRU_CLKSFTRST_CON_BASE 0x300
> +#define CRU_CLKSFTRST_CON(i) (CRU_CLKSFTRST_CON_BASE + ((i) * 4))
> +
> +struct px30_ddr_grf_regs {
> + u32 ddr_grf_con[4];
> + u32 reserved1[(0x20 - 0x10) / 4];
> + u32 ddr_grf_lp_con;
> + u32 reserved2[(0x100 - 0x24) / 4];
> + u32 ddr_grf_status[11];
> +};
> +
> +struct px30_msch_timings {
> + u32 ddrtiminga0;
> + u32 ddrtimingb0;
> + u32 ddrtimingc0;
> + u32 devtodev0;
> + u32 ddrmode;
> + u32 ddr4timing;
> + u32 agingx0;
> +};
> +
> +struct px30_sdram_channel {
> + unsigned int rank;
> + unsigned int col;
> + /* 3:8bank, 2:4bank */
> + unsigned int bk;
> + /* channel buswidth, 2:32bit, 1:16bit, 0:8bit */
> + unsigned int bw;
> + /* die buswidth, 2:32bit, 1:16bit, 0:8bit */
> + unsigned int dbw;
> + unsigned int row_3_4;
> + unsigned int cs0_row;
> + unsigned int cs1_row;
> + unsigned int cs0_high16bit_row;
> + unsigned int cs1_high16bit_row;
> + unsigned int ddrconfig;
> + struct px30_msch_timings noc_timings;
> +};
> +
> +struct px30_base_params {
> + unsigned int ddr_freq;
> + unsigned int dramtype;
> + unsigned int num_channels;
> + unsigned int stride;
> + unsigned int odt;
> +};
> +
> +struct px30_sdram_params {
> + struct px30_sdram_channel ch;
> + struct px30_base_params base;
> + struct ddr_pctl_regs pctl_regs;
> + struct ddr_phy_regs phy_regs;
> + struct ddr_phy_skew *skew;
> +};
> +
> +struct px30_msch_regs {
> + u32 coreid;
> + u32 revisionid;
> + u32 deviceconf;
> + u32 devicesize;
> + u32 ddrtiminga0;
> + u32 ddrtimingb0;
> + u32 ddrtimingc0;
> + u32 devtodev0;
> + u32 reserved1[(0x110 - 0x20) / 4];
> + u32 ddrmode;
> + u32 ddr4timing;
> + u32 reserved2[(0x1000 - 0x118) / 4];
> + u32 agingx0;
> + u32 reserved3[(0x1040 - 0x1004) / 4];
> + u32 aging0;
> + u32 aging1;
> + u32 aging2;
> + u32 aging3;
> +};
> +
> +int sdram_init(void);
> +
> +#endif
> diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
> index f5a80b4f0c..116b40a3c5 100644
> --- a/arch/arm/mach-rockchip/Kconfig
> +++ b/arch/arm/mach-rockchip/Kconfig
> @@ -1,5 +1,27 @@
> if ARCH_ROCKCHIP
>
> +config ROCKCHIP_PX30
> + bool "Support Rockchip PX30"
> + select ARM64
> + select SUPPORT_SPL
> + select SUPPORT_TPL
> + select SPL
> + select TPL
> + select TPL_TINY_FRAMEWORK if TPL
This TPL_TINY_FRAMEWORK is not available on upstream, remove it.
Other code looks good for me.
Thanks,
- Kever
> + select TPL_NEEDS_SEPARATE_TEXT_BASE if SPL
> + select TPL_NEEDS_SEPARATE_STACK if TPL
> + imply SPL_SEPARATE_BSS
> + select SPL_SERIAL_SUPPORT
> + select TPL_SERIAL_SUPPORT
> + select DEBUG_UART_BOARD_INIT
> + imply ROCKCHIP_COMMON_BOARD
> + imply SPL_ROCKCHIP_COMMON_BOARD
> + help
> + The Rockchip PX30 is a ARM-based SoC with a quad-core Cortex-A35
> + including NEON and GPU, Mali-400 graphics, several DDR3 options
> + and video codec support. Peripherals include Gigabit Ethernet,
> + USB2 host and OTG, SDIO, I2S, UART, SPI, I2C and PWMs.
> +
> config ROCKCHIP_RK3036
> bool "Support Rockchip RK3036"
> select CPU_V7A
> @@ -315,6 +337,7 @@ config TPL_ROCKCHIP_EARLYRETURN_TO_BROM
> config SPL_MMC_SUPPORT
> default y if !SPL_ROCKCHIP_BACK_TO_BROM
>
> +source "arch/arm/mach-rockchip/px30/Kconfig"
> source "arch/arm/mach-rockchip/rk3036/Kconfig"
> source "arch/arm/mach-rockchip/rk3128/Kconfig"
> source "arch/arm/mach-rockchip/rk3188/Kconfig"
> diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
> index 45d9b06233..ddff566dee 100644
> --- a/arch/arm/mach-rockchip/Makefile
> +++ b/arch/arm/mach-rockchip/Makefile
> @@ -11,6 +11,7 @@ obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o
> obj-spl-$(CONFIG_SPL_ROCKCHIP_COMMON_BOARD) += spl.o spl-boot-order.o
> obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o
> obj-tpl-$(CONFIG_TPL_ROCKCHIP_COMMON_BOARD) += tpl.o
> +obj-tpl-$(CONFIG_ROCKCHIP_PX30) += px30-board-tpl.o
>
> obj-spl-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
>
> @@ -27,6 +28,7 @@ endif
>
> obj-$(CONFIG_$(SPL_TPL_)RAM) += sdram_common.o
>
> +obj-$(CONFIG_ROCKCHIP_PX30) += px30/
> obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/
> obj-$(CONFIG_ROCKCHIP_RK3128) += rk3128/
> obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188/
> diff --git a/arch/arm/mach-rockchip/px30-board-tpl.c b/arch/arm/mach-rockchip/px30-board-tpl.c
> new file mode 100644
> index 0000000000..8c8976f61c
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30-board-tpl.c
> @@ -0,0 +1,59 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2019 Rockchip Electronics Co., Ltd
> + */
> +
> +#include <common.h>
> +#include <debug_uart.h>
> +#include <dm.h>
> +#include <ram.h>
> +#include <spl.h>
> +#include <version.h>
> +#include <asm/io.h>
> +#include <asm/arch-rockchip/bootrom.h>
> +#include <asm/arch-rockchip/sdram_px30.h>
> +
> +#define TIMER_LOAD_COUNT0 0x00
> +#define TIMER_LOAD_COUNT1 0x04
> +#define TIMER_CUR_VALUE0 0x08
> +#define TIMER_CUR_VALUE1 0x0c
> +#define TIMER_CONTROL_REG 0x10
> +
> +#define TIMER_EN 0x1
> +#define TIMER_FMODE (0 << 1)
> +#define TIMER_RMODE (1 << 1)
> +
> +void secure_timer_init(void)
> +{
> + writel(0, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
> + writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_LOAD_COUNT0);
> + writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_LOAD_COUNT1);
> + writel(TIMER_EN | TIMER_FMODE,
> + CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
> +}
> +
> +void board_init_f(ulong dummy)
> +{
> + int ret;
> +
> +#ifdef CONFIG_DEBUG_UART
> + debug_uart_init();
> + /*
> + * Debug UART can be used from here if required:
> + *
> + * debug_uart_init();
> + * printch('a');
> + * printhex8(0x1234);
> + * printascii("string");
> + */
> + printascii("U-Boot TPL board init\n");
> +#endif
> +
> + secure_timer_init();
> + ret = sdram_init();
> + if (ret)
> + printascii("sdram_init failed\n");
> +
> + /* return to maskrom */
> + back_to_bootrom(BROM_BOOT_NEXTSTAGE);
> +}
> diff --git a/arch/arm/mach-rockchip/px30/Kconfig b/arch/arm/mach-rockchip/px30/Kconfig
> new file mode 100644
> index 0000000000..ef04afca8d
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/Kconfig
> @@ -0,0 +1,48 @@
> +if ROCKCHIP_PX30
> +
> +config TARGET_EVB_PX30
> + bool "EVB_PX30"
> +
> +config ROCKCHIP_BOOT_MODE_REG
> + default 0xff010200
> +
> +config SYS_SOC
> + default "px30"
> +
> +config SYS_MALLOC_F_LEN
> + default 0x400
> +
> +config SPL_SERIAL_SUPPORT
> + default y
> +
> +config TPL_LDSCRIPT
> + default "arch/arm/mach-rockchip/u-boot-tpl-v8.lds"
> +
> +config TPL_TEXT_BASE
> + default 0xff0e1000
> +
> +config TPL_MAX_SIZE
> + default 10240
> +
> +config TPL_STACK
> + default 0xff0e4fff
> +
> +config ROCKCHIP_RK3326
> + bool "Support Rockchip RK3326 "
> + help
> + RK3326 can use most code from PX30, but at some situations we have
> + to distinguish between RK3326 and PX30, so this macro gives help.
> + It is usually selected in rk3326 board defconfig.
> +
> +config DEBUG_UART2_CHANNEL
> + int "Mux channel to use for debug UART2"
> + depends on DEBUG_UART_BOARD_INIT
> + default 0
> + help
> + UART2 can use two different set of pins to route the output.
> + For using the UART for early debugging the route to use needs
> + to be declared (0 or 1).
> +
> +source "board/rockchip/evb_px30/Kconfig"
> +
> +endif
> diff --git a/arch/arm/mach-rockchip/px30/Makefile b/arch/arm/mach-rockchip/px30/Makefile
> new file mode 100644
> index 0000000000..6d0742bcab
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/Makefile
> @@ -0,0 +1,14 @@
> +#
> +# (C) Copyright 2017 Rockchip Electronics Co., Ltd.
> +#
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +
> +obj-y += clk_px30.o
> +
> +ifndef CONFIG_TPL_BUILD
> +obj-y += syscon_px30.o
> +endif
> +
> +obj-y += px30.o
> +obj-y += sdram_px30.o
> diff --git a/arch/arm/mach-rockchip/px30/clk_px30.c b/arch/arm/mach-rockchip/px30/clk_px30.c
> new file mode 100644
> index 0000000000..0bd6b471da
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/clk_px30.c
> @@ -0,0 +1,31 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <syscon.h>
> +#include <asm/arch-rockchip/clock.h>
> +#include <asm/arch-rockchip/cru_px30.h>
> +
> +int rockchip_get_clk(struct udevice **devp)
> +{
> + return uclass_get_device_by_driver(UCLASS_CLK,
> + DM_GET_DRIVER(rockchip_px30_cru), devp);
> +}
> +
> +void *rockchip_get_cru(void)
> +{
> + struct px30_clk_priv *priv;
> + struct udevice *dev;
> + int ret;
> +
> + ret = rockchip_get_clk(&dev);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + priv = dev_get_priv(dev);
> +
> + return priv->cru;
> +}
> diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c
> new file mode 100644
> index 0000000000..7cd2292fe2
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/px30.c
> @@ -0,0 +1,248 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2017 Rockchip Electronics Co., Ltd
> + */
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <asm/armv8/mmu.h>
> +#include <asm/io.h>
> +#include <asm/arch-rockchip/grf_px30.h>
> +#include <asm/arch-rockchip/hardware.h>
> +#include <asm/arch-rockchip/uart.h>
> +#include <asm/arch-rockchip/clock.h>
> +#include <asm/arch-rockchip/cru_px30.h>
> +#include <dt-bindings/clock/px30-cru.h>
> +
> +static struct mm_region px30_mem_map[] = {
> + {
> + .virt = 0x0UL,
> + .phys = 0x0UL,
> + .size = 0xff000000UL,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> + PTE_BLOCK_INNER_SHARE
> + }, {
> + .virt = 0xff000000UL,
> + .phys = 0xff000000UL,
> + .size = 0x01000000UL,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> + PTE_BLOCK_NON_SHARE |
> + PTE_BLOCK_PXN | PTE_BLOCK_UXN
> + }, {
> + /* List terminator */
> + 0,
> + }
> +};
> +
> +struct mm_region *mem_map = px30_mem_map;
> +
> +#define PMU_PWRDN_CON 0xff000018
> +#define GRF_BASE 0xff140000
> +#define CRU_BASE 0xff2b0000
> +#define VIDEO_PHY_BASE 0xff2e0000
> +#define SERVICE_CORE_ADDR 0xff508000
> +#define DDR_FW_BASE 0xff534000
> +
> +#define FW_DDR_CON 0x40
> +
> +#define QOS_PRIORITY 0x08
> +
> +#define QOS_PRIORITY_LEVEL(h, l) ((((h) & 3) << 8) | ((l) & 3))
> +
> +/* GRF_GPIO1CL_IOMUX */
> +enum {
> + GPIO1C1_SHIFT = 4,
> + GPIO1C1_MASK = 0xf << GPIO1C1_SHIFT,
> + GPIO1C1_GPIO = 0,
> + GPIO1C1_UART1_TX,
> +
> + GPIO1C0_SHIFT = 0,
> + GPIO1C0_MASK = 0xf << GPIO1C0_SHIFT,
> + GPIO1C0_GPIO = 0,
> + GPIO1C0_UART1_RX,
> +};
> +
> +/* GRF_GPIO1DL_IOMUX */
> +enum {
> + GPIO1D3_SHIFT = 12,
> + GPIO1D3_MASK = 0xf << GPIO1D3_SHIFT,
> + GPIO1D3_GPIO = 0,
> + GPIO1D3_SDMMC_D1,
> + GPIO1D3_UART2_RXM0,
> +
> + GPIO1D2_SHIFT = 8,
> + GPIO1D2_MASK = 0xf << GPIO1D2_SHIFT,
> + GPIO1D2_GPIO = 0,
> + GPIO1D2_SDMMC_D0,
> + GPIO1D2_UART2_TXM0,
> +};
> +
> +/* GRF_GPIO1DH_IOMUX */
> +enum {
> + GPIO1D7_SHIFT = 12,
> + GPIO1D7_MASK = 0xf << GPIO1D7_SHIFT,
> + GPIO1D7_GPIO = 0,
> + GPIO1D7_SDMMC_CMD,
> +
> + GPIO1D6_SHIFT = 8,
> + GPIO1D6_MASK = 0xf << GPIO1D6_SHIFT,
> + GPIO1D6_GPIO = 0,
> + GPIO1D6_SDMMC_CLK,
> +
> + GPIO1D5_SHIFT = 4,
> + GPIO1D5_MASK = 0xf << GPIO1D5_SHIFT,
> + GPIO1D5_GPIO = 0,
> + GPIO1D5_SDMMC_D3,
> +
> + GPIO1D4_SHIFT = 0,
> + GPIO1D4_MASK = 0xf << GPIO1D4_SHIFT,
> + GPIO1D4_GPIO = 0,
> + GPIO1D4_SDMMC_D2,
> +};
> +
> +/* GRF_GPIO2BH_IOMUX */
> +enum {
> + GPIO2B6_SHIFT = 8,
> + GPIO2B6_MASK = 0xf << GPIO2B6_SHIFT,
> + GPIO2B6_GPIO = 0,
> + GPIO2B6_CIF_D1M0,
> + GPIO2B6_UART2_RXM1,
> +
> + GPIO2B4_SHIFT = 0,
> + GPIO2B4_MASK = 0xf << GPIO2B4_SHIFT,
> + GPIO2B4_GPIO = 0,
> + GPIO2B4_CIF_D0M0,
> + GPIO2B4_UART2_TXM1,
> +};
> +
> +/* GRF_GPIO3AL_IOMUX */
> +enum {
> + GPIO3A2_SHIFT = 8,
> + GPIO3A2_MASK = 0xf << GPIO3A2_SHIFT,
> + GPIO3A2_GPIO = 0,
> + GPIO3A2_UART5_TX = 4,
> +
> + GPIO3A1_SHIFT = 4,
> + GPIO3A1_MASK = 0xf << GPIO3A1_SHIFT,
> + GPIO3A1_GPIO = 0,
> + GPIO3A1_UART5_RX = 4,
> +};
> +
> +int arch_cpu_init(void)
> +{
> + static struct px30_grf * const grf = (void *)GRF_BASE;
> + u32 __maybe_unused val;
> +
> +#ifdef CONFIG_SPL_BUILD
> + /* We do some SoC one time setting here. */
> + /* Disable the ddr secure region setting to make it non-secure */
> + writel(0x0, DDR_FW_BASE + FW_DDR_CON);
> +
> + /* Set cpu qos priority */
> + writel(QOS_PRIORITY_LEVEL(1, 1), SERVICE_CORE_ADDR + QOS_PRIORITY);
> +
> +#if !defined(CONFIG_DEBUG_UART_BOARD_INIT) || \
> + (CONFIG_DEBUG_UART_BASE != 0xff160000) || \
> + (CONFIG_DEBUG_UART_CHANNEL != 0)
> + /* fix sdmmc pinmux if not using uart2-channel0 as debug uart */
> + rk_clrsetreg(&grf->gpio1dl_iomux,
> + GPIO1D3_MASK | GPIO1D2_MASK,
> + GPIO1D3_SDMMC_D1 << GPIO1D3_SHIFT |
> + GPIO1D2_SDMMC_D0 << GPIO1D2_SHIFT);
> + rk_clrsetreg(&grf->gpio1dh_iomux,
> + GPIO1D7_MASK | GPIO1D6_MASK | GPIO1D5_MASK | GPIO1D4_MASK,
> + GPIO1D7_SDMMC_CMD << GPIO1D7_SHIFT |
> + GPIO1D6_SDMMC_CLK << GPIO1D6_SHIFT |
> + GPIO1D5_SDMMC_D3 << GPIO1D5_SHIFT |
> + GPIO1D4_SDMMC_D2 << GPIO1D4_SHIFT);
> +#endif
> +
> +#endif
> +
> + /* Enable PD_VO (default disable at reset) */
> + rk_clrreg(PMU_PWRDN_CON, 1 << 13);
> +
> + /* Disable video phy bandgap by default */
> + writel(0x82, VIDEO_PHY_BASE + 0x0000);
> + writel(0x05, VIDEO_PHY_BASE + 0x03ac);
> +
> + /* Clear the force_jtag */
> + rk_clrreg(&grf->cpu_con[1], 1 << 7);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_DEBUG_UART_BOARD_INIT
> +void board_debug_uart_init(void)
> +{
> + static struct px30_grf * const grf = (void *)GRF_BASE;
> + static struct px30_cru * const cru = (void *)CRU_BASE;
> +
> +#if defined(CONFIG_DEBUG_UART_BASE) && (CONFIG_DEBUG_UART_BASE == 0xff158000)
> + /* uart_sel_clk default select 24MHz */
> + rk_clrsetreg(&cru->clksel_con[34],
> + UART1_PLL_SEL_MASK | UART1_DIV_CON_MASK,
> + UART1_PLL_SEL_24M << UART1_PLL_SEL_SHIFT | 0);
> + rk_clrsetreg(&cru->clksel_con[35],
> + UART1_CLK_SEL_MASK,
> + UART1_CLK_SEL_UART1 << UART1_CLK_SEL_SHIFT);
> +
> + rk_clrsetreg(&grf->gpio1cl_iomux,
> + GPIO1C1_MASK | GPIO1C0_MASK,
> + GPIO1C1_UART1_TX << GPIO1C1_SHIFT |
> + GPIO1C0_UART1_RX << GPIO1C0_SHIFT);
> +#elif defined(CONFIG_DEBUG_UART_BASE) && (CONFIG_DEBUG_UART_BASE == 0xff178000)
> + /* uart_sel_clk default select 24MHz */
> + rk_clrsetreg(&cru->clksel_con[46],
> + UART5_PLL_SEL_MASK | UART5_DIV_CON_MASK,
> + UART5_PLL_SEL_24M << UART5_PLL_SEL_SHIFT | 0);
> + rk_clrsetreg(&cru->clksel_con[47],
> + UART5_CLK_SEL_MASK,
> + UART5_CLK_SEL_UART5 << UART5_CLK_SEL_SHIFT);
> +
> + rk_clrsetreg(&grf->gpio3al_iomux,
> + GPIO3A2_MASK | GPIO3A1_MASK,
> + GPIO3A2_UART5_TX << GPIO3A2_SHIFT |
> + GPIO3A1_UART5_RX << GPIO3A1_SHIFT);
> +#else
> + /* GRF_IOFUNC_CON0 */
> + enum {
> + CON_IOMUX_UART2SEL_SHIFT = 10,
> + CON_IOMUX_UART2SEL_MASK = 3 << CON_IOMUX_UART2SEL_SHIFT,
> + CON_IOMUX_UART2SEL_M0 = 0,
> + CON_IOMUX_UART2SEL_M1,
> + CON_IOMUX_UART2SEL_USBPHY,
> + };
> +
> + /* uart_sel_clk default select 24MHz */
> + rk_clrsetreg(&cru->clksel_con[37],
> + UART2_PLL_SEL_MASK | UART2_DIV_CON_MASK,
> + UART2_PLL_SEL_24M << UART2_PLL_SEL_SHIFT | 0);
> + rk_clrsetreg(&cru->clksel_con[38],
> + UART2_CLK_SEL_MASK,
> + UART2_CLK_SEL_UART2 << UART2_CLK_SEL_SHIFT);
> +
> +#if (CONFIG_DEBUG_UART2_CHANNEL == 1)
> + /* Enable early UART2 */
> + rk_clrsetreg(&grf->iofunc_con0,
> + CON_IOMUX_UART2SEL_MASK,
> + CON_IOMUX_UART2SEL_M1 << CON_IOMUX_UART2SEL_SHIFT);
> +
> + rk_clrsetreg(&grf->gpio2bh_iomux,
> + GPIO2B6_MASK | GPIO2B4_MASK,
> + GPIO2B6_UART2_RXM1 << GPIO2B6_SHIFT |
> + GPIO2B4_UART2_TXM1 << GPIO2B4_SHIFT);
> +#else
> + rk_clrsetreg(&grf->iofunc_con0,
> + CON_IOMUX_UART2SEL_MASK,
> + CON_IOMUX_UART2SEL_M0 << CON_IOMUX_UART2SEL_SHIFT);
> +
> + rk_clrsetreg(&grf->gpio1dl_iomux,
> + GPIO1D3_MASK | GPIO1D2_MASK,
> + GPIO1D3_UART2_RXM0 << GPIO1D3_SHIFT |
> + GPIO1D2_UART2_TXM0 << GPIO1D2_SHIFT);
> +#endif /* CONFIG_DEBUG_UART2_CHANNEL == 1 */
> +
> +#endif /* CONFIG_DEBUG_UART_BASE && CONFIG_DEBUG_UART_BASE == ... */
> +}
> +#endif /* CONFIG_DEBUG_UART_BOARD_INIT */
> diff --git a/arch/arm/mach-rockchip/px30/sdram-px30-ddr3-detect-333.inc b/arch/arm/mach-rockchip/px30/sdram-px30-ddr3-detect-333.inc
> new file mode 100644
> index 0000000000..e17b2ed86c
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/sdram-px30-ddr3-detect-333.inc
> @@ -0,0 +1,70 @@
> +{
> + {
> + .rank = 0x1,
> + .col = 0xC,
> + .bk = 0x3,
> + .bw = 0x1,
> + .dbw = 0x0,
> + .row_3_4 = 0x0,
> + .cs0_row = 0x10,
> + .cs1_row = 0x10,
> + .cs0_high16bit_row = 0x10,
> + .cs1_high16bit_row = 0x10,
> + .ddrconfig = 0,
> + {
> + 0x290b0609,
> + 0x08020401,
> + 0x00000002,
> + 0x00001111,
> + 0x0000000c,
> + 0x00000222,
> + 0x000000ff
> + }
> + },
> + {
> + .ddr_freq = 333,
> + .dramtype = DDR3,
> + .num_channels = 1,
> + .stride = 0,
> + .odt = 0,
> + },
> + {
> + {
> + {0x00000000, 0x43041001}, /* MSTR */
> + {0x00000064, 0x0028003b}, /* RFSHTMG */
> + {0x000000d0, 0x00020053}, /* INIT0 */
> + {0x000000d4, 0x00020000}, /* INIT1 */
> + {0x000000d8, 0x00000100}, /* INIT2 */
> + {0x000000dc, 0x03200000}, /* INIT3 */
> + {0x000000e0, 0x00000000}, /* INIT4 */
> + {0x000000e4, 0x00090000}, /* INIT5 */
> + {0x000000f4, 0x000f012f}, /* RANKCTL */
> + {0x00000100, 0x07090b06}, /* DRAMTMG0 */
> + {0x00000104, 0x00050209}, /* DRAMTMG1 */
> + {0x00000108, 0x03030407}, /* DRAMTMG2 */
> + {0x0000010c, 0x00202006}, /* DRAMTMG3 */
> + {0x00000110, 0x03020204}, /* DRAMTMG4 */
> + {0x00000114, 0x03030202}, /* DRAMTMG5 */
> + {0x00000120, 0x00000903}, /* DRAMTMG8 */
> + {0x00000180, 0x00800020}, /* ZQCTL0 */
> + {0x00000184, 0x00000000}, /* ZQCTL1 */
> + {0x00000190, 0x07010001}, /* DFITMG0 */
> + {0x00000198, 0x07000101}, /* DFILPCFG0 */
> + {0x000001a0, 0xc0400003}, /* DFIUPD0 */
> + {0x00000240, 0x06000604}, /* ODTCFG */
> + {0x00000244, 0x00000201}, /* ODTMAP */
> + {0x00000250, 0x00001f00}, /* SCHED */
> + {0x00000490, 0x00000001}, /* PCTRL_0 */
> + {0xffffffff, 0xffffffff}
> + }
> + },
> + {
> + {
> + {0x00000004, 0x0000000a}, /* PHYREG01 */
> + {0x00000028, 0x00000006}, /* PHYREG0A */
> + {0x0000002c, 0x00000000}, /* PHYREG0B */
> + {0x00000030, 0x00000005}, /* PHYREG0C */
> + {0xffffffff, 0xffffffff}
> + }
> + }
> +},
> diff --git a/arch/arm/mach-rockchip/px30/sdram-px30-ddr4-detect-333.inc b/arch/arm/mach-rockchip/px30/sdram-px30-ddr4-detect-333.inc
> new file mode 100644
> index 0000000000..cdc417405a
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/sdram-px30-ddr4-detect-333.inc
> @@ -0,0 +1,73 @@
> +{
> + {
> + .rank = 0x1,
> + .col = 0xA,
> + .bk = 0x2,
> + .bw = 0x1,
> + .dbw = 0x0,
> + .row_3_4 = 0x0,
> + .cs0_row = 0x11,
> + .cs1_row = 0x0,
> + .cs0_high16bit_row = 0x11,
> + .cs1_high16bit_row = 0x0,
> + .ddrconfig = 0,
> + {
> + 0x4d110a08,
> + 0x06020501,
> + 0x00000002,
> + 0x00001111,
> + 0x0000000c,
> + 0x0000022a,
> + 0x000000ff
> + }
> + },
> + {
> + .ddr_freq = 333,
> + .dramtype = DDR4,
> + .num_channels = 1,
> + .stride = 0,
> + .odt = 0,
> + },
> + {
> + {
> + {0x00000000, 0x43049010}, /* MSTR */
> + {0x00000064, 0x0028003b}, /* RFSHTMG */
> + {0x000000d0, 0x00020053}, /* INIT0 */
> + {0x000000d4, 0x00220000}, /* INIT1 */
> + {0x000000d8, 0x00000100}, /* INIT2 */
> + {0x000000dc, 0x00040000}, /* INIT3 */
> + {0x000000e0, 0x00000000}, /* INIT4 */
> + {0x000000e4, 0x00110000}, /* INIT5 */
> + {0x000000e8, 0x00000420}, /* INIT6 */
> + {0x000000ec, 0x00000400}, /* INIT7 */
> + {0x000000f4, 0x000f012f}, /* RANKCTL */
> + {0x00000100, 0x09060b06}, /* DRAMTMG0 */
> + {0x00000104, 0x00020209}, /* DRAMTMG1 */
> + {0x00000108, 0x0505040a}, /* DRAMTMG2 */
> + {0x0000010c, 0x0040400c}, /* DRAMTMG3 */
> + {0x00000110, 0x05030206}, /* DRAMTMG4 */
> + {0x00000114, 0x03030202}, /* DRAMTMG5 */
> + {0x00000120, 0x03030b03}, /* DRAMTMG8 */
> + {0x00000124, 0x00020208}, /* DRAMTMG9 */
> + {0x00000180, 0x01000040}, /* ZQCTL0 */
> + {0x00000184, 0x00000000}, /* ZQCTL1 */
> + {0x00000190, 0x07030003}, /* DFITMG0 */
> + {0x00000198, 0x07000101}, /* DFILPCFG0 */
> + {0x000001a0, 0xc0400003}, /* DFIUPD0 */
> + {0x00000240, 0x06000604}, /* ODTCFG */
> + {0x00000244, 0x00000201}, /* ODTMAP */
> + {0x00000250, 0x00001f00}, /* SCHED */
> + {0x00000490, 0x00000001}, /* PCTRL_0 */
> + {0xffffffff, 0xffffffff}
> + }
> + },
> + {
> + {
> + {0x00000004, 0x0000000c}, /* PHYREG01 */
> + {0x00000028, 0x0000000a}, /* PHYREG0A */
> + {0x0000002c, 0x00000000}, /* PHYREG0B */
> + {0x00000030, 0x00000009}, /* PHYREG0C */
> + {0xffffffff, 0xffffffff}
> + }
> + }
> +},
> \ No newline at end of file
> diff --git a/arch/arm/mach-rockchip/px30/sdram-px30-ddr_skew.inc b/arch/arm/mach-rockchip/px30/sdram-px30-ddr_skew.inc
> new file mode 100644
> index 0000000000..f24343dda1
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/sdram-px30-ddr_skew.inc
> @@ -0,0 +1,121 @@
> + {
> + 0x77,
> + 0x88,
> + 0x79,
> + 0x79,
> + 0x87,
> + 0x97,
> + 0x87,
> + 0x78,
> + 0x77,
> + 0x78,
> + 0x87,
> + 0x88,
> + 0x87,
> + 0x87,
> + 0x77
> + },
> + {
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x69,
> + 0x9,
> + },
> + {
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x79,
> + 0x9,
> + },
> + {
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x69,
> + 0x9,
> + },
> + {
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x79,
> + 0x9,
> + },
> + {
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x69,
> + 0x9,
> + },
> + {
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x79,
> + 0x9,
> + },
> + {
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x78,
> + 0x69,
> + 0x9,
> + },
> + {
> + 0x77,
> + 0x78,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x77,
> + 0x79,
> + 0x9,
> + }
> diff --git a/arch/arm/mach-rockchip/px30/sdram-px30-lpddr2-detect-333.inc b/arch/arm/mach-rockchip/px30/sdram-px30-lpddr2-detect-333.inc
> new file mode 100644
> index 0000000000..3bde062d62
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/sdram-px30-lpddr2-detect-333.inc
> @@ -0,0 +1,71 @@
> +{
> + {
> + .rank = 0x1,
> + .col = 0xC,
> + .bk = 0x3,
> + .bw = 0x1,
> + .dbw = 0x0,
> + .row_3_4 = 0x0,
> + .cs0_row = 0xF,
> + .cs1_row = 0xF,
> + .cs0_high16bit_row = 0xF,
> + .cs1_high16bit_row = 0xF,
> + .ddrconfig = 0,
> + {
> + 0x2b0c070a,
> + 0x08020303,
> + 0x00000002,
> + 0x00001111,
> + 0x0000000c,
> + 0x00000219,
> + 0x000000ff
> + }
> + },
> + {
> + .ddr_freq = 333,
> + .dramtype = LPDDR2,
> + .num_channels = 1,
> + .stride = 0,
> + .odt = 0,
> + },
> + {
> + {
> + {0x00000000, 0x41041004}, /* MSTR */
> + {0x00000064, 0x00140023}, /* RFSHTMG */
> + {0x000000d0, 0x00220002}, /* INIT0 */
> + {0x000000d4, 0x00010000}, /* INIT1 */
> + {0x000000d8, 0x00000703}, /* INIT2 */
> + {0x000000dc, 0x00630005}, /* INIT3 */
> + {0x000000e0, 0x00010000}, /* INIT4 */
> + {0x000000e4, 0x00070003}, /* INIT5 */
> + {0x000000f4, 0x000f012f}, /* RANKCTL */
> + {0x00000100, 0x07090b07}, /* DRAMTMG0 */
> + {0x00000104, 0x0002010b}, /* DRAMTMG1 */
> + {0x00000108, 0x02040506}, /* DRAMTMG2 */
> + {0x0000010c, 0x00303000}, /* DRAMTMG3 */
> + {0x00000110, 0x04010204}, /* DRAMTMG4 */
> + {0x00000114, 0x01010303}, /* DRAMTMG5 */
> + {0x00000118, 0x02020003}, /* DRAMTMG6 */
> + {0x00000120, 0x00000303}, /* DRAMTMG8 */
> + {0x00000138, 0x00000025}, /* DRAMTMG14 */
> + {0x00000180, 0x003c000f}, /* ZQCTL0 */
> + {0x00000184, 0x00900000}, /* ZQCTL1 */
> + {0x00000190, 0x07020001}, /* DFITMG0 */
> + {0x00000198, 0x07000101}, /* DFILPCFG0 */
> + {0x000001a0, 0xc0400003}, /* DFIUPD0 */
> + {0x00000240, 0x07030718}, /* ODTCFG */
> + {0x00000250, 0x00001f00}, /* SCHED */
> + {0x00000490, 0x00000001}, /* PCTRL_0 */
> + {0xffffffff, 0xffffffff}
> + }
> + },
> + {
> + {
> + {0x00000004, 0x00000009}, /* PHYREG01 */
> + {0x00000028, 0x00000007}, /* PHYREG0A */
> + {0x0000002c, 0x00000000}, /* PHYREG0B */
> + {0x00000030, 0x00000004}, /* PHYREG0C */
> + {0xffffffff, 0xffffffff}
> + }
> + }
> +},
> diff --git a/arch/arm/mach-rockchip/px30/sdram-px30-lpddr3-detect-333.inc b/arch/arm/mach-rockchip/px30/sdram-px30-lpddr3-detect-333.inc
> new file mode 100644
> index 0000000000..a205fc9332
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/sdram-px30-lpddr3-detect-333.inc
> @@ -0,0 +1,72 @@
> +{
> + {
> + .rank = 0x1,
> + .col = 0xC,
> + .bk = 0x3,
> + .bw = 0x1,
> + .dbw = 0x0,
> + .row_3_4 = 0x0,
> + .cs0_row = 0x10,
> + .cs1_row = 0x10,
> + .cs0_high16bit_row = 0x10,
> + .cs1_high16bit_row = 0x10,
> + .ddrconfig = 0,
> + {
> + 0x290a060a,
> + 0x08020303,
> + 0x00000002,
> + 0x00001111,
> + 0x0000000c,
> + 0x0000021a,
> + 0x000000ff
> + }
> + },
> + {
> + .ddr_freq = 333,
> + .dramtype = LPDDR3,
> + .num_channels = 1,
> + .stride = 0,
> + .odt = 0,
> + },
> + {
> + {
> + {0x00000000, 0x43041008}, /* MSTR */
> + {0x00000064, 0x00140023}, /* RFSHTMG */
> + {0x000000d0, 0x00220002}, /* INIT0 */
> + {0x000000d4, 0x00010000}, /* INIT1 */
> + {0x000000d8, 0x00000703}, /* INIT2 */
> + {0x000000dc, 0x00830004}, /* INIT3 */
> + {0x000000e0, 0x00010000}, /* INIT4 */
> + {0x000000e4, 0x00070003}, /* INIT5 */
> + {0x000000f4, 0x000f012f}, /* RANKCTL */
> + {0x00000100, 0x06090b07}, /* DRAMTMG0 */
> + {0x00000104, 0x0002020b}, /* DRAMTMG1 */
> + {0x00000108, 0x02030506}, /* DRAMTMG2 */
> + {0x0000010c, 0x00505000}, /* DRAMTMG3 */
> + {0x00000110, 0x03020204}, /* DRAMTMG4 */
> + {0x00000114, 0x01010303}, /* DRAMTMG5 */
> + {0x00000118, 0x02020003}, /* DRAMTMG6 */
> + {0x00000120, 0x00000303}, /* DRAMTMG8 */
> + {0x00000138, 0x00000025}, /* DRAMTMG14 */
> + {0x00000180, 0x003c000f}, /* ZQCTL0 */
> + {0x00000184, 0x00900000}, /* ZQCTL1 */
> + {0x00000190, 0x07020000}, /* DFITMG0 */
> + {0x00000198, 0x07000101}, /* DFILPCFG0 */
> + {0x000001a0, 0xc0400003}, /* DFIUPD0 */
> + {0x00000240, 0x0900090c}, /* ODTCFG */
> + {0x00000244, 0x00000101}, /* ODTMAP */
> + {0x00000250, 0x00001f00}, /* SCHED */
> + {0x00000490, 0x00000001}, /* PCTRL_0 */
> + {0xffffffff, 0xffffffff}
> + }
> + },
> + {
> + {
> + {0x00000004, 0x0000000b}, /* PHYREG01 */
> + {0x00000028, 0x00000006}, /* PHYREG0A */
> + {0x0000002c, 0x00000000}, /* PHYREG0B */
> + {0x00000030, 0x00000003}, /* PHYREG0C */
> + {0xffffffff, 0xffffffff}
> + }
> + }
> +},
> diff --git a/arch/arm/mach-rockchip/px30/sdram_px30.c b/arch/arm/mach-rockchip/px30/sdram_px30.c
> new file mode 100644
> index 0000000000..2590d9366e
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/sdram_px30.c
> @@ -0,0 +1,1405 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
> + */
> +
> +#include <common.h>
> +#include <debug_uart.h>
> +#include <dm.h>
> +#include <ram.h>
> +#include <syscon.h>
> +#include <asm/io.h>
> +#include <asm/arch-rockchip/clock.h>
> +#include <asm/arch-rockchip/cru_px30.h>
> +#include <asm/arch-rockchip/grf_px30.h>
> +#include <asm/arch-rockchip/hardware.h>
> +#include <asm/arch-rockchip/sdram_common.h>
> +#include <asm/arch-rockchip/sdram_px30.h>
> +
> +#define TIMER_CUR_VALUE0 0x08
> +#define TIMER_CUR_VALUE1 0x0c
> +
> +static u64 rockchip_get_ticks(void)
> +{
> + u64 timebase_h, timebase_l;
> +
> + timebase_l = readl(CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CUR_VALUE0);
> + timebase_h = readl(CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CUR_VALUE1);
> +
> + return timebase_h << 32 | timebase_l;
> +}
> +
> +void rockchip_udelay(unsigned int usec)
> +{
> + u64 tmp;
> +
> + /* get timestamp */
> + tmp = rockchip_get_ticks() + usec_to_tick(usec);
> +
> + /* loop till event */
> + while (rockchip_get_ticks() < tmp + 1)
> + ;
> +}
> +
> +u8 ddr_cfg_2_rbc[] = {
> + /*
> + * [6:4] max row: 13+n
> + * [3] bank(0:4bank,1:8bank)
> + * [2:0] col(10+n)
> + */
> + ((5 << 4) | (1 << 3) | 0), /* 0 */
> + ((5 << 4) | (1 << 3) | 1), /* 1 */
> + ((4 << 4) | (1 << 3) | 2), /* 2 */
> + ((3 << 4) | (1 << 3) | 3), /* 3 */
> + ((2 << 4) | (1 << 3) | 4), /* 4 */
> + ((5 << 4) | (0 << 3) | 2), /* 5 */
> + ((4 << 4) | (1 << 3) | 2), /* 6 */
> +};
> +
> +#ifdef CONFIG_TPL_BUILD
> +
> +/*
> + * for ddr4 if ddrconfig=7, upctl should set 7 and noc should
> + * set to 1 for more efficient.
> + * noc ddrconf, upctl addrmap
> + * 1 7
> + * 2 8
> + * 3 9
> + * 12 10
> + * 5 11
> + */
> +static u8 d4_rbc_2_d3_rbc[] = {
> + 1, /* 7 */
> + 2, /* 8 */
> + 3, /* 9 */
> + 12, /* 10 */
> + 5, /* 11 */
> +};
> +
> +/*
> + * row higher than cs should be disabled by set to 0xf
> + * rank addrmap calculate by real cap.
> + */
> +static u32 addrmap[][8] = {
> + /* map0 map1, map2, map3, map4, map5
> + * map6, map7, map8
> + * -------------------------------------------------------
> + * bk2-0 col 5-2 col 9-6 col 11-10 row 11-0
> + * row 15-12 row 17-16 bg1,0
> + * -------------------------------------------------------
> + * 4,3,2 5-2 9-6 6
> + * 3,2
> + */
> + {0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505,
> + 0x05050505, 0x00000505, 0x3f3f}, /* 0 */
> + {0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
> + 0x06060606, 0x06060606, 0x3f3f}, /* 1 */
> + {0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
> + 0x07070707, 0x00000f07, 0x3f3f}, /* 2 */
> + {0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
> + 0x08080808, 0x00000f0f, 0x3f3f}, /* 3 */
> + {0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
> + 0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */
> + {0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
> + 0x06060606, 0x00000606, 0x3f3f}, /* 5 */
> + {0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
> + 0x07070707, 0x00000f0f, 0x3f3f}, /* 6 */
> + {0x003f0808, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606,
> + 0x06060606, 0x00000606, 0x0600}, /* 7 */
> + {0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
> + 0x07070707, 0x00000f07, 0x0700}, /* 8 */
> + {0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
> + 0x08080808, 0x00000f0f, 0x0801}, /* 9 */
> + {0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
> + 0x07070707, 0x00000f07, 0x3f01}, /* 10 */
> + {0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
> + 0x06060606, 0x00000606, 0x3f00}, /* 11 */
> + /* when ddr4 12 map to 10, when ddr3 12 unused */
> + {0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
> + 0x07070707, 0x00000f07, 0x3f01}, /* 10 */
> + {0x00070706, 0x00000000, 0x1f010000, 0x00001f1f, 0x06060606,
> + 0x06060606, 0x00000606, 0x3f3f}, /* 13 */
> +};
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +struct dram_info {
> + struct ddr_pctl_regs *pctl;
> + struct ddr_phy_regs *phy;
> + struct px30_cru *cru;
> + struct px30_msch_regs *msch;
> + struct px30_ddr_grf_regs *ddr_grf;
> + struct px30_grf *grf;
> + struct ram_info info;
> + struct px30_pmugrf *pmugrf;
> +};
> +
> +#define PMUGRF_BASE_ADDR 0xFF010000
> +#define CRU_BASE_ADDR 0xFF2B0000
> +#define GRF_BASE_ADDR 0xFF140000
> +#define DDRC_BASE_ADDR 0xFF600000
> +#define DDR_PHY_BASE_ADDR 0xFF2A0000
> +#define SERVER_MSCH0_BASE_ADDR 0xFF530000
> +#define DDR_GRF_BASE_ADDR 0xff630000
> +
> +struct dram_info dram_info;
> +
> +struct px30_sdram_params sdram_configs[] = {
> +#include "sdram-px30-ddr3-detect-333.inc"
> +};
> +
> +struct ddr_phy_skew skew = {
> +#include "sdram-px30-ddr_skew.inc"
> +};
> +
> +#define PATTERN (0x5aa5f00f)
> +
> +/*
> + * cs: 0:cs0
> + * 1:cs1
> + * else cs0+cs1
> + * note: it didn't consider about row_3_4
> + */
> +u64 sdram_get_cs_cap(struct px30_sdram_channel *cap_info, u32 cs, u32 dram_type)
> +{
> + u32 bg;
> + u64 cap[2];
> +
> + if (dram_type == DDR4)
> + /* DDR4 8bit dram BG = 2(4bank groups),
> + * 16bit dram BG = 1 (2 bank groups)
> + */
> + bg = (cap_info->dbw == 0) ? 2 : 1;
> + else
> + bg = 0;
> + cap[0] = 1llu << (cap_info->bw + cap_info->col +
> + bg + cap_info->bk + cap_info->cs0_row);
> +
> + if (cap_info->rank == 2)
> + cap[1] = 1llu << (cap_info->bw + cap_info->col +
> + bg + cap_info->bk + cap_info->cs1_row);
> + else
> + cap[1] = 0;
> +
> + if (cs == 0)
> + return cap[0];
> + else if (cs == 1)
> + return cap[1];
> + else
> + return (cap[0] + cap[1]);
> +}
> +
> +/* n: Unit bytes */
> +void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n)
> +{
> + int i;
> +
> + for (i = 0; i < n / sizeof(u32); i++) {
> + writel(*src, dest);
> + src++;
> + dest++;
> + }
> +}
> +
> +static void sdram_phy_dll_bypass_set(void __iomem *phy_base, u32 freq)
> +{
> + u32 tmp;
> + u32 i, j;
> +
> + setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
> + clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
> + for (i = 0; i < 4; i++) {
> + j = 0x26 + i * 0x10;
> + setbits_le32(PHY_REG(phy_base, j), 1 << 4);
> + clrbits_le32(PHY_REG(phy_base, j + 0x1), 1 << 3);
> + }
> +
> + if (freq <= (400000000))
> + /* DLL bypass */
> + setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
> + else
> + clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
> +
> + if (freq <= (801000000))
> + tmp = 2;
> + else
> + tmp = 1;
> +
> + for (i = 0; i < 4; i++) {
> + j = 0x28 + i * 0x10;
> + writel(tmp, PHY_REG(phy_base, j));
> + }
> +}
> +
> +static void sdram_phy_set_ds_odt(void __iomem *phy_base,
> + u32 dram_type)
> +{
> + u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
> + u32 i, j;
> +
> + if (dram_type == DDR3) {
> + cmd_drv = PHY_DDR3_RON_RTT_34ohm;
> + clk_drv = PHY_DDR3_RON_RTT_45ohm;
> + dqs_drv = PHY_DDR3_RON_RTT_34ohm;
> + dqs_odt = PHY_DDR3_RON_RTT_225ohm;
> + } else {
> + cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
> + clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
> + dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
> + if (dram_type == LPDDR2)
> + dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_DISABLE;
> + else
> + dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
> + }
> + /* DS */
> + writel(cmd_drv, PHY_REG(phy_base, 0x11));
> + clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
> + writel(clk_drv, PHY_REG(phy_base, 0x16));
> + writel(clk_drv, PHY_REG(phy_base, 0x18));
> +
> + for (i = 0; i < 4; i++) {
> + j = 0x20 + i * 0x10;
> + writel(dqs_drv, PHY_REG(phy_base, j));
> + writel(dqs_drv, PHY_REG(phy_base, j + 0xf));
> + /* ODT */
> + writel(dqs_odt, PHY_REG(phy_base, j + 0x1));
> + writel(dqs_odt, PHY_REG(phy_base, j + 0xe));
> + }
> +}
> +
> +static void phy_soft_reset(void __iomem *phy_base)
> +{
> + clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
> + udelay(1);
> + setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
> + udelay(5);
> + setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
> + udelay(1);
> +}
> +
> +static void phy_dram_set_bw(void __iomem *phy_base, u32 bw)
> +{
> + if (bw == 2) {
> + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
> + setbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
> + setbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
> + } else if (bw == 1) {
> + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
> + clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
> + clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
> + } else if (bw == 0) {
> + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
> + clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
> + clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
> + clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
> + }
> +
> + phy_soft_reset(phy_base);
> +}
> +
> +static int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype)
> +{
> + u32 ret;
> + u32 odt_val;
> + u32 i, j;
> +
> + odt_val = readl(PHY_REG(phy_base, 0x2e));
> +
> + for (i = 0; i < 4; i++) {
> + j = 0x20 + i * 0x10;
> + writel(PHY_DDR3_RON_RTT_225ohm, PHY_REG(phy_base, j + 0x1));
> + writel(0, PHY_REG(phy_base, j + 0xe));
> + }
> +
> + if (dramtype == DDR4) {
> + clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
> + clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
> + clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
> + clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
> + }
> + /* choose training cs */
> + clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
> + /* enable gate training */
> + clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
> + udelay(50);
> + ret = readl(PHY_REG(phy_base, 0xff));
> + /* disable gate training */
> + clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
> + clrbits_le32(PHY_REG(phy_base, 2), 0x30);
> +
> + if (dramtype == DDR4) {
> + clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
> + clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
> + clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
> + clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
> + }
> +
> + if (ret & 0x10) {
> + ret = -1;
> + } else {
> + ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
> + ret = (ret == 0) ? 0 : -1;
> + }
> +
> + for (i = 0; i < 4; i++) {
> + j = 0x20 + i * 0x10;
> + writel(odt_val, PHY_REG(phy_base, j + 0x1));
> + writel(odt_val, PHY_REG(phy_base, j + 0xe));
> + }
> +
> + return ret;
> +}
> +
> +static void phy_cfg(void __iomem *phy_base,
> + struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew,
> + struct px30_base_params *base, u32 bw)
> +{
> + u32 i;
> +
> + sdram_phy_dll_bypass_set(phy_base, base->ddr_freq);
> + for (i = 0; phy_regs->phy[i][0] != 0xFFFFFFFF; i++) {
> + writel(phy_regs->phy[i][1],
> + phy_base + phy_regs->phy[i][0]);
> + }
> + if (bw == 2) {
> + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
> + } else if (bw == 1) {
> + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
> + /* disable DQS2,DQS3 tx dll for saving power */
> + clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
> + clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
> + } else {
> + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
> + /* disable DQS2,DQS3 tx dll for saving power */
> + clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
> + clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
> + clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
> + }
> + sdram_phy_set_ds_odt(phy_base, base->dramtype);
> +
> + /* deskew */
> + setbits_le32(PHY_REG(phy_base, 2), 8);
> + sdram_copy_to_reg(PHY_REG(phy_base, 0xb0),
> + &skew->a0_a1_skew[0], 15 * 4);
> + sdram_copy_to_reg(PHY_REG(phy_base, 0x70),
> + &skew->cs0_dm0_skew[0], 44 * 4);
> + sdram_copy_to_reg(PHY_REG(phy_base, 0xc0),
> + &skew->cs1_dm0_skew[0], 44 * 4);
> +}
> +
> +void sdram_org_config(struct px30_sdram_channel *info,
> + struct px30_base_params *base,
> + u32 *p_os_reg2, u32 *p_os_reg3, u32 channel)
> +{
> + *p_os_reg2 |= base->dramtype << SYS_REG_DDRTYPE_SHIFT;
> + *p_os_reg2 |= (base->num_channels - 1) << SYS_REG_NUM_CH_SHIFT;
> + *p_os_reg2 |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(channel);
> + *p_os_reg2 |= 1 << SYS_REG_CHINFO_SHIFT(channel);
> + *p_os_reg2 |= (info->rank - 1) << SYS_REG_RANK_SHIFT(channel);
> + *p_os_reg2 |= (info->col - 9) << SYS_REG_COL_SHIFT(channel);
> + *p_os_reg2 |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(channel);
> + *p_os_reg2 |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(channel);
> + if (info->cs1_row >= 13)
> + *p_os_reg2 |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(channel);
> + *p_os_reg2 |= (2 >> info->bw) << SYS_REG_BW_SHIFT(channel);
> + *p_os_reg2 |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(channel);
> +}
> +
> +void sdram_msch_config(struct px30_msch_regs *msch,
> + struct px30_msch_timings *noc_timings,
> + struct px30_sdram_channel *cap_info,
> + struct px30_base_params *base)
> +{
> + u64 cs_cap[2];
> +
> + cs_cap[0] = sdram_get_cs_cap(cap_info, 0, base->dramtype);
> + cs_cap[1] = sdram_get_cs_cap(cap_info, 1, base->dramtype);
> + writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) |
> + (((cs_cap[0] >> 20) / 64) & 0xff),
> + &msch->devicesize);
> +
> + writel(noc_timings->ddrtiminga0, &msch->ddrtiminga0);
> + writel(noc_timings->ddrtimingb0, &msch->ddrtimingb0);
> + writel(noc_timings->ddrtimingc0, &msch->ddrtimingc0);
> + writel(noc_timings->devtodev0, &msch->devtodev0);
> + writel(noc_timings->ddrmode, &msch->ddrmode);
> + writel(noc_timings->ddr4timing, &msch->ddr4timing);
> + writel(noc_timings->agingx0, &msch->agingx0);
> + writel(noc_timings->agingx0, &msch->aging0);
> + writel(noc_timings->agingx0, &msch->aging1);
> + writel(noc_timings->agingx0, &msch->aging2);
> + writel(noc_timings->agingx0, &msch->aging3);
> +}
> +
> +int sdram_detect_bw(struct px30_sdram_channel *cap_info)
> +{
> + return 0;
> +}
> +
> +int sdram_detect_cs(struct px30_sdram_channel *cap_info)
> +{
> + return 0;
> +}
> +
> +int sdram_detect_col(struct px30_sdram_channel *cap_info,
> + u32 coltmp)
> +{
> + void __iomem *test_addr;
> + u32 col;
> + u32 bw = cap_info->bw;
> +
> + for (col = coltmp; col >= 9; col -= 1) {
> + writel(0, CONFIG_SYS_SDRAM_BASE);
> + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
> + (1ul << (col + bw - 1ul)));
> + writel(PATTERN, test_addr);
> + if ((readl(test_addr) == PATTERN) &&
> + (readl(CONFIG_SYS_SDRAM_BASE) == 0))
> + break;
> + }
> + if (col == 8) {
> + printascii("col error\n");
> + return -1;
> + }
> +
> + cap_info->col = col;
> +
> + return 0;
> +}
> +
> +int sdram_detect_bank(struct px30_sdram_channel *cap_info,
> + u32 coltmp, u32 bktmp)
> +{
> + void __iomem *test_addr;
> + u32 bk;
> + u32 bw = cap_info->bw;
> +
> + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
> + (1ul << (coltmp + bktmp + bw - 1ul)));
> + writel(0, CONFIG_SYS_SDRAM_BASE);
> + writel(PATTERN, test_addr);
> + if ((readl(test_addr) == PATTERN) &&
> + (readl(CONFIG_SYS_SDRAM_BASE) == 0))
> + bk = 3;
> + else
> + bk = 2;
> +
> + cap_info->bk = bk;
> +
> + return 0;
> +}
> +
> +/* detect bg for ddr4 */
> +int sdram_detect_bg(struct px30_sdram_channel *cap_info,
> + u32 coltmp)
> +{
> + void __iomem *test_addr;
> + u32 dbw;
> + u32 bw = cap_info->bw;
> +
> + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
> + (1ul << (coltmp + bw + 1ul)));
> + writel(0, CONFIG_SYS_SDRAM_BASE);
> + writel(PATTERN, test_addr);
> + if ((readl(test_addr) == PATTERN) &&
> + (readl(CONFIG_SYS_SDRAM_BASE) == 0))
> + dbw = 0;
> + else
> + dbw = 1;
> +
> + cap_info->dbw = dbw;
> +
> + return 0;
> +}
> +
> +/* detect dbw for ddr3,lpddr2,lpddr3,lpddr4 */
> +int sdram_detect_dbw(struct px30_sdram_channel *cap_info, u32 dram_type)
> +{
> + u32 row, col, bk, bw, cs_cap, cs;
> + u32 die_bw_0 = 0, die_bw_1 = 0;
> +
> + if (dram_type == DDR3 || dram_type == LPDDR4) {
> + cap_info->dbw = 1;
> + } else if (dram_type == LPDDR3 || dram_type == LPDDR2) {
> + row = cap_info->cs0_row;
> + col = cap_info->col;
> + bk = cap_info->bk;
> + cs = cap_info->rank;
> + bw = cap_info->bw;
> + cs_cap = (1 << (row + col + bk + bw - 20));
> + if (bw == 2) {
> + if (cs_cap <= 0x2000000) /* 256Mb */
> + die_bw_0 = (col < 9) ? 2 : 1;
> + else if (cs_cap <= 0x10000000) /* 2Gb */
> + die_bw_0 = (col < 10) ? 2 : 1;
> + else if (cs_cap <= 0x40000000) /* 8Gb */
> + die_bw_0 = (col < 11) ? 2 : 1;
> + else
> + die_bw_0 = (col < 12) ? 2 : 1;
> + if (cs > 1) {
> + row = cap_info->cs1_row;
> + cs_cap = (1 << (row + col + bk + bw - 20));
> + if (cs_cap <= 0x2000000) /* 256Mb */
> + die_bw_0 = (col < 9) ? 2 : 1;
> + else if (cs_cap <= 0x10000000) /* 2Gb */
> + die_bw_0 = (col < 10) ? 2 : 1;
> + else if (cs_cap <= 0x40000000) /* 8Gb */
> + die_bw_0 = (col < 11) ? 2 : 1;
> + else
> + die_bw_0 = (col < 12) ? 2 : 1;
> + }
> + } else {
> + die_bw_1 = 1;
> + die_bw_0 = 1;
> + }
> + cap_info->dbw = (die_bw_0 > die_bw_1) ? die_bw_0 : die_bw_1;
> + }
> +
> + return 0;
> +}
> +
> +int sdram_detect_row(struct px30_sdram_channel *cap_info,
> + u32 coltmp, u32 bktmp, u32 rowtmp)
> +{
> + u32 row;
> + u32 bw = cap_info->bw;
> + void __iomem *test_addr;
> +
> + for (row = rowtmp; row > 12; row--) {
> + writel(0, CONFIG_SYS_SDRAM_BASE);
> + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
> + (1ul << (row + bktmp + coltmp + bw - 1ul)));
> + writel(PATTERN, test_addr);
> + if ((readl(test_addr) == PATTERN) &&
> + (readl(CONFIG_SYS_SDRAM_BASE) == 0))
> + break;
> + }
> + if (row == 12) {
> + printascii("row error");
> + return -1;
> + }
> +
> + cap_info->cs0_row = row;
> +
> + return 0;
> +}
> +
> +int sdram_detect_row_3_4(struct px30_sdram_channel *cap_info,
> + u32 coltmp, u32 bktmp)
> +{
> + u32 row_3_4;
> + u32 bw = cap_info->bw;
> + u32 row = cap_info->cs0_row;
> + void __iomem *test_addr, *test_addr1;
> +
> + test_addr = CONFIG_SYS_SDRAM_BASE;
> + test_addr1 = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
> + (0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
> +
> + writel(0, test_addr);
> + writel(PATTERN, test_addr1);
> + if ((readl(test_addr) == 0) && (readl(test_addr1) == PATTERN))
> + row_3_4 = 0;
> + else
> + row_3_4 = 1;
> +
> + cap_info->row_3_4 = row_3_4;
> +
> + return 0;
> +}
> +
> +int sdram_detect_high_row(struct px30_sdram_channel *cap_info)
> +{
> + cap_info->cs0_high16bit_row = cap_info->cs0_row;
> + cap_info->cs1_high16bit_row = cap_info->cs1_row;
> +
> + return 0;
> +}
> +
> +int sdram_detect_cs1_row(struct px30_sdram_channel *cap_info, u32 dram_type)
> +{
> + void __iomem *test_addr;
> + u32 row = 0, bktmp, coltmp, bw;
> + ulong cs0_cap;
> + u32 byte_mask;
> +
> + if (cap_info->rank == 2) {
> + cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
> +
> + if (dram_type == DDR4) {
> + if (cap_info->dbw == 0)
> + bktmp = cap_info->bk + 2;
> + else
> + bktmp = cap_info->bk + 1;
> + } else {
> + bktmp = cap_info->bk;
> + }
> + bw = cap_info->bw;
> + coltmp = cap_info->col;
> +
> + /*
> + * because px30 support axi split,min bandwidth
> + * is 8bit. if cs0 is 32bit, cs1 may 32bit or 16bit
> + * so we check low 16bit data when detect cs1 row.
> + * if cs0 is 16bit/8bit, we check low 8bit data.
> + */
> + if (bw == 2)
> + byte_mask = 0xFFFF;
> + else
> + byte_mask = 0xFF;
> +
> + /* detect cs1 row */
> + for (row = cap_info->cs0_row; row > 12; row--) {
> + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
> + cs0_cap +
> + (1ul << (row + bktmp + coltmp + bw - 1ul)));
> + writel(0, CONFIG_SYS_SDRAM_BASE + cs0_cap);
> + writel(PATTERN, test_addr);
> +
> + if (((readl(test_addr) & byte_mask) ==
> + (PATTERN & byte_mask)) &&
> + ((readl(CONFIG_SYS_SDRAM_BASE + cs0_cap) &
> + byte_mask) == 0)) {
> + break;
> + }
> + }
> + }
> +
> + cap_info->cs1_row = row;
> +
> + return 0;
> +}
> +
> +static void rkclk_ddr_reset(struct dram_info *dram,
> + u32 ctl_srstn, u32 ctl_psrstn,
> + u32 phy_srstn, u32 phy_psrstn)
> +{
> + writel(upctl2_srstn_req(ctl_srstn) | upctl2_psrstn_req(ctl_psrstn) |
> + upctl2_asrstn_req(ctl_srstn),
> + &dram->cru->softrst_con[1]);
> + writel(ddrphy_srstn_req(phy_srstn) | ddrphy_psrstn_req(phy_psrstn),
> + &dram->cru->softrst_con[2]);
> +}
> +
> +static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
> +{
> + unsigned int refdiv, postdiv1, postdiv2, fbdiv;
> + int delay = 1000;
> + u32 mhz = hz / MHz;
> +
> + refdiv = 1;
> + if (mhz <= 300) {
> + postdiv1 = 4;
> + postdiv2 = 2;
> + } else if (mhz <= 400) {
> + postdiv1 = 6;
> + postdiv2 = 1;
> + } else if (mhz <= 600) {
> + postdiv1 = 4;
> + postdiv2 = 1;
> + } else if (mhz <= 800) {
> + postdiv1 = 3;
> + postdiv2 = 1;
> + } else if (mhz <= 1600) {
> + postdiv1 = 2;
> + postdiv2 = 1;
> + } else {
> + postdiv1 = 1;
> + postdiv2 = 1;
> + }
> + fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
> +
> + writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode);
> +
> + writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0);
> + writel(DSMPD(1) | POSTDIV2(postdiv2) | REFDIV(refdiv),
> + &dram->cru->pll[1].con1);
> +
> + while (delay > 0) {
> + rockchip_udelay(1);
> + if (LOCK(readl(&dram->cru->pll[1].con1)))
> + break;
> + delay--;
> + }
> +
> + writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode);
> +}
> +
> +static void rkclk_configure_ddr(struct dram_info *dram,
> + struct px30_sdram_params *sdram_params)
> +{
> + /* for inno ddr phy need 2*freq */
> + rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHz * 2);
> +}
> +
> +/* return ddrconfig value
> + * (-1), find ddrconfig fail
> + * other, the ddrconfig value
> + * only support cs0_row >= cs1_row
> + */
> +static unsigned int calculate_ddrconfig(struct px30_sdram_params *sdram_params)
> +{
> + struct px30_sdram_channel *cap_info = &sdram_params->ch;
> + u32 bw, die_bw, col, bank;
> + u32 i, tmp;
> + u32 ddrconf = -1;
> +
> + bw = cap_info->bw;
> + die_bw = cap_info->dbw;
> + col = cap_info->col;
> + bank = cap_info->bk;
> +
> + if (sdram_params->base.dramtype == DDR4) {
> + if (die_bw == 0)
> + ddrconf = 7 + bw;
> + else
> + ddrconf = 12 - bw;
> + ddrconf = d4_rbc_2_d3_rbc[ddrconf - 7];
> + } else {
> + tmp = ((bank - 2) << 3) | (col + bw - 10);
> + for (i = 0; i < 7; i++)
> + if ((ddr_cfg_2_rbc[i] & 0xf) == tmp) {
> + ddrconf = i;
> + break;
> + }
> + if (i > 6)
> + printascii("calculate ddrconfig error\n");
> + }
> +
> + return ddrconf;
> +}
> +
> +/*
> + * rank = 1: cs0
> + * rank = 2: cs1
> + */
> +static void pctl_read_mr(void __iomem *pctl_base, u32 rank, u32 mr_num)
> +{
> + writel((rank << 4) | (1 << 0), pctl_base + DDR_PCTL2_MRCTRL0);
> + writel((mr_num << 8), pctl_base + DDR_PCTL2_MRCTRL1);
> + setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
> + while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
> + continue;
> + while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
> + continue;
> +}
> +
> +/* rank = 1: cs0
> + * rank = 2: cs1
> + * rank = 3: cs0 & cs1
> + * note: be careful of keep mr original val
> + */
> +static int pctl_write_mr(void __iomem *pctl_base, u32 rank, u32 mr_num, u32 arg,
> + u32 dramtype)
> +{
> + while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
> + continue;
> + if (dramtype == DDR3 || dramtype == DDR4) {
> + writel((mr_num << 12) | (rank << 4) | (0 << 0),
> + pctl_base + DDR_PCTL2_MRCTRL0);
> + writel(arg, pctl_base + DDR_PCTL2_MRCTRL1);
> + } else {
> + writel((rank << 4) | (0 << 0),
> + pctl_base + DDR_PCTL2_MRCTRL0);
> + writel((mr_num << 8) | (arg & 0xff),
> + pctl_base + DDR_PCTL2_MRCTRL1);
> + }
> +
> + setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
> + while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
> + continue;
> + while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
> + continue;
> +
> + return 0;
> +}
> +
> +static int upctl2_update_ref_reg(void __iomem *pctl_base)
> +{
> + u32 ret;
> +
> + ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
> + writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
> +
> + return 0;
> +}
> +
> +static u32 pctl_dis_zqcs_aref(void __iomem *pctl_base)
> +{
> + u32 dis_auto_zq = 0;
> +
> + /* disable zqcs */
> + if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) &
> + (1ul << 31))) {
> + dis_auto_zq = 1;
> + setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
> + }
> +
> + /* disable auto refresh */
> + setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
> +
> + upctl2_update_ref_reg(pctl_base);
> +
> + return dis_auto_zq;
> +}
> +
> +static void pctl_rest_zqcs_aref(void __iomem *pctl_base, u32 dis_auto_zq)
> +{
> + /* restore zqcs */
> + if (dis_auto_zq)
> + clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
> +
> + /* restore auto refresh */
> + clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
> +
> + upctl2_update_ref_reg(pctl_base);
> +}
> +
> +/*
> + * rank : 1:cs0, 2:cs1, 3:cs0&cs1
> + * vrefrate: 4500: 45%,
> + */
> +static int pctl_write_vrefdq(void __iomem *pctl_base, u32 rank, u32 vrefrate,
> + u32 dramtype)
> +{
> + u32 tccd_l, value;
> + u32 dis_auto_zq = 0;
> +
> + if (dramtype != DDR4 || vrefrate < 4500 ||
> + vrefrate > 9200)
> + return (-1);
> +
> + tccd_l = (readl(pctl_base + DDR_PCTL2_DRAMTMG4) >> 16) & 0xf;
> + tccd_l = (tccd_l - 4) << 10;
> +
> + if (vrefrate > 7500) {
> + /* range 1 */
> + value = ((vrefrate - 6000) / 65) | tccd_l;
> + } else {
> + /* range 2 */
> + value = ((vrefrate - 4500) / 65) | tccd_l | (1 << 6);
> + }
> +
> + dis_auto_zq = pctl_dis_zqcs_aref(pctl_base);
> +
> + /* enable vrefdq calibratin */
> + pctl_write_mr(pctl_base, rank, 6, value | (1 << 7), dramtype);
> + udelay(1);/* tvrefdqe */
> + /* write vrefdq value */
> + pctl_write_mr(pctl_base, rank, 6, value | (1 << 7), dramtype);
> + udelay(1);/* tvref_time */
> + pctl_write_mr(pctl_base, rank, 6, value | (0 << 7), dramtype);
> + udelay(1);/* tvrefdqx */
> +
> + pctl_rest_zqcs_aref(pctl_base, dis_auto_zq);
> +
> + return 0;
> +}
> +
> +static u32 pctl_remodify_sdram_params(struct ddr_pctl_regs *pctl_regs,
> + struct px30_sdram_channel *cap_info,
> + u32 dram_type)
> +{
> + u32 tmp = 0, tmp_adr = 0, i;
> +
> + for (i = 0; pctl_regs->pctl[i][0] != 0xFFFFFFFF; i++) {
> + if (pctl_regs->pctl[i][0] == 0) {
> + tmp = pctl_regs->pctl[i][1];/* MSTR */
> + tmp_adr = i;
> + }
> + }
> +
> + tmp &= ~((3ul << 30) | (3ul << 24) | (3ul << 12));
> +
> + switch (cap_info->dbw) {
> + case 2:
> + tmp |= (3ul << 30);
> + break;
> + case 1:
> + tmp |= (2ul << 30);
> + break;
> + case 0:
> + default:
> + tmp |= (1ul << 30);
> + break;
> + }
> +
> + /*
> + * If DDR3 or DDR4 MSTR.active_ranks=1,
> + * it will gate memory clock when enter power down.
> + * Force set active_ranks to 3 to workaround it.
> + */
> + if (cap_info->rank == 2 || dram_type == DDR3 ||
> + dram_type == DDR4)
> + tmp |= 3 << 24;
> + else
> + tmp |= 1 << 24;
> +
> + tmp |= (2 - cap_info->bw) << 12;
> +
> + pctl_regs->pctl[tmp_adr][1] = tmp;
> +
> + return 0;
> +}
> +
> +static int pctl_cfg(void __iomem *pctl_base, struct ddr_pctl_regs *pctl_regs,
> + u32 sr_idle, u32 pd_idle)
> +{
> + u32 i;
> +
> + for (i = 0; pctl_regs->pctl[i][0] != 0xFFFFFFFF; i++) {
> + writel(pctl_regs->pctl[i][1],
> + pctl_base + pctl_regs->pctl[i][0]);
> + }
> + clrsetbits_le32(pctl_base + DDR_PCTL2_PWRTMG,
> + (0xff << 16) | 0x1f,
> + ((sr_idle & 0xff) << 16) | (pd_idle & 0x1f));
> +
> + clrsetbits_le32(pctl_base + DDR_PCTL2_HWLPCTL,
> + 0xfff << 16,
> + 5 << 16);
> + /* disable zqcs */
> + setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1u << 31);
> +
> + return 0;
> +}
> +
> +/*
> + * calculate controller dram address map, and setting to register.
> + * argument sdram_params->ch.ddrconf must be right value before
> + * call this function.
> + */
> +static void set_ctl_address_map(struct dram_info *dram,
> + struct px30_sdram_params *sdram_params)
> +{
> + struct px30_sdram_channel *cap_info = &sdram_params->ch;
> + void __iomem *pctl_base = dram->pctl;
> + u32 cs_pst, bg, max_row, ddrconf;
> + u32 i;
> +
> + if (sdram_params->base.dramtype == DDR4)
> + /*
> + * DDR4 8bit dram BG = 2(4bank groups),
> + * 16bit dram BG = 1 (2 bank groups)
> + */
> + bg = (cap_info->dbw == 0) ? 2 : 1;
> + else
> + bg = 0;
> +
> + cs_pst = cap_info->bw + cap_info->col +
> + bg + cap_info->bk + cap_info->cs0_row;
> + if (cs_pst >= 32 || cap_info->rank == 1)
> + writel(0x1f, pctl_base + DDR_PCTL2_ADDRMAP0);
> + else
> + writel(cs_pst - 8, pctl_base + DDR_PCTL2_ADDRMAP0);
> +
> + ddrconf = cap_info->ddrconfig;
> + if (sdram_params->base.dramtype == DDR4) {
> + for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc); i++) {
> + if (d4_rbc_2_d3_rbc[i] == ddrconf) {
> + ddrconf = 7 + i;
> + break;
> + }
> + }
> + }
> +
> + sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP1),
> + &addrmap[ddrconf][0], 8 * 4);
> + max_row = cs_pst - 1 - 8 - (addrmap[ddrconf][5] & 0xf);
> +
> + if (max_row < 12)
> + printascii("set addrmap fail\n");
> + /* need to disable row ahead of rank by set to 0xf */
> + for (i = 17; i > max_row; i--)
> + clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 +
> + ((i - 12) * 8 / 32) * 4,
> + 0xf << ((i - 12) * 8 % 32),
> + 0xf << ((i - 12) * 8 % 32));
> +
> + if ((sdram_params->base.dramtype == LPDDR3 ||
> + sdram_params->base.dramtype == LPDDR2) &&
> + cap_info->row_3_4)
> + setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
> + if (sdram_params->base.dramtype == DDR4 && cap_info->bw != 0x2)
> + setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
> +}
> +
> +/*
> + * rank = 1: cs0
> + * rank = 2: cs1
> + */
> +int read_mr(struct dram_info *dram, u32 rank, u32 mr_num)
> +{
> + void __iomem *ddr_grf_base = dram->ddr_grf;
> +
> + pctl_read_mr(dram->pctl, rank, mr_num);
> +
> + return (readl(ddr_grf_base + DDR_GRF_STATUS(0)) & 0xff);
> +}
> +
> +#define MIN(a, b) (((a) > (b)) ? (b) : (a))
> +#define MAX(a, b) (((a) > (b)) ? (a) : (b))
> +static u32 check_rd_gate(struct dram_info *dram)
> +{
> + void __iomem *phy_base = dram->phy;
> +
> + u32 max_val = 0;
> + u32 min_val = 0xff;
> + u32 gate[4];
> + u32 i, bw;
> +
> + bw = (readl(PHY_REG(phy_base, 0x0)) >> 4) & 0xf;
> + switch (bw) {
> + case 0x1:
> + bw = 1;
> + break;
> + case 0x3:
> + bw = 2;
> + break;
> + case 0xf:
> + default:
> + bw = 4;
> + break;
> + }
> +
> + for (i = 0; i < bw; i++) {
> + gate[i] = readl(PHY_REG(phy_base, 0xfb + i));
> + max_val = MAX(max_val, gate[i]);
> + min_val = MIN(min_val, gate[i]);
> + }
> +
> + if (max_val > 0x80 || min_val < 0x20)
> + return -1;
> + else
> + return 0;
> +}
> +
> +static int data_training(struct dram_info *dram, u32 cs, u32 dramtype)
> +{
> + void __iomem *pctl_base = dram->pctl;
> + u32 dis_auto_zq = 0;
> + u32 pwrctl;
> + u32 ret;
> +
> + /* disable auto low-power */
> + pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
> + writel(0, pctl_base + DDR_PCTL2_PWRCTL);
> +
> + dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
> +
> + ret = phy_data_training(dram->phy, cs, dramtype);
> +
> + pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
> +
> + /* restore auto low-power */
> + writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
> +
> + return ret;
> +}
> +
> +static void dram_set_bw(struct dram_info *dram, u32 bw)
> +{
> + phy_dram_set_bw(dram->phy, bw);
> +}
> +
> +static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
> +{
> + writel(ddrconfig | (ddrconfig << 8), &dram->msch->deviceconf);
> + rk_clrsetreg(&dram->grf->soc_noc_con[1], 0x3 << 14, 0 << 14);
> +}
> +
> +static void dram_all_config(struct dram_info *dram,
> + struct px30_sdram_params *sdram_params)
> +{
> + struct px30_sdram_channel *cap_info = &sdram_params->ch;
> + u32 sys_reg2 = 0;
> + u32 sys_reg3 = 0;
> +
> + set_ddrconfig(dram, cap_info->ddrconfig);
> + sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
> + &sys_reg3, 0);
> + writel(sys_reg2, &dram->pmugrf->os_reg[2]);
> + writel(sys_reg3, &dram->pmugrf->os_reg[3]);
> + sdram_msch_config(dram->msch, &sdram_params->ch.noc_timings, cap_info,
> + &sdram_params->base);
> +}
> +
> +static void enable_low_power(struct dram_info *dram,
> + struct px30_sdram_params *sdram_params)
> +{
> + void __iomem *pctl_base = dram->pctl;
> + void __iomem *phy_base = dram->phy;
> + void __iomem *ddr_grf_base = dram->ddr_grf;
> + u32 grf_lp_con;
> +
> + /*
> + * bit0: grf_upctl_axi_cg_en = 1 enable upctl2 axi clk auto gating
> + * bit1: grf_upctl_apb_cg_en = 1 ungated axi,core clk for apb access
> + * bit2: grf_upctl_core_cg_en = 1 enable upctl2 core clk auto gating
> + * bit3: grf_selfref_type2_en = 0 disable core clk gating when type2 sr
> + * bit4: grf_upctl_syscreq_cg_en = 1
> + * ungating coreclk when c_sysreq assert
> + * bit8-11: grf_auto_sr_dly = 6
> + */
> + writel(0x1f1f0617, &dram->ddr_grf->ddr_grf_con[1]);
> +
> + if (sdram_params->base.dramtype == DDR4)
> + grf_lp_con = (0x7 << 16) | (1 << 1);
> + else if (sdram_params->base.dramtype == DDR3)
> + grf_lp_con = (0x7 << 16) | (1 << 0);
> + else
> + grf_lp_con = (0x7 << 16) | (1 << 2);
> +
> + /* en lpckdis_en */
> + grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9);
> + writel(grf_lp_con, ddr_grf_base + DDR_GRF_LP_CON);
> +
> + /* off digit module clock when enter power down */
> + setbits_le32(PHY_REG(phy_base, 7), 1 << 7);
> +
> + /* enable sr, pd */
> + if (PD_IDLE == 0)
> + clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
> + else
> + setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
> + if (SR_IDLE == 0)
> + clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
> + else
> + setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
> + setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
> +}
> +
> +/*
> + * pre_init: 0: pre init for dram cap detect
> + * 1: detect correct cap(except cs1 row)info, than reinit
> + * 2: after reinit, we detect cs1_row, if cs1_row not equal
> + * to cs0_row and cs is in middle on ddrconf map, we need
> + * to reinit dram, than set the correct ddrconf.
> + */
> +static int sdram_init_(struct dram_info *dram,
> + struct px30_sdram_params *sdram_params, u32 pre_init)
> +{
> + struct px30_sdram_channel *cap_info = &sdram_params->ch;
> + void __iomem *pctl_base = dram->pctl;
> +
> + rkclk_ddr_reset(dram, 1, 1, 1, 1);
> + rockchip_udelay(10);
> + /*
> + * dereset ddr phy psrstn to config pll,
> + * if using phy pll psrstn must be dereset
> + * before config pll
> + */
> + rkclk_ddr_reset(dram, 1, 1, 1, 0);
> + rkclk_configure_ddr(dram, sdram_params);
> +
> + /* release phy srst to provide clk to ctrl */
> + rkclk_ddr_reset(dram, 1, 1, 0, 0);
> + rockchip_udelay(10);
> + phy_soft_reset(dram->phy);
> +
> + /* release ctrl presetn, and config ctl registers */
> + rkclk_ddr_reset(dram, 1, 0, 0, 0);
> + pctl_cfg(dram->pctl, &sdram_params->pctl_regs, SR_IDLE, PD_IDLE);
> + cap_info->ddrconfig = calculate_ddrconfig(sdram_params);
> + set_ctl_address_map(dram, sdram_params);
> + phy_cfg(dram->phy, &sdram_params->phy_regs, sdram_params->skew,
> + &sdram_params->base, cap_info->bw);
> +
> + /* enable dfi_init_start to init phy after ctl srstn deassert */
> + setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
> +
> + rkclk_ddr_reset(dram, 0, 0, 0, 0);
> + /* wait for dfi_init_done and dram init complete */
> + while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0)
> + continue;
> +
> + if (sdram_params->base.dramtype == LPDDR3)
> + pctl_write_mr(dram->pctl, 3, 11, 3, LPDDR3);
> +
> + /* do ddr gate training */
> +redo_cs0_training:
> + if (data_training(dram, 0, sdram_params->base.dramtype) != 0) {
> + if (pre_init != 0)
> + printascii("DTT cs0 error\n");
> + return -1;
> + }
> + if (check_rd_gate(dram)) {
> + printascii("re training cs0");
> + goto redo_cs0_training;
> + }
> +
> + if (sdram_params->base.dramtype == LPDDR3) {
> + if ((read_mr(dram, 1, 8) & 0x3) != 0x3)
> + return -1;
> + } else if (sdram_params->base.dramtype == LPDDR2) {
> + if ((read_mr(dram, 1, 8) & 0x3) != 0x0)
> + return -1;
> + }
> +
> + /* for px30: when 2cs, both 2 cs should be training */
> + if (pre_init != 0 && cap_info->rank == 2) {
> +redo_cs1_training:
> + if (data_training(dram, 1, sdram_params->base.dramtype) != 0) {
> + printascii("DTT cs1 error\n");
> + return -1;
> + }
> + if (check_rd_gate(dram)) {
> + printascii("re training cs1");
> + goto redo_cs1_training;
> + }
> + }
> +
> + if (sdram_params->base.dramtype == DDR4)
> + pctl_write_vrefdq(dram->pctl, 0x3, 5670,
> + sdram_params->base.dramtype);
> +
> + dram_all_config(dram, sdram_params);
> + enable_low_power(dram, sdram_params);
> +
> + return 0;
> +}
> +
> +static int dram_detect_cap(struct dram_info *dram,
> + struct px30_sdram_params *sdram_params,
> + unsigned char channel)
> +{
> + struct px30_sdram_channel *cap_info = &sdram_params->ch;
> +
> + /*
> + * for ddr3: ddrconf = 3
> + * for ddr4: ddrconf = 12
> + * for lpddr3: ddrconf = 3
> + * default bw = 1
> + */
> + u32 bk, bktmp;
> + u32 col, coltmp;
> + u32 rowtmp;
> + u32 cs;
> + u32 bw = 1;
> + u32 dram_type = sdram_params->base.dramtype;
> +
> + if (dram_type != DDR4) {
> + /* detect col and bk for ddr3/lpddr3 */
> + coltmp = 12;
> + bktmp = 3;
> + if (dram_type == LPDDR2)
> + rowtmp = 15;
> + else
> + rowtmp = 16;
> +
> + if (sdram_detect_col(cap_info, coltmp) != 0)
> + goto cap_err;
> + sdram_detect_bank(cap_info, coltmp, bktmp);
> + sdram_detect_dbw(cap_info, dram_type);
> + } else {
> + /* detect bg for ddr4 */
> + coltmp = 10;
> + bktmp = 4;
> + rowtmp = 17;
> +
> + col = 10;
> + bk = 2;
> + cap_info->col = col;
> + cap_info->bk = bk;
> + sdram_detect_bg(cap_info, coltmp);
> + }
> +
> + /* detect row */
> + if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
> + goto cap_err;
> +
> + /* detect row_3_4 */
> + sdram_detect_row_3_4(cap_info, coltmp, bktmp);
> +
> + /* bw and cs detect using data training */
> + if (data_training(dram, 1, dram_type) == 0)
> + cs = 1;
> + else
> + cs = 0;
> + cap_info->rank = cs + 1;
> +
> + dram_set_bw(dram, 2);
> + if (data_training(dram, 0, dram_type) == 0)
> + bw = 2;
> + else
> + bw = 1;
> + cap_info->bw = bw;
> +
> + cap_info->cs0_high16bit_row = cap_info->cs0_row;
> + if (cs) {
> + cap_info->cs1_row = cap_info->cs0_row;
> + cap_info->cs1_high16bit_row = cap_info->cs0_row;
> + } else {
> + cap_info->cs1_row = 0;
> + cap_info->cs1_high16bit_row = 0;
> + }
> +
> + return 0;
> +cap_err:
> + return -1;
> +}
> +
> +static int sdram_init_detect(struct dram_info *dram,
> + struct px30_sdram_params *sdram_params)
> +{
> + struct px30_sdram_channel *cap_info = &sdram_params->ch;
> + u32 ret;
> + u32 sys_reg = 0;
> + u32 sys_reg3 = 0;
> +
> + if (sdram_init_(dram, sdram_params, 0) != 0)
> + return -1;
> +
> + if (dram_detect_cap(dram, sdram_params, 0) != 0)
> + return -1;
> +
> + /* modify bw, cs related timing */
> + pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
> + sdram_params->base.dramtype);
> + /* reinit sdram by real dram cap */
> + ret = sdram_init_(dram, sdram_params, 1);
> + if (ret != 0)
> + goto out;
> +
> + /* redetect cs1 row */
> + sdram_detect_cs1_row(cap_info, sdram_params->base.dramtype);
> + if (cap_info->cs1_row) {
> + sys_reg = readl(&dram->pmugrf->os_reg[2]);
> + sys_reg3 = readl(&dram->pmugrf->os_reg[3]);
> + writel(sys_reg, &dram->pmugrf->os_reg[2]);
> + writel(sys_reg3, &dram->pmugrf->os_reg[3]);
> + }
> +
> + ret = sdram_detect_high_row(cap_info);
> +
> +out:
> + return ret;
> +}
> +
> +struct px30_sdram_params *get_default_sdram_config(void)
> +{
> + sdram_configs[0].skew = &skew;
> +
> + return &sdram_configs[0];
> +}
> +
> +int sdram_init(void)
> +{
> + struct px30_sdram_params *sdram_params;
> + int ret = 0;
> +
> + dram_info.phy = (void *)DDR_PHY_BASE_ADDR;
> + dram_info.pctl = (void *)DDRC_BASE_ADDR;
> + dram_info.grf = (void *)GRF_BASE_ADDR;
> + dram_info.cru = (void *)CRU_BASE_ADDR;
> + dram_info.msch = (void *)SERVER_MSCH0_BASE_ADDR;
> + dram_info.ddr_grf = (void *)DDR_GRF_BASE_ADDR;
> + dram_info.pmugrf = (void *)PMUGRF_BASE_ADDR;
> +
> + sdram_params = get_default_sdram_config();
> + ret = sdram_init_detect(&dram_info, sdram_params);
> + if (ret)
> + return ret;
> +
> + return ret;
> +}
> +#endif /* CONFIG_TPL_BUILD */
> diff --git a/arch/arm/mach-rockchip/px30/syscon_px30.c b/arch/arm/mach-rockchip/px30/syscon_px30.c
> new file mode 100644
> index 0000000000..0331491b40
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/px30/syscon_px30.c
> @@ -0,0 +1,53 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) Copyright 2017 Rockchip Electronics Co., Ltd
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <syscon.h>
> +#include <asm/arch-rockchip/clock.h>
> +
> +static const struct udevice_id px30_syscon_ids[] = {
> + { .compatible = "rockchip,px30-pmu", .data = ROCKCHIP_SYSCON_PMU },
> + { .compatible = "rockchip,px30-pmugrf", .data = ROCKCHIP_SYSCON_PMUGRF },
> + { .compatible = "rockchip,px30-grf", .data = ROCKCHIP_SYSCON_GRF },
> + { }
> +};
> +
> +U_BOOT_DRIVER(syscon_px30) = {
> + .id = UCLASS_SYSCON,
> + .name = "px30_syscon",
> + .of_match = px30_syscon_ids,
> +};
> +
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +static int px30_syscon_bind_of_platdata(struct udevice *dev)
> +{
> + dev->driver_data = dev->driver->of_match->data;
> + debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
> +
> + return 0;
> +}
> +
> +U_BOOT_DRIVER(rockchip_px30_pmu) = {
> + .name = "rockchip_px30_pmu",
> + .id = UCLASS_SYSCON,
> + .of_match = px30_syscon_ids,
> + .bind = px30_syscon_bind_of_platdata,
> +};
> +
> +U_BOOT_DRIVER(rockchip_px30_pmugrf) = {
> + .name = "rockchip_px30_pmugrf",
> + .id = UCLASS_SYSCON,
> + .of_match = px30_syscon_ids + 1,
> + .bind = px30_syscon_bind_of_platdata,
> +};
> +
> +U_BOOT_DRIVER(rockchip_px30_grf) = {
> + .name = "rockchip_px30_grf",
> + .id = UCLASS_SYSCON,
> + .of_match = px30_syscon_ids + 2,
> + .bind = px30_syscon_bind_of_platdata,
> +};
> +#endif
More information about the U-Boot
mailing list