From mboxrd@z Thu Jan 1 00:00:00 1970 From: hl Date: Mon, 09 Nov 2015 11:29:01 +0800 Subject: [U-Boot] [RESEND PATCH v3 15/20] rockchip: add rk3036 sdram driver In-Reply-To: References: <1446803622-31966-1-git-send-email-hl@rock-chips.com> <1446803622-31966-16-git-send-email-hl@rock-chips.com> Message-ID: <564012FD.9080907@rock-chips.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Simon, On 07/11/15 07:58, Simon Glass wrote: > Hi Lin, > > On 6 November 2015 at 01:53, Lin Huang wrote: >> add rk3036 sdram driver so we can set up sdram in SPL >> >> Signed-off-by: Lin Huang >> --- >> Changes in v1: None >> Changes in v2: None >> Changes in v3: fix some code style error >> >> arch/arm/include/asm/arch-rockchip/sdram_rk3036.h | 336 ++++++++++ >> arch/arm/mach-rockchip/rk3036/Makefile | 2 + >> arch/arm/mach-rockchip/rk3036/sdram_rk3036.c | 729 ++++++++++++++++++++++ >> 3 files changed, 1067 insertions(+) >> create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_rk3036.h >> create mode 100644 arch/arm/mach-rockchip/rk3036/sdram_rk3036.c >> > Just a few nits. > >> diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3036.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3036.h >> new file mode 100644 >> index 0000000..76c8b5b >> --- /dev/null >> +++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3036.h >> @@ -0,0 +1,336 @@ >> +/* >> + * (C) Copyright 2015 Rockchip Electronics Co., Ltd >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + */ >> +#ifndef _ASM_ARCH_SDRAM_RK3036_H >> +#define _ASM_ARCH_SDRAM_RK3036_H >> + >> +#include >> + >> +struct rk3036_ddr_pctl { >> + u32 scfg; >> + u32 sctl; >> + u32 stat; >> + u32 intrstat; >> + u32 reserved0[12]; >> + u32 mcmd; >> + u32 powctl; >> + u32 powstat; >> + u32 cmdtstat; >> + u32 cmdtstaten; >> + u32 reserved1[3]; >> + u32 mrrcfg0; >> + u32 mrrstat0; >> + u32 mrrstat1; >> + u32 reserved2[4]; >> + u32 mcfg1; >> + u32 mcfg; >> + u32 ppcfg; >> + u32 mstat; >> + u32 lpddr2zqcfg; >> + u32 reserved3; >> + u32 dtupdes; >> + u32 dtuna; >> + u32 dtune; >> + u32 dtuprd0; >> + u32 dtuprd1; >> + u32 dtuprd2; >> + u32 dtuprd3; >> + u32 dtuawdt; >> + u32 reserved4[3]; >> + u32 togcnt1u; >> + u32 tinit; >> + u32 trsth; >> + u32 togcnt100n; >> + u32 trefi; >> + u32 tmrd; >> + u32 trfc; >> + u32 trp; >> + u32 trtw; >> + u32 tal; >> + u32 tcl; >> + u32 tcwl; >> + u32 tras; >> + u32 trc; >> + u32 trcd; >> + u32 trrd; >> + u32 trtp; >> + u32 twr; >> + u32 twtr; >> + u32 texsr; >> + u32 txp; >> + u32 txpdll; >> + u32 tzqcs; >> + u32 tzqcsi; >> + u32 tdqs; >> + u32 tcksre; >> + u32 tcksrx; >> + u32 tcke; >> + u32 tmod; >> + u32 trstl; >> + u32 tzqcl; >> + u32 tmrr; >> + u32 tckesr; >> + u32 reserved5[47]; >> + u32 dtuwactl; >> + u32 dturactl; >> + u32 dtucfg; >> + u32 dtuectl; >> + u32 dtuwd0; >> + u32 dtuwd1; >> + u32 dtuwd2; >> + u32 dtuwd3; >> + u32 dtuwdm; >> + u32 dturd0; >> + u32 dturd1; >> + u32 dturd2; >> + u32 dturd3; >> + u32 dtulfsrwd; >> + u32 dtulfsrrd; >> + u32 dtueaf; >> + u32 dfitctrldelay; >> + u32 dfiodtcfg; >> + u32 dfiodtcfg1; >> + u32 dfiodtrankmap; >> + u32 dfitphywrdata; >> + u32 dfitphywrlat; >> + u32 reserved7[2]; >> + u32 dfitrddataen; >> + u32 dfitphyrdlat; >> + u32 reserved8[2]; >> + u32 dfitphyupdtype0; >> + u32 dfitphyupdtype1; >> + u32 dfitphyupdtype2; >> + u32 dfitphyupdtype3; >> + u32 dfitctrlupdmin; >> + u32 dfitctrlupdmax; >> + u32 dfitctrlupddly; >> + u32 reserved9; >> + u32 dfiupdcfg; >> + u32 dfitrefmski; >> + u32 dfitctrlupdi; >> + u32 reserved10[4]; >> + u32 dfitrcfg0; >> + u32 dfitrstat0; >> + u32 dfitrwrlvlen; >> + u32 dfitrrdlvlen; >> + u32 dfitrrdlvlgateen; >> + u32 dfiststat0; >> + u32 dfistcfg0; >> + u32 dfistcfg1; >> + u32 reserved11; >> + u32 dfitdramclken; >> + u32 dfitdramclkdis; >> + u32 dfistcfg2; >> + u32 dfistparclr; >> + u32 dfistparlog; >> + u32 reserved12[3]; >> + u32 dfilpcfg0; >> + u32 reserved13[3]; >> + u32 dfitrwrlvlresp0; >> + u32 dfitrwrlvlresp1; >> + u32 dfitrwrlvlresp2; >> + u32 dfitrrdlvlresp0; >> + u32 dfitrrdlvlresp1; >> + u32 dfitrrdlvlresp2; >> + u32 dfitrwrlvldelay0; >> + u32 dfitrwrlvldelay1; >> + u32 dfitrwrlvldelay2; >> + u32 dfitrrdlvldelay0; >> + u32 dfitrrdlvldelay1; >> + u32 dfitrrdlvldelay2; >> + u32 dfitrrdlvlgatedelay0; >> + u32 dfitrrdlvlgatedelay1; >> + u32 dfitrrdlvlgatedelay2; >> + u32 dfitrcmd; >> + u32 reserved14[46]; >> + u32 ipvr; >> + u32 iptr; >> +}; >> +check_member(rk3036_ddr_pctl, iptr, 0x03fc); >> + >> +struct rk3036_ddr_phy { >> + u32 ddrphy_reg1; >> + u32 ddrphy_reg3; >> + u32 ddrphy_reg2; >> + u32 reserve[11]; >> + u32 ddrphy_reg4a; >> + u32 ddrphy_reg4b; >> + u32 reserve1[5]; >> + u32 ddrphy_reg16; >> + u32 reserve2; >> + u32 ddrphy_reg18; >> + u32 ddrphy_reg19; >> + u32 reserve3; >> + u32 ddrphy_reg21; >> + u32 reserve4; >> + u32 ddrphy_reg22; >> + u32 reserve5[3]; >> + u32 ddrphy_reg25; >> + u32 ddrphy_reg26; >> + u32 ddrphy_reg27; >> + u32 ddrphy_reg28; >> + u32 reserve6[17]; >> + u32 ddrphy_reg6; >> + u32 ddrphy_reg7; >> + u32 reserve7; >> + u32 ddrphy_reg8; >> + u32 ddrphy_reg0e4; >> + u32 reserve8[11]; >> + u32 ddrphy_reg9; >> + u32 ddrphy_reg10; >> + u32 reserve9; >> + u32 ddrphy_reg11; >> + u32 ddrphy_reg124; >> + u32 reserve10[38]; >> + u32 ddrphy_reg29; >> + u32 reserve11[40]; >> + u32 ddrphy_reg264; >> + u32 reserve12[18]; >> + u32 ddrphy_reg2a; >> + u32 reserve13[4]; >> + u32 ddrphy_reg30; >> + u32 ddrphy_reg31; >> + u32 ddrphy_reg32; >> + u32 ddrphy_reg33; >> + u32 ddrphy_reg34; >> + u32 ddrphy_reg35; >> + u32 ddrphy_reg36; >> + u32 ddrphy_reg37; >> + u32 ddrphy_reg38; >> + u32 ddrphy_reg39; >> + u32 ddrphy_reg40; >> + u32 ddrphy_reg41; >> + u32 ddrphy_reg42; >> + u32 ddrphy_reg43; >> + u32 ddrphy_reg44; >> + u32 ddrphy_reg45; >> + u32 ddrphy_reg46; >> + u32 ddrphy_reg47; >> + u32 ddrphy_reg48; >> + u32 ddrphy_reg49; >> + u32 ddrphy_reg50; >> + u32 ddrphy_reg51; >> + u32 ddrphy_reg52; >> + u32 ddrphy_reg53; >> + u32 reserve14; >> + u32 ddrphy_reg54; >> + u32 ddrphy_reg55; >> + u32 ddrphy_reg56; >> + u32 ddrphy_reg57; >> + u32 ddrphy_reg58; >> + u32 ddrphy_reg59; >> + u32 ddrphy_reg5a; >> + u32 ddrphy_reg5b; >> + u32 ddrphy_reg5c; >> + u32 ddrphy_reg5d; >> + u32 ddrphy_reg5e; >> + u32 reserve15[28]; >> + u32 ddrphy_reg5f; >> + u32 reserve16[6]; >> + u32 ddrphy_reg60; >> + u32 ddrphy_reg61; >> + u32 ddrphy_reg62; >> +}; >> +check_member(rk3036_ddr_phy, ddrphy_reg62, 0x03e8); >> + >> +struct rk3036_pctl_timing { >> + u32 togcnt1u; >> + u32 tinit; >> + u32 trsth; >> + u32 togcnt100n; >> + u32 trefi; >> + u32 tmrd; >> + u32 trfc; >> + u32 trp; >> + u32 trtw; >> + u32 tal; >> + u32 tcl; >> + u32 tcwl; >> + u32 tras; >> + u32 trc; >> + u32 trcd; >> + u32 trrd; >> + u32 trtp; >> + u32 twr; >> + u32 twtr; >> + u32 texsr; >> + u32 txp; >> + u32 txpdll; >> + u32 tzqcs; >> + u32 tzqcsi; >> + u32 tdqs; >> + u32 tcksre; >> + u32 tcksrx; >> + u32 tcke; >> + u32 tmod; >> + u32 trstl; >> + u32 tzqcl; >> + u32 tmrr; >> + u32 tckesr; >> + u32 tdpd; >> +}; >> + >> +struct rk3036_phy_timing { >> + u32 mr[4]; >> + u32 bl; >> + u32 cl_al; >> +}; >> + >> +typedef union { >> + u32 noc_timing; >> + struct { >> + u32 acttoact:6; >> + u32 rdtomiss:6; >> + u32 wrtomiss:6; >> + u32 burstlen:3; >> + u32 rdtowr:5; >> + u32 wrtord:5; >> + u32 bwratio:1; >> + }; >> +} rk3036_noc_timing; >> + >> +struct rk3036_ddr_timing { >> + u32 freq; >> + struct rk3036_pctl_timing pctl_timing; >> + struct rk3036_phy_timing phy_timing; >> + rk3036_noc_timing noc_timing; >> +}; >> + >> +struct rk3036_service_sys { >> + u32 id_coreid; >> + u32 id_revisionid; >> + u32 ddrconf; >> + u32 ddrtiming; >> + u32 ddrmode; >> + u32 readlatency; >> +}; >> + >> +struct rk3036_ddr_config { >> + /* >> + * 000: lpddr >> + * 001: ddr >> + * 010: ddr2 >> + * 011: ddr3 >> + * 100: lpddr2-s2 >> + * 101: lpddr2-s4 >> + * 110: lpddr3 >> + */ >> + u32 ddr_type; >> + u32 rank; >> + u32 cs0_row; >> + u32 cs1_row; >> + >> + /* 2: 4bank, 3: 8bank */ >> + u32 bank; >> + u32 col; >> + >> + /* bw(0: 8bit, 1: 16bit, 2: 32bit) */ >> + u32 bw; >> +}; >> + >> +void sdram_init(void); >> +void get_ddr_config(struct rk3036_ddr_config *config); >> +size_t sdram_size(void); > Can you add function comments for these? Ok, will be done in next version > >> +#endif >> diff --git a/arch/arm/mach-rockchip/rk3036/Makefile b/arch/arm/mach-rockchip/rk3036/Makefile >> index 5d14b95..6095777 100644 >> --- a/arch/arm/mach-rockchip/rk3036/Makefile >> +++ b/arch/arm/mach-rockchip/rk3036/Makefile >> @@ -8,3 +8,5 @@ ifndef CONFIG_SPL_BUILD >> obj-y += reset_rk3036.o >> obj-y += syscon_rk3036.o >> endif >> + >> +obj-y += sdram_rk3036.o >> diff --git a/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c b/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c >> new file mode 100644 >> index 0000000..0327f18 >> --- /dev/null >> +++ b/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c >> @@ -0,0 +1,729 @@ >> +/* >> + * (C) Copyright 2015 Google, Inc >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + */ >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include > common.h should go first > then > then Got it, thank you > >> + >> +#define CRU_BASE 0x20000000 >> +static struct rk3036_cru * const cru = (void *)CRU_BASE; >> + >> +#define GRF_BASE 0x20008000 >> +static struct rk3036_grf * const grf = (void *)GRF_BASE; >> + >> +#define DDR_PHY_BASE 0x2000a000 >> +static struct rk3036_ddr_phy * const ddr_phy = (void *)DDR_PHY_BASE; >> + >> +#define DDR_PCTL_BASE 0x20004000 >> +static struct rk3036_ddr_pctl * const pctl = (void *)DDR_PCTL_BASE; >> + >> +#define CPU_AXI_BUS_BASE 0x10128000 >> +static struct rk3036_service_sys * const axi_bus = (void *)CPU_AXI_BUS_BASE; > Can you just make these local variables? Okay, will be done next version. > >> + >> +/* use interge mode, 396M dpll setting >> + * refdiv, fbdiv, postdiv1, postdiv2 >> + */ >> +static const struct pll_div dpll_init_cfg = {1, 66, 4, 1}; >> + >> +/* 396Mhz ddr timing */ >> +struct rk3036_ddr_timing ddr_timing = {0x18c, > const? > >> + 0x18c, 0xc8, 0x1f4, 0x27, 0x4e, >> + 0x4, 0x8b, 0x06, 0x03, 0x0, 0x06, 0x05, 0x0f, 0x15, 0x06, 0x04, 0x04, >> + 0x06, 0x04, 0x200, 0x03, 0x0a, 0x40, 0x2710, 0x01, 0x05, 0x05, 0x03, >> + 0x0c, 0x28, 0x100, 0x0, 0x04, 0x0, >> + 0x420, 0x42, 0x0, 0x0, 0x01, 0x60, >> + 0x24717315}; >> + >> +/* ddr die config */ >> +static struct rk3036_ddr_config ddr_config; > Why is this static? Can it just be a local variable in the function? > >> + >> +/* >> + * [7:6] bank(n:n bit bank) >> + * [5:4] row(13+n) >> + * [3] cs(0:1 cs, 1:2 cs) >> + * [2:1] bank(n:n bit bank) >> + * [0] col(10+n) >> + */ >> +char ddr_cfg_2_rbc[] = { >> + ((3 << 6) | (3 << 4) | (0 << 3) | (0 << 1) | 1), >> + ((0 << 6) | (1 << 4) | (0 << 3) | (3 << 1) | 0), >> + ((0 << 6) | (2 << 4) | (0 << 3) | (3 << 1) | 0), >> + ((0 << 6) | (3 << 4) | (0 << 3) | (3 << 1) | 0), >> + ((0 << 6) | (1 << 4) | (0 << 3) | (3 << 1) | 1), >> + ((0 << 6) | (2 << 4) | (0 << 3) | (3 << 1) | 1), >> + ((0 << 6) | (3 << 4) | (0 << 3) | (3 << 1) | 1), >> + ((0 << 6) | (0 << 4) | (0 << 3) | (3 << 1) | 0), >> + ((0 << 6) | (0 << 4) | (0 << 3) | (3 << 1) | 1), >> + ((0 << 6) | (3 << 4) | (1 << 3) | (3 << 1) | 0), >> + ((0 << 6) | (3 << 4) | (1 << 3) | (3 << 1) | 1), >> + ((1 << 6) | (2 << 4) | (0 << 3) | (2 << 1) | 0), >> + ((3 << 6) | (2 << 4) | (0 << 3) | (0 << 1) | 1), >> + ((3 << 6) | (3 << 4) | (0 << 3) | (0 << 1) | 0), >> +}; >> + >> +/* DDRPHY REG */ >> +enum { >> + /* DDRPHY_REG1 */ >> + SOFT_RESET_MASK = 3, >> + SOFT_RESET_SHIFT = 2, >> + >> + /* DDRPHY_REG2 */ >> + MEMORY_SELECT_DDR3 = 0 << 6, >> + DQS_SQU_CAL_NORMAL_MODE = 0 << 1, >> + DQS_SQU_CAL_START = 1 << 0, >> + DQS_SQU_NO_CAL = 0 << 0, >> + >> + /* DDRPHY_REG2A */ >> + CMD_DLL_BYPASS = 1 << 4, >> + CMD_DLL_BYPASS_DISABLE = 0 << 4, >> + HIGH_8BIT_DLL_BYPASS = 1 << 3, >> + HIGH_8BIT_DLL_BYPASS_DISABLE = 0 << 3, >> + LOW_8BIT_DLL_BYPASS = 1 << 2, >> + LOW_8BIT_DLL_BYPASS_DISABLE = 0 << 2, >> + >> + /* DDRPHY_REG19 */ >> + CMD_FEEDBACK_ENABLE = 1 << 5, >> + CMD_SLAVE_DLL_INVERSE_MODE = 1 << 4, >> + CMD_SLAVE_DLL_NO_INVERSE_MODE = 0 << 4, >> + CMD_SLAVE_DLL_ENALBE = 1 << 3, >> + CMD_TX_SLAVE_DLL_DELAY_MASK = 7, >> + CMD_TX_SLAVE_DLL_DELAY_SHIFT = 0, >> + >> + /* DDRPHY_REG6 */ >> + LEFT_CHN_TX_DQ_PHASE_BYPASS_90 = 1 << 4, >> + LEFT_CHN_TX_DQ_PHASE_BYPASS_0 = 0 << 4, >> + LEFT_CHN_TX_DQ_DLL_ENABLE = 1 << 3, >> + LEFT_CHN_TX_DQ_DLL_DELAY_MASK = 7, >> + LEFT_CHN_TX_DQ_DLL_DELAY_SHIFT = 0, >> + >> + /* DDRPHY_REG8 */ >> + LEFT_CHN_RX_DQS_DELAY_TAP_MASK = 3, >> + LEFT_CHN_RX_DQS_DELAY_TAP_SHIFT = 0, >> + >> + /* DDRPHY_REG9 */ >> + RIGHT_CHN_TX_DQ_PHASE_BYPASS_90 = 1 << 4, >> + RIGHT_CHN_TX_DQ_PHASE_BYPASS_0 = 0 << 4, >> + RIGHT_CHN_TX_DQ_DLL_ENABLE = 1 << 3, >> + RIGHT_CHN_TX_DQ_DLL_DELAY_MASK = 7, >> + RIGHT_CHN_TX_DQ_DLL_DELAY_SHIFT = 0, >> + >> + /* DDRPHY_REG11 */ >> + RIGHT_CHN_RX_DQS_DELAY_TAP_MASK = 3, >> + RIGHT_CHN_RX_DQS_DELAY_TAP_SHIFT = 0, >> + >> + /* DDRPHY_REG62 */ >> + CAL_DONE_MASK = 3, >> + HIGH_8BIT_CAL_DONE = 1 << 1, >> + LOW_8BIT_CAL_DONE = 1 << 0, >> +}; >> + >> +/* PTCL */ >> +enum { >> + /* PCTL_DFISTCFG0 */ >> + DFI_INIT_START = 1 << 0, >> + DFI_DATA_BYTE_DISABLE_EN = 1 << 2, >> + >> + /* PCTL_DFISTCFG1 */ >> + DFI_DRAM_CLK_SR_EN = 1 << 0, >> + DFI_DRAM_CLK_DPD_EN = 1 << 1, >> + >> + /* PCTL_DFISTCFG2 */ >> + DFI_PARITY_INTR_EN = 1 << 0, >> + DFI_PARITY_EN = 1 << 1, >> + >> + /* PCTL_DFILPCFG0 */ >> + TLP_RESP_TIME_SHIFT = 16, >> + LP_SR_EN = 1 << 8, >> + LP_PD_EN = 1 << 0, >> + >> + /* PCTL_DFIODTCFG */ >> + RANK0_ODT_WRITE_SEL = 1 << 3, >> + RANK1_ODT_WRITE_SEL = 1 << 11, >> + >> + /* PCTL_DFIODTCFG1 */ >> + ODT_LEN_BL8_W_SHIFT = 16, >> + >> + /* PCTL_MCFG */ >> + TFAW_CFG_MASK = 3, >> + TFAW_CFG_SHIFT = 18, >> + PD_EXIT_SLOW_MODE = 0 << 17, >> + PD_ACTIVE_POWER_DOWN = 1 << 16, >> + PD_IDLE_MASK = 0xff, >> + PD_IDLE_SHIFT = 8, >> + MEM_BL4 = 0 << 0, >> + MEM_BL8 = 1 << 0, >> + >> + /* PCTL_MCFG1 */ >> + HW_EXIT_IDLE_EN_MASK = 1, >> + HW_EXIT_IDLE_EN_SHIFT = 31, >> + SR_IDLE_MASK = 0x1ff, >> + SR_IDLE_SHIFT = 0, >> + >> + /* PCTL_SCFG */ >> + HW_LOW_POWER_EN = 1 << 0, >> + >> + /* PCTL_POWCTL */ >> + POWER_UP_START = 1 << 0, >> + >> + /* PCTL_POWSTAT */ >> + POWER_UP_DONE = 1 << 0, >> + >> + /* PCTL_MCMD */ >> + START_CMD = 1 << 31, >> + BANK_ADDR_MASK = 7, >> + BANK_ADDR_SHIFT = 17, >> + CMD_ADDR_MASK = 0x1fff, >> + CMD_ADDR_SHIFT = 4, >> + DESELECT_CMD = 0, >> + PREA_CMD, >> + REF_CMD, >> + MRS_CMD, >> + ZQCS_CMD, >> + ZQCL_CMD, >> + RSTL_CMD, >> + MRR_CMD = 8, >> + >> + /* PCTL_STAT */ >> + INIT_MEM = 0, >> + CONFIG, >> + CONFIG_REQ, >> + ACCESS, >> + ACCESS_REQ, >> + LOW_POWER, >> + LOW_POWER_ENTRY_REQ, >> + LOW_POWER_EXIT_REQ, >> + PCTL_STAT_MASK = 7, >> + >> + /* PCTL_SCTL */ >> + INIT_STATE = 0, >> + CFG_STATE = 1, >> + GO_STATE = 2, >> + SLEEP_STATE = 3, >> + WAKEUP_STATE = 4, >> +}; >> + >> +/* GRF_SOC_CON2 */ >> +#define MSCH4_MAINDDR3 1 << 7 > () around that. Also can you remove extra space after #define? Got it. > >> + >> +#define PHY_RON_DISABLE 0 >> +#define PHY_RON_309OHM 1 >> +#define PHY_RON_155OHM 2 >> +#define PHY_RON_103OHM 3 >> +#define PHY_RON_63OHM 5 >> +#define PHY_RON_45OHM 7 >> +#define PHY_RON_77OHM 8 >> +#define PHY_RON_62OHM 9 >> +#define PHY_RON_52OHM 0xa >> +#define PHY_RON_44OHM 0xb >> +#define PHY_RON_39OHM 0xc >> +#define PHY_RON_34OHM 0xd >> +#define PHY_RON_31OHM 0xe >> +#define PHY_RON_28OHM 0xf >> + >> + >> +#define PHY_RTT_DISABLE 0 >> +#define PHY_RTT_861OHM 1 >> +#define PHY_RTT_431OHM 2 >> +#define PHY_RTT_287OHM 3 >> +#define PHY_RTT_216OHM 4 >> +#define PHY_RTT_172OHM 5 >> +#define PHY_RTT_145OHM 6 >> +#define PHY_RTT_124OHM 7 >> +#define PHY_RTT_215OHM 8 >> +#define PHY_RTT_144OHM 0xa >> +#define PHY_RTT_123OHM 0xb >> +#define PHY_RTT_108OHM 0xc >> +#define PHY_RTT_96OHM 0xd >> +#define PHY_RTT_86OHM 0xe >> +#define PHY_RTT_78OHM 0xf > How about using enum for these? Okay, will be done next version > >> + >> +#define PHY_DRV_ODT_SET(n) ((n << 4) | n) >> + >> +#define DDR3_DLL_RESET (1 << 8) >> + >> +/* GRF_OS_REG1 */ >> +enum { >> + /* >> + * 000: lpddr >> + * 001: ddr >> + * 010: ddr2 >> + * 011: ddr3 >> + * 100: lpddr2-s2 >> + * 101: lpddr2-s4 >> + * 110: lpddr3 >> + */ >> + DDR_TYPE_MASK = 7, >> + DDR_TYPE_SHIFT = 13, >> + >> + /* 0: 1 chn, 1: 2 chn */ >> + DDR_CHN_CNT_SHIFT = 12, >> + >> + /* 0: 1 rank, 1: 2 rank */ >> + DDR_RANK_CNT_MASK = 1, >> + DDR_RANK_CNT_SHIFT = 11, >> + >> + /* >> + * 00: 9col >> + * 01: 10col >> + * 10: 11col >> + * 11: 12col >> + */ >> + DDR_COL_MASK = 3, >> + DDR_COL_SHIFT = 9, >> + >> + /* 0: 8 bank, 1: 4 bank*/ >> + DDR_BANK_MASK = 1, >> + DDR_BANK_SHIFT = 8, >> + >> + /* >> + * 00: 13 row >> + * 01: 14 row >> + * 10: 15 row >> + * 11: 16 row >> + */ >> + DDR_CS0_ROW_MASK = 3, >> + DDR_CS0_ROW_SHIFT = 6, >> + DDR_CS1_ROW_MASK = 3, >> + DDR_CS1_ROW_SHIFT = 4, >> + >> + /* >> + * 00: 32 bit >> + * 01: 16 bit >> + * 10: 8 bit >> + * rk3036 only support 16bit >> + */ >> + DDR_BW_MASK = 3, >> + DDR_BW_SHIFT = 2, >> + DDR_DIE_BW_MASK = 3, >> + DDR_DIE_BW_SHIFT = 0, >> +}; >> + >> +static void rkdclk_init(void) >> +{ >> + struct rk3036_pll *pll = &cru->pll[1]; >> + >> + /* pll enter slow-mode */ >> + rk_clrsetreg(&cru->cru_mode_con, >> + DPLL_MODE_MASK << DPLL_MODE_SHIFT, >> + DPLL_MODE_SLOW << DPLL_MODE_SHIFT); >> + >> + /* use interger mode */ >> + rk_clrreg(&pll->con1, 1 << PLL_DSMPD_SHIFT); >> + >> + rk_clrsetreg(&pll->con0, >> + PLL_POSTDIV1_MASK << PLL_POSTDIV1_SHIFT | PLL_FBDIV_MASK, >> + (dpll_init_cfg.postdiv1 << PLL_POSTDIV1_SHIFT) | >> + dpll_init_cfg.fbdiv); >> + rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK << PLL_POSTDIV2_SHIFT | >> + PLL_REFDIV_MASK << PLL_REFDIV_SHIFT, >> + (dpll_init_cfg.postdiv2 << PLL_POSTDIV2_SHIFT | >> + dpll_init_cfg.refdiv << PLL_REFDIV_SHIFT)); >> + >> + /* waiting for pll lock */ >> + while (readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT)) >> + rockchip_udelay(1); >> + >> + /* PLL enter normal-mode */ >> + rk_clrsetreg(&cru->cru_mode_con, >> + DPLL_MODE_MASK << DPLL_MODE_SHIFT, >> + DPLL_MODE_NORM << DPLL_MODE_SHIFT); >> +} >> + >> +static void 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++; >> + } >> +} >> + >> +void phy_pctrl_reset(void) >> +{ >> + rk_clrsetreg(&cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT | >> + 1 << DDRCTRL_SRST_SHIFT | 1 << DDRPHY_PSRST_SHIFT | >> + 1 << DDRPHY_SRST_SHIFT, >> + 1 << DDRCTRL_PSRST_SHIFT | 1 << DDRCTRL_SRST_SHIFT | >> + 1 << DDRPHY_PSRST_SHIFT | 1 << DDRPHY_SRST_SHIFT); >> + rockchip_udelay(10); >> + >> + rk_clrsetreg(&cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT | >> + 1 << DDRCTRL_SRST_SHIFT | 1 << DDRPHY_PSRST_SHIFT | >> + 1 << DDRPHY_SRST_SHIFT, >> + 1 << DDRCTRL_PSRST_SHIFT | 1 << DDRCTRL_SRST_SHIFT | >> + 0 << DDRPHY_PSRST_SHIFT | 0 << DDRPHY_SRST_SHIFT); >> + rockchip_udelay(10); >> + >> + rk_clrsetreg(&cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT | >> + 1 << DDRCTRL_SRST_SHIFT | 1 << DDRPHY_PSRST_SHIFT | >> + 1 << DDRPHY_SRST_SHIFT, >> + 0 << DDRCTRL_PSRST_SHIFT | 0 << DDRCTRL_SRST_SHIFT | >> + 0 << DDRPHY_PSRST_SHIFT | 0 << DDRPHY_SRST_SHIFT); >> + rockchip_udelay(10); >> + >> + clrsetbits_le32(&ddr_phy->ddrphy_reg1, >> + SOFT_RESET_MASK << SOFT_RESET_SHIFT, >> + 0 << SOFT_RESET_SHIFT); >> + rockchip_udelay(10); >> + clrsetbits_le32(&ddr_phy->ddrphy_reg1, >> + SOFT_RESET_MASK << SOFT_RESET_SHIFT, >> + 3 << SOFT_RESET_SHIFT); >> + >> + rockchip_udelay(1); >> +} >> + >> +void phy_dll_bypass_set(unsigned int freq) >> +{ >> + if (freq < ddr_timing.freq) { >> + writel(CMD_DLL_BYPASS | HIGH_8BIT_DLL_BYPASS | >> + LOW_8BIT_DLL_BYPASS, &ddr_phy->ddrphy_reg2a); >> + >> + writel(CMD_SLAVE_DLL_NO_INVERSE_MODE | CMD_SLAVE_DLL_ENALBE | >> + (0 & CMD_TX_SLAVE_DLL_DELAY_MASK) << >> + CMD_TX_SLAVE_DLL_DELAY_SHIFT, &ddr_phy->ddrphy_reg19); >> + >> + writel(LEFT_CHN_TX_DQ_PHASE_BYPASS_90 | >> + LEFT_CHN_TX_DQ_DLL_ENABLE | >> + (0 & LEFT_CHN_TX_DQ_DLL_DELAY_MASK) << >> + LEFT_CHN_TX_DQ_DLL_DELAY_SHIFT, &ddr_phy->ddrphy_reg6); >> + >> + writel(RIGHT_CHN_TX_DQ_PHASE_BYPASS_90 | >> + RIGHT_CHN_TX_DQ_DLL_ENABLE | >> + (0 & RIGHT_CHN_TX_DQ_DLL_DELAY_MASK) << >> + RIGHT_CHN_TX_DQ_DLL_DELAY_SHIFT, >> + &ddr_phy->ddrphy_reg9); >> + } else { >> + writel(CMD_DLL_BYPASS_DISABLE | HIGH_8BIT_DLL_BYPASS_DISABLE | >> + LOW_8BIT_DLL_BYPASS_DISABLE, &ddr_phy->ddrphy_reg2a); >> + >> + writel(CMD_SLAVE_DLL_NO_INVERSE_MODE | CMD_SLAVE_DLL_ENALBE | >> + (0 & CMD_TX_SLAVE_DLL_DELAY_MASK) << >> + CMD_TX_SLAVE_DLL_DELAY_SHIFT, &ddr_phy->ddrphy_reg19); > Is this the same as the ddrphy_reg19 line above? Oh, yes, you are right, will move together next version > >> + >> + writel(LEFT_CHN_TX_DQ_PHASE_BYPASS_0 | >> + LEFT_CHN_TX_DQ_DLL_ENABLE | >> + (4 & LEFT_CHN_TX_DQ_DLL_DELAY_MASK) << >> + LEFT_CHN_TX_DQ_DLL_DELAY_SHIFT, >> + &ddr_phy->ddrphy_reg6); >> + >> + writel(RIGHT_CHN_TX_DQ_PHASE_BYPASS_0 | >> + RIGHT_CHN_TX_DQ_DLL_ENABLE | >> + (4 & RIGHT_CHN_TX_DQ_DLL_DELAY_MASK) << >> + RIGHT_CHN_TX_DQ_DLL_DELAY_SHIFT, >> + &ddr_phy->ddrphy_reg9); >> + } >> + >> + /* 45 degree delay */ >> + writel((2 & LEFT_CHN_RX_DQS_DELAY_TAP_MASK) << > 2 should be in an enum Okay > >> + LEFT_CHN_RX_DQS_DELAY_TAP_SHIFT, &ddr_phy->ddrphy_reg8); >> + writel((2 & RIGHT_CHN_RX_DQS_DELAY_TAP_MASK) << >> + RIGHT_CHN_RX_DQS_DELAY_TAP_SHIFT, &ddr_phy->ddrphy_reg11); >> +} >> + >> +static void send_command(u32 rank, u32 cmd, u32 arg) >> +{ >> + writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd); >> + rockchip_udelay(1); >> + while (readl(&pctl->mcmd) & START_CMD) >> + ; >> +} >> + >> +static void memory_init(void) >> +{ >> + send_command(3, DESELECT_CMD, 0); >> + rockchip_udelay(1); >> + send_command(3, PREA_CMD, 0); >> + send_command(3, MRS_CMD, (0x02 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT | >> + (ddr_timing.phy_timing.mr[2] & CMD_ADDR_MASK) << >> + CMD_ADDR_SHIFT); >> + >> + send_command(3, MRS_CMD, (0x03 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT | >> + (ddr_timing.phy_timing.mr[3] & CMD_ADDR_MASK) << >> + CMD_ADDR_SHIFT); >> + >> + send_command(3, MRS_CMD, (0x01 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT | >> + (ddr_timing.phy_timing.mr[1] & CMD_ADDR_MASK) << >> + CMD_ADDR_SHIFT); >> + >> + send_command(3, MRS_CMD, (0x00 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT | >> + (ddr_timing.phy_timing.mr[0] & CMD_ADDR_MASK) << >> + CMD_ADDR_SHIFT | DDR3_DLL_RESET); > The order is strange here - 2, 3, 1, 0. Then you do a RESET. > > Is it possible to put this in a for() loop? > >> + >> + send_command(3, ZQCL_CMD, 0); >> +} >> + >> +static void data_training(void) >> +{ >> + u32 value; >> + >> + /* disable auto refresh */ >> + value = readl(&pctl->trefi), >> + writel(0, &pctl->trefi); >> + >> + clrsetbits_le32(&ddr_phy->ddrphy_reg2, 0x03, >> + DQS_SQU_CAL_NORMAL_MODE | DQS_SQU_CAL_START); >> + >> + rockchip_udelay(10); >> + while ((readl(&ddr_phy->ddrphy_reg62) & CAL_DONE_MASK) != >> + (HIGH_8BIT_CAL_DONE | LOW_8BIT_CAL_DONE)) { >> + ; >> + } >> + >> + clrsetbits_le32(&ddr_phy->ddrphy_reg2, 0x03, >> + DQS_SQU_CAL_NORMAL_MODE | DQS_SQU_NO_CAL); >> + send_command(3, REF_CMD, 0); >> + send_command(3, REF_CMD, 0); >> + send_command(3, REF_CMD, 0); >> + >> + writel(value, &pctl->trefi); >> +} >> + >> +static void move_to_config_state(void) >> +{ >> + unsigned int state; >> + >> + while (1) { >> + state = readl(&pctl->stat) & PCTL_STAT_MASK; >> + switch (state) { >> + case LOW_POWER: >> + writel(WAKEUP_STATE, &pctl->sctl); >> + while ((readl(&pctl->stat) & PCTL_STAT_MASK) >> + != ACCESS) >> + ; >> + /* if at low power state,need wakeup first, > /* > * If at ... > > Also please try to wrap the comments to the full width (e.g. 75-78 chars). Okay , thank you >> + * and then enter the config >> + * so fallthrough. >> + */ >> + case ACCESS: >> + /* fallthrough */ >> + case INIT_MEM: >> + writel(CFG_STATE, &pctl->sctl); >> + while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG) >> + ; >> + break; >> + > Drop blank line Got it. >> + case CONFIG: >> + return; >> + default: >> + break; >> + } >> + } >> +} >> + >> +static void move_to_access_state(void) >> +{ >> + unsigned int state; >> + >> + while (1) { >> + state = readl(&pctl->stat) & PCTL_STAT_MASK; >> + switch (state) { >> + case LOW_POWER: >> + writel(WAKEUP_STATE, &pctl->sctl); >> + while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS) >> + ; >> + break; >> + case INIT_MEM: >> + writel(CFG_STATE, &pctl->sctl); >> + while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG) >> + ; >> + /* fallthrough */ >> + case CONFIG: >> + writel(GO_STATE, &pctl->sctl); >> + while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS) >> + ; >> + break; >> + case ACCESS: >> + return; >> + default: >> + break; >> + } >> + } >> +} >> + >> +static void pctl_cfg(void) >> +{ >> + u32 burst_len; >> + u32 reg; >> + >> + writel(DFI_INIT_START | DFI_DATA_BYTE_DISABLE_EN, &pctl->dfistcfg0); >> + writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN, &pctl->dfistcfg1); >> + writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2); >> + writel(7 << TLP_RESP_TIME_SHIFT | LP_SR_EN | LP_PD_EN, >> + &pctl->dfilpcfg0); >> + >> + writel(1, &pctl->dfitphyupdtype0); >> + writel(0x0d, &pctl->dfitphyrdlat); >> + >> + /* cs0 and cs1 write odt enable */ >> + writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL), >> + &pctl->dfiodtcfg); >> + >> + /* odt write length */ >> + writel(7 << ODT_LEN_BL8_W_SHIFT, &pctl->dfiodtcfg1); >> + >> + /* phyupd and ctrlupd disabled */ >> + writel(0, &pctl->dfiupdcfg); >> + >> + if ((ddr_timing.noc_timing.burstlen << 1) == 4) >> + burst_len = MEM_BL4; >> + else >> + burst_len = MEM_BL8; >> + >> + copy_to_reg(&pctl->togcnt1u, &ddr_timing.pctl_timing.togcnt1u, >> + sizeof(struct rk3036_pctl_timing)); >> + >> + reg = readl(&pctl->tcl); >> + writel(reg - 3, &pctl->dfitrddataen); >> + reg = readl(&pctl->tcwl); >> + writel(reg - 1, &pctl->dfitphywrlat); >> + >> + writel(burst_len | (1 & TFAW_CFG_MASK) << TFAW_CFG_SHIFT | >> + PD_EXIT_SLOW_MODE | PD_ACTIVE_POWER_DOWN | >> + (0 & PD_IDLE_MASK) << PD_IDLE_SHIFT, >> + &pctl->mcfg); >> + >> + writel(RK_SETBITS(MSCH4_MAINDDR3), &grf->soc_con2); >> + setbits_le32(&pctl->scfg, HW_LOW_POWER_EN); >> +} >> + >> +static void phy_cfg(void) >> +{ >> + writel(ddr_timing.noc_timing.noc_timing, &axi_bus->ddrtiming); >> + writel(0x3f, &axi_bus->readlatency); >> + >> + writel(MEMORY_SELECT_DDR3 | DQS_SQU_CAL_NORMAL_MODE, >> + &ddr_phy->ddrphy_reg2); >> + >> + clrsetbits_le32(&ddr_phy->ddrphy_reg3, 1, ddr_timing.phy_timing.bl); >> + writel(ddr_timing.phy_timing.cl_al, &ddr_phy->ddrphy_reg4a); >> + writel(PHY_DRV_ODT_SET(PHY_RON_44OHM), &ddr_phy->ddrphy_reg16); >> + writel(PHY_DRV_ODT_SET(PHY_RON_44OHM), &ddr_phy->ddrphy_reg22); >> + writel(PHY_DRV_ODT_SET(PHY_RON_44OHM), &ddr_phy->ddrphy_reg25); >> + writel(PHY_DRV_ODT_SET(PHY_RON_44OHM), &ddr_phy->ddrphy_reg26); >> + writel(PHY_DRV_ODT_SET(PHY_RTT_216OHM), &ddr_phy->ddrphy_reg27); >> + writel(PHY_DRV_ODT_SET(PHY_RTT_216OHM), &ddr_phy->ddrphy_reg28); >> +} >> + >> +void dram_cfg_rbc(void) >> +{ >> + char noc_config; >> + int i = 0; >> + >> + move_to_config_state(); >> + >> + /* 2bit in BIT1, 2 */ >> + if (ddr_config.rank == 2) { >> + noc_config = (ddr_config.cs0_row - 13) << 4 | >> + ddr_config.bank << 1 | >> + 1 << 3 | (ddr_config.col - 10); >> + if (noc_config == ddr_cfg_2_rbc[9]) { >> + i = 9; >> + goto finish; >> + } else if (noc_config == ddr_cfg_2_rbc[10]) { >> + i = 10; >> + goto finish; >> + } >> + } >> + >> + noc_config = (ddr_config.cs0_row - 13) << 4 | ddr_config.bank << 1 | >> + (ddr_config.col - 10); >> + >> + for (i = 0; i < sizeof(ddr_cfg_2_rbc); i++) { >> + if (noc_config == ddr_cfg_2_rbc[i]) >> + goto finish; >> + } >> + >> + /* bank: 1 bit in BIT6,7, 1bit in BIT1, 2 */ >> + noc_config = 1 << 6 | (ddr_config.cs0_row - 13) << 4 | >> + 2 << 1 | (ddr_config.col - 10); >> + if (noc_config == ddr_cfg_2_rbc[11]) { >> + i = 11; >> + goto finish; >> + } >> + >> + /* bank: 2bit in BIT6,7 */ >> + noc_config = (ddr_config.bank << 6) | (ddr_config.cs0_row - 13) << 4 | >> + (ddr_config.col - 10); >> + >> + if (noc_config == ddr_cfg_2_rbc[0]) >> + i = 0; >> + else if (noc_config == ddr_cfg_2_rbc[12]) >> + i = 12; >> + else if (noc_config == ddr_cfg_2_rbc[13]) >> + i = 13; >> +finish: >> + writel(i, &axi_bus->ddrconf); >> + move_to_access_state(); >> + >> + return; >> +} >> + >> +static void sdram_all_config(void) >> +{ >> + u32 os_reg = 0; >> + >> + os_reg = ddr_config.ddr_type << DDR_TYPE_SHIFT | >> + 0 << DDR_CHN_CNT_SHIFT | >> + (ddr_config.rank - 1) << DDR_RANK_CNT_SHIFT | >> + (ddr_config.col - 1) << DDR_COL_SHIFT | >> + (ddr_config.bank == 3 ? 0 : 1) << DDR_BANK_SHIFT | >> + (ddr_config.cs0_row - 13) << DDR_CS0_ROW_SHIFT | >> + (ddr_config.cs1_row - 13) << DDR_CS1_ROW_SHIFT | >> + 1 << DDR_BW_SHIFT | ddr_config.bw << DDR_DIE_BW_SHIFT; >> + writel(os_reg, &grf->os_reg[1]); >> +} >> + >> +size_t sdram_size(void) >> +{ >> + u32 size, os_reg, cs0_row, cs1_row, col, bank, rank; >> + >> + os_reg = readl(&grf->os_reg[1]); >> + print_hex(os_reg); > Do you want this? What is the purpose? Oh, careless, sorry. > >> + >> + cs0_row = 13 + ((os_reg >> DDR_CS0_ROW_SHIFT) & DDR_CS0_ROW_MASK); >> + cs1_row = 13 + ((os_reg >> DDR_CS1_ROW_SHIFT) & DDR_CS1_ROW_MASK); >> + col = 9 + ((os_reg >> DDR_COL_SHIFT) & DDR_COL_MASK); >> + bank = 3 - ((os_reg >> DDR_BANK_SHIFT) & DDR_BANK_MASK); >> + rank = 1 + ((os_reg >> DDR_RANK_CNT_SHIFT) & DDR_RANK_CNT_MASK); >> + >> + /* row + col + bank + bw(rk3036 only support 16bit, so fix in 1) */ >> + size = 1 << (cs0_row + col + bank + 1); >> + >> + if (rank > 1) >> + size += size >> (cs0_row - cs1_row); >> + >> + return size; >> +} >> + >> +__weak void get_ddr_config(struct rk3036_ddr_config *config) >> +{ >> +} >> + >> +void sdram_init(void) >> +{ >> + get_ddr_config(&ddr_config); >> + sdram_all_config(); >> + rkdclk_init(); >> + phy_pctrl_reset(); >> + phy_dll_bypass_set(ddr_timing.freq); >> + pctl_cfg(); >> + phy_cfg(); >> + writel(POWER_UP_START, &pctl->powctl); >> + while (!(readl(&pctl->powstat) & POWER_UP_DONE)) >> + ; >> + memory_init(); >> + move_to_config_state(); >> + data_training(); >> + move_to_access_state(); >> + dram_cfg_rbc(); > This looks good and very clear, thank you. Thank you for your review, i will rework it. > >> +} >> -- >> 1.9.1 >> > Regards, > Simon > > > -- Lin Huang