add rk3036 sdram driver so we can set up sdram in SPL Signed-off-by: Lin Huang <hl@rock-chips.com> Acked-by: Simon Glass <sjg@chromium.org>master
parent
07d8d35a61
commit
53c45f0ca2
@ -0,0 +1,341 @@ |
||||
/*
|
||||
* (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 <common.h> |
||||
|
||||
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; |
||||
}; |
||||
|
||||
/* rk3036 sdram initial */ |
||||
void sdram_init(void); |
||||
|
||||
/* get ddr die config, implement in specific board */ |
||||
void get_ddr_config(struct rk3036_ddr_config *config); |
||||
|
||||
/* get ddr size on board */ |
||||
size_t sdram_size(void); |
||||
#endif |
@ -0,0 +1,764 @@ |
||||
/*
|
||||
* (C) Copyright 2015 Google, Inc |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
#include <common.h> |
||||
#include <asm/io.h> |
||||
#include <asm/types.h> |
||||
#include <asm/arch/cru_rk3036.h> |
||||
#include <asm/arch/grf_rk3036.h> |
||||
#include <asm/arch/hardware.h> |
||||
#include <asm/arch/sdram_rk3036.h> |
||||
#include <asm/arch/timer.h> |
||||
#include <asm/arch/uart.h> |
||||
|
||||
/*
|
||||
* we can not fit the code to access the device tree in SPL |
||||
* (due to 4K SRAM size limits), so these are hard-coded |
||||
*/ |
||||
#define CRU_BASE 0x20000000 |
||||
#define GRF_BASE 0x20008000 |
||||
#define DDR_PHY_BASE 0x2000a000 |
||||
#define DDR_PCTL_BASE 0x20004000 |
||||
#define CPU_AXI_BUS_BASE 0x10128000 |
||||
|
||||
struct rk3036_sdram_priv { |
||||
struct rk3036_cru *cru; |
||||
struct rk3036_grf *grf; |
||||
struct rk3036_ddr_phy *phy; |
||||
struct rk3036_ddr_pctl *pctl; |
||||
struct rk3036_service_sys *axi_bus; |
||||
|
||||
/* ddr die config */ |
||||
struct rk3036_ddr_config ddr_config; |
||||
}; |
||||
|
||||
/* use integer mode, 396MHz dpll setting
|
||||
* refdiv, fbdiv, postdiv1, postdiv2 |
||||
*/ |
||||
const struct pll_div dpll_init_cfg = {1, 66, 4, 1}; |
||||
|
||||
/* 396Mhz ddr timing */ |
||||
const struct rk3036_ddr_timing ddr_timing = {0x18c, |
||||
{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} }; |
||||
|
||||
/*
|
||||
* [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) |
||||
*/ |
||||
const 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) |
||||
#define PHY_DRV_ODT_SET(n) ((n << 4) | n) |
||||
#define DDR3_DLL_RESET (1 << 8) |
||||
|
||||
/* CK pull up/down driver strength control */ |
||||
enum { |
||||
PHY_RON_DISABLE = 0, |
||||
PHY_RON_309OHM = 1, |
||||
PHY_RON_155OHM, |
||||
PHY_RON_103OHM = 3, |
||||
PHY_RON_63OHM = 5, |
||||
PHY_RON_45OHM = 7, |
||||
PHY_RON_77OHM, |
||||
PHY_RON_62OHM, |
||||
PHY_RON_52OHM, |
||||
PHY_RON_44OHM, |
||||
PHY_RON_39OHM, |
||||
PHY_RON_34OHM, |
||||
PHY_RON_31OHM, |
||||
PHY_RON_28OHM, |
||||
}; |
||||
|
||||
/* DQ pull up/down control */ |
||||
enum { |
||||
PHY_RTT_DISABLE = 0, |
||||
PHY_RTT_861OHM = 1, |
||||
PHY_RTT_431OHM, |
||||
PHY_RTT_287OHM, |
||||
PHY_RTT_216OHM, |
||||
PHY_RTT_172OHM, |
||||
PHY_RTT_145OHM, |
||||
PHY_RTT_124OHM, |
||||
PHY_RTT_215OHM, |
||||
PHY_RTT_144OHM = 0xa, |
||||
PHY_RTT_123OHM, |
||||
PHY_RTT_108OHM, |
||||
PHY_RTT_96OHM, |
||||
PHY_RTT_86OHM, |
||||
PHY_RTT_78OHM, |
||||
}; |
||||
|
||||
/* DQS squelch DLL delay */ |
||||
enum { |
||||
DQS_DLL_NO_DELAY = 0, |
||||
DQS_DLL_22P5_DELAY, |
||||
DQS_DLL_45_DELAY, |
||||
DQS_DLL_67P5_DELAY, |
||||
DQS_DLL_90_DELAY, |
||||
DQS_DLL_112P5_DELAY, |
||||
DQS_DLL_135_DELAY, |
||||
DQS_DLL_157P5_DELAY, |
||||
}; |
||||
|
||||
/* 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(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
struct rk3036_pll *pll = &priv->cru->pll[1]; |
||||
|
||||
/* pll enter slow-mode */ |
||||
rk_clrsetreg(&priv->cru->cru_mode_con, |
||||
DPLL_MODE_MASK << DPLL_MODE_SHIFT, |
||||
DPLL_MODE_SLOW << DPLL_MODE_SHIFT); |
||||
|
||||
/* use integer 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(&priv->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(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
struct rk3036_ddr_phy *ddr_phy = priv->phy; |
||||
|
||||
rk_clrsetreg(&priv->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_clrreg(&priv->cru->cru_softrst_con[5], 1 << DDRPHY_PSRST_SHIFT | |
||||
1 << DDRPHY_SRST_SHIFT); |
||||
rockchip_udelay(10); |
||||
|
||||
rk_clrreg(&priv->cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT | |
||||
1 << DDRCTRL_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(struct rk3036_sdram_priv *priv, unsigned int freq) |
||||
{ |
||||
struct rk3036_ddr_phy *ddr_phy = priv->phy; |
||||
|
||||
if (freq < ddr_timing.freq) { |
||||
writel(CMD_DLL_BYPASS | HIGH_8BIT_DLL_BYPASS | |
||||
LOW_8BIT_DLL_BYPASS, &ddr_phy->ddrphy_reg2a); |
||||
|
||||
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(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); |
||||
} |
||||
|
||||
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); |
||||
|
||||
/* 45 degree delay */ |
||||
writel((DQS_DLL_45_DELAY & LEFT_CHN_RX_DQS_DELAY_TAP_MASK) << |
||||
LEFT_CHN_RX_DQS_DELAY_TAP_SHIFT, &ddr_phy->ddrphy_reg8); |
||||
writel((DQS_DLL_45_DELAY & RIGHT_CHN_RX_DQS_DELAY_TAP_MASK) << |
||||
RIGHT_CHN_RX_DQS_DELAY_TAP_SHIFT, &ddr_phy->ddrphy_reg11); |
||||
} |
||||
|
||||
static void send_command(struct rk3036_ddr_pctl *pctl, |
||||
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(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
struct rk3036_ddr_pctl *pctl = priv->pctl; |
||||
|
||||
send_command(pctl, 3, DESELECT_CMD, 0); |
||||
rockchip_udelay(1); |
||||
send_command(pctl, 3, PREA_CMD, 0); |
||||
send_command(pctl, 3, MRS_CMD, |
||||
(0x02 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT | |
||||
(ddr_timing.phy_timing.mr[2] & CMD_ADDR_MASK) << |
||||
CMD_ADDR_SHIFT); |
||||
|
||||
send_command(pctl, 3, MRS_CMD, |
||||
(0x03 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT | |
||||
(ddr_timing.phy_timing.mr[3] & CMD_ADDR_MASK) << |
||||
CMD_ADDR_SHIFT); |
||||
|
||||
send_command(pctl, 3, MRS_CMD, |
||||
(0x01 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT | |
||||
(ddr_timing.phy_timing.mr[1] & CMD_ADDR_MASK) << |
||||
CMD_ADDR_SHIFT); |
||||
|
||||
send_command(pctl, 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); |
||||
|
||||
send_command(pctl, 3, ZQCL_CMD, 0); |
||||
} |
||||
|
||||
static void data_training(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
struct rk3036_ddr_phy *ddr_phy = priv->phy; |
||||
struct rk3036_ddr_pctl *pctl = priv->pctl; |
||||
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(1); |
||||
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); |
||||
|
||||
/*
|
||||
* since data training will take about 20us, so send some auto |
||||
* refresh(about 7.8us) to complement the lost time |
||||
*/ |
||||
send_command(pctl, 3, REF_CMD, 0); |
||||
send_command(pctl, 3, REF_CMD, 0); |
||||
send_command(pctl, 3, REF_CMD, 0); |
||||
|
||||
writel(value, &pctl->trefi); |
||||
} |
||||
|
||||
static void move_to_config_state(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
unsigned int state; |
||||
struct rk3036_ddr_pctl *pctl = priv->pctl; |
||||
|
||||
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, 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; |
||||
case CONFIG: |
||||
return; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void move_to_access_state(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
unsigned int state; |
||||
struct rk3036_ddr_pctl *pctl = priv->pctl; |
||||
|
||||
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(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
struct rk3036_ddr_pctl *pctl = priv->pctl; |
||||
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), &priv->grf->soc_con2); |
||||
setbits_le32(&pctl->scfg, HW_LOW_POWER_EN); |
||||
} |
||||
|
||||
static void phy_cfg(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
struct rk3036_ddr_phy *ddr_phy = priv->phy; |
||||
struct rk3036_service_sys *axi_bus = priv->axi_bus; |
||||
|
||||
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(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
char noc_config; |
||||
int i = 0; |
||||
struct rk3036_ddr_config config = priv->ddr_config; |
||||
struct rk3036_service_sys *axi_bus = priv->axi_bus; |
||||
|
||||
move_to_config_state(priv); |
||||
|
||||
/* 2bit in BIT1, 2 */ |
||||
if (config.rank == 2) { |
||||
noc_config = (config.cs0_row - 13) << 4 | config.bank << 1 | |
||||
1 << 3 | (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 = (config.cs0_row - 13) << 4 | config.bank << 1 | |
||||
(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 | (config.cs0_row - 13) << 4 | |
||||
2 << 1 | (config.col - 10); |
||||
if (noc_config == ddr_cfg_2_rbc[11]) { |
||||
i = 11; |
||||
goto finish; |
||||
} |
||||
|
||||
/* bank: 2bit in BIT6,7 */ |
||||
noc_config = (config.bank << 6) | (config.cs0_row - 13) << 4 | |
||||
(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(priv); |
||||
} |
||||
|
||||
static void sdram_all_config(struct rk3036_sdram_priv *priv) |
||||
{ |
||||
u32 os_reg = 0; |
||||
struct rk3036_ddr_config config = priv->ddr_config; |
||||
|
||||
os_reg = config.ddr_type << DDR_TYPE_SHIFT | |
||||
0 << DDR_CHN_CNT_SHIFT | |
||||
(config.rank - 1) << DDR_RANK_CNT_SHIFT | |
||||
(config.col - 1) << DDR_COL_SHIFT | |
||||
(config.bank == 3 ? 0 : 1) << DDR_BANK_SHIFT | |
||||
(config.cs0_row - 13) << DDR_CS0_ROW_SHIFT | |
||||
(config.cs1_row - 13) << DDR_CS1_ROW_SHIFT | |
||||
1 << DDR_BW_SHIFT | config.bw << DDR_DIE_BW_SHIFT; |
||||
writel(os_reg, &priv->grf->os_reg[1]); |
||||
} |
||||
|
||||
size_t sdram_size(void) |
||||
{ |
||||
u32 size, os_reg, cs0_row, cs1_row, col, bank, rank; |
||||
struct rk3036_grf *grf = (void *)GRF_BASE; |
||||
|
||||
os_reg = readl(&grf->os_reg[1]); |
||||
|
||||
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; |
||||
} |
||||
|
||||
void sdram_init(void) |
||||
{ |
||||
struct rk3036_sdram_priv sdram_priv; |
||||
|
||||
sdram_priv.cru = (void *)CRU_BASE; |
||||
sdram_priv.grf = (void *)GRF_BASE; |
||||
sdram_priv.phy = (void *)DDR_PHY_BASE; |
||||
sdram_priv.pctl = (void *)DDR_PCTL_BASE; |
||||
sdram_priv.axi_bus = (void *)CPU_AXI_BUS_BASE; |
||||
|
||||
get_ddr_config(&sdram_priv.ddr_config); |
||||
sdram_all_config(&sdram_priv); |
||||
rkdclk_init(&sdram_priv); |
||||
phy_pctrl_reset(&sdram_priv); |
||||
phy_dll_bypass_set(&sdram_priv, ddr_timing.freq); |
||||
pctl_cfg(&sdram_priv); |
||||
phy_cfg(&sdram_priv); |
||||
writel(POWER_UP_START, &sdram_priv.pctl->powctl); |
||||
while (!(readl(&sdram_priv.pctl->powstat) & POWER_UP_DONE)) |
||||
; |
||||
memory_init(&sdram_priv); |
||||
move_to_config_state(&sdram_priv); |
||||
data_training(&sdram_priv); |
||||
move_to_access_state(&sdram_priv); |
||||
dram_cfg_rbc(&sdram_priv); |
||||
} |
Loading…
Reference in new issue