25.03.2019 10:45, Joseph Lo пишет: > This patch adds the required APIs and variables for the EMC scaling > sequence code on Tegra210. > > Based on the work of Peter De Schrijver <pdeschrijver@xxxxxxxxxx>. > > Signed-off-by: Joseph Lo <josephl@xxxxxxxxxx> > --- > drivers/memory/tegra/tegra210-emc-reg.h | 265 +++++++ > drivers/memory/tegra/tegra210-emc.c | 923 ++++++++++++++++++++++++ > 2 files changed, 1188 insertions(+) > > diff --git a/drivers/memory/tegra/tegra210-emc-reg.h b/drivers/memory/tegra/tegra210-emc-reg.h > index 84fcc85f3b6d..31a69e718dbc 100644 > --- a/drivers/memory/tegra/tegra210-emc-reg.h > +++ b/drivers/memory/tegra/tegra210-emc-reg.h > @@ -12,6 +12,13 @@ > > #include "mc.h" > > +#define DVFS_FGCG_HIGH_SPEED_THRESHOLD 1000 > +#define IOBRICK_DCC_THRESHOLD 2400 > +#define DVFS_FGCG_MID_SPEED_THRESHOLD 600 > + > +#define EMC_STATUS_UPDATE_TIMEOUT 1000 > + > +#define MC_EMEM_ADR_CFG 0x54 > #define MC_EMEM_ARB_CFG 0x90 > #define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 > #define MC_EMEM_ARB_TIMING_RCD 0x98 > @@ -75,12 +82,33 @@ > #define EMC_CLK_EMC_2X_CLK_SRC_SHIFT 29 > #define EMC_CLK_EMC_2X_CLK_SRC_MASK \ > (0x7 << EMC_CLK_EMC_2X_CLK_SRC_SHIFT) > +#define EMC_CLK_SOURCE_PLLM_LJ 0x4 > +#define EMC_CLK_SOURCE_PLLMB_LJ 0x5 > #define EMC_CLK_MC_EMC_SAME_FREQ BIT(16) > #define EMC_CLK_EMC_2X_CLK_DIVISOR_SHIFT 0 > #define EMC_CLK_EMC_2X_CLK_DIVISOR_MASK \ > (0xff << EMC_CLK_EMC_2X_CLK_DIVISOR_SHIFT) > > +#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664 > +#define DLL_CLK_EMC_DLL_CLK_SRC_SHIFT 29 > +#define DLL_CLK_EMC_DLL_CLK_SRC_MASK \ > + (0x7 << DLL_CLK_EMC_DLL_CLK_SRC_SHIFT) > +#define DLL_CLK_EMC_DLL_DDLL_CLK_SEL_SHIFT 10 > +#define DLL_CLK_EMC_DLL_DDLL_CLK_SEL_MASK \ > + (0x3 << DLL_CLK_EMC_DLL_DDLL_CLK_SEL_SHIFT) > +#define PLLM_VCOA 0 > +#define PLLM_VCOB 1 > +#define EMC_DLL_SWITCH_OUT 2 > +#define DLL_CLK_EMC_DLL_CLK_DIVISOR_SHIFT 0 > +#define DLL_CLK_EMC_DLL_CLK_DIVISOR_MASK \ > + (0xff << DLL_CLK_EMC_DLL_CLK_DIVISOR_SHIFT) > + > +#define EMC_INTSTATUS 0x0 > +#define EMC_INTSTATUS_CLKCHANGE_COMPLETE BIT(4) > +#define EMC_DBG 0x8 > +#define EMC_DBG_WRITE_MUX_ACTIVE BIT(1) > #define EMC_CFG 0xc > +#define EMC_TIMING_CONTROL 0x28 > #define EMC_RC 0x2c > #define EMC_RFC 0x30 > #define EMC_RAS 0x34 > @@ -125,16 +153,40 @@ > #define EMC_FBIO_CFG5_DRAM_TYPE_SHIFT 0 > #define EMC_FBIO_CFG5_DRAM_TYPE_MASK \ > (0x3 << EMC_FBIO_CFG5_DRAM_TYPE_SHIFT) > +#define EMC_FBIO_CFG5_CMD_TX_DIS BIT(8) > + > #define EMC_PDEX2CKE 0x118 > #define EMC_CKE2PDEN 0x11c > +#define EMC_MPC 0x128 > #define EMC_R2R 0x144 > #define EMC_EINPUT 0x14c > #define EMC_EINPUT_DURATION 0x150 > #define EMC_PUTERM_EXTRA 0x154 > #define EMC_TCKESR 0x158 > #define EMC_TPD 0x15c > +#define EMC_EMC_STATUS 0x2b4 > +#define EMC_EMC_STATUS_TIMING_UPDATE_STALLED BIT(23) > #define EMC_CFG_DIG_DLL 0x2bc > +#define EMC_CFG_DIG_DLL_CFG_DLL_EN BIT(0) > +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_UNTIL_LOCK BIT(1) > +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_TRAFFIC BIT(3) > +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_RW_UNTIL_LOCK BIT(4) > +#define EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT 6 > +#define EMC_CFG_DIG_DLL_CFG_DLL_MODE_MASK \ > + (0x3 << EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT) > +#define EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_SHIFT 8 > +#define EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_MASK \ > + (0x7 << EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_SHIFT) > + > #define EMC_CFG_DIG_DLL_PERIOD 0x2c0 > +#define EMC_DIG_DLL_STATUS 0x2c4 > +#define EMC_DIG_DLL_STATUS_DLL_LOCK BIT(15) > +#define EMC_DIG_DLL_STATUS_DLL_PRIV_UPDATED BIT(17) > +#define EMC_DIG_DLL_STATUS_DLL_OUT_SHIFT 0 > +#define EMC_DIG_DLL_STATUS_DLL_OUT_MASK \ > + (0x7ff << EMC_DIG_DLL_STATUS_DLL_OUT_SHIFT) > + > +#define EMC_CFG_DIG_DLL_1 0x2c8 > #define EMC_RDV_MASK 0x2cc > #define EMC_WDV_MASK 0x2d0 > #define EMC_RDV_EARLY_MASK 0x2d4 > @@ -153,6 +205,8 @@ > #define EMC_PRE_REFRESH_REQ_CNT 0x3dc > #define EMC_DYN_SELF_REF_CONTROL 0x3e0 > #define EMC_TXSRDLL 0x3e4 > +#define EMC_CCFIFO_ADDR 0x3e8 > +#define EMC_CCFIFO_DATA 0x3ec > #define EMC_TR_QPOP 0x3f4 > #define EMC_TR_RDV_MASK 0x3f8 > #define EMC_TR_QSAFE 0x3fc > @@ -185,8 +239,60 @@ > #define EMC_PUTERM_WIDTH 0x56c > #define EMC_REFCTRL2 0x580 > #define EMC_FBIO_CFG7 0x584 > +#define EMC_FBIO_CFG7_CH0_ENABLE BIT(1) > +#define EMC_FBIO_CFG7_CH1_ENABLE BIT(2) > #define EMC_DATA_BRLSHFT_0 0x588 > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT 21 > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT 18 > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT 15 > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT 12 > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT 9 > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT 6 > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT 3 > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT 0 > +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT) > + > #define EMC_DATA_BRLSHFT_1 0x58c > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT 21 > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT 18 > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT 15 > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT 12 > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT 9 > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT 6 > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT 3 > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT) > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT 0 > +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_MASK \ > + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT) > + > #define EMC_RFCPB 0x590 > #define EMC_DQS_BRLSHFT_0 0x594 > #define EMC_DQS_BRLSHFT_1 0x598 > @@ -201,6 +307,10 @@ > #define EMC_QUSE_BRLSHFT_3 0x5c4 > #define EMC_DLL_CFG_0 0x5e4 > #define EMC_DLL_CFG_1 0x5e8 > +#define EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_SHIFT 10 > +#define EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_MASK \ > + (0x7ff << EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_SHIFT) > + > #define EMC_CONFIG_SAMPLE_DELAY 0x5f0 > #define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600 > #define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604 > @@ -215,15 +325,103 @@ > #define EMC_PMACRO_QUSE_DDLL_RANK1_4 0x630 > #define EMC_PMACRO_QUSE_DDLL_RANK1_5 0x634 > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 0x640 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_SHIFT \ > + 16 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_SHIFT) > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_SHIFT \ > + 0 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_SHIFT) > + > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 0x644 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_SHIFT \ > + 16 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_SHIFT) > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_SHIFT \ > + 0 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_SHIFT) > + > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 0x648 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_SHIFT \ > + 16 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_SHIFT) > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_SHIFT \ > + 0 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_SHIFT) > + > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 0x64c > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_SHIFT \ > + 16 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_SHIFT) > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_SHIFT \ > + 0 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_SHIFT) > + > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4 0x650 > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5 0x654 > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 0x660 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_SHIFT \ > + 16 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_SHIFT) > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_SHIFT \ > + 0 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_SHIFT) > + > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 0x664 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_SHIFT \ > + 16 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_SHIFT) > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_SHIFT \ > + 0 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_SHIFT) > + > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 0x668 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_SHIFT \ > + 16 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_SHIFT) > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_SHIFT \ > + 0 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_SHIFT) > + > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 0x66c > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_SHIFT \ > + 16 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_SHIFT) > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_SHIFT \ > + 0 > +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_MASK \ > + (0x3ff << \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_SHIFT) > + > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4 0x670 > #define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5 0x674 > #define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0 0x680 > @@ -432,7 +630,18 @@ > #define EMC_PMACRO_CMD_RX_TERM_MODE 0xc58 > #define EMC_PMACRO_DATA_RX_TERM_MODE 0xc5c > #define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60 > +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_E_DCC BIT(1) > +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSP_TX_E_DCC BIT(9) > +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSN_TX_E_DCC BIT(16) > +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_CMD_TX_E_DCC BIT(24) > +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_DRVFORCEON BIT(26) > + > #define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64 > +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_TX_E_DCC BIT(1) > +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSP_TX_E_DCC BIT(9) > +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC BIT(16) > +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC BIT(24) > + > #define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68 > #define EMC_PMACRO_AUTOCAL_CFG_COMMON 0xc78 > #define EMC_PMACRO_VTTGEN_CTRL_2 0xcf0 > @@ -954,6 +1163,16 @@ enum { > DRAM_TYPE_DDR2 = 3, > }; > > +enum { > + SINGLE_CHANNEL = 0, > + DUAL_CHANNEL > +}; > + > +enum { > + DLL_OFF, > + DLL_ON > +}; > + > struct emc_table { > u32 rev; > char dvfs_ver[60]; > @@ -1075,9 +1294,55 @@ struct supported_sequence { > char *seq_rev; > }; > > +extern u32 burst_mc_regs_off[]; > +extern u32 burst_regs_off[]; > +extern u32 burst_regs_per_ch_off[]; > +extern u32 burst_regs_per_ch_type[]; > +extern unsigned long dram_over_temp_state; > +extern u32 la_scale_regs_off[]; > +extern u32 trim_regs_off[]; > +extern u32 trim_regs_per_ch_off[]; > +extern u32 trim_regs_per_ch_type[]; > +extern u32 vref_regs_per_ch_off[]; > +extern u32 vref_regs_per_ch_type[]; > + > +void ccfifo_writel(struct tegra_emc *emc, u32 val, unsigned long addr, > + u32 delay); > +u32 div_o3(u32 a, u32 b); > +void emc_writel(struct tegra_emc *emc, u32 val, unsigned long offset); > +u32 emc_readl(struct tegra_emc *emc, unsigned long offset); > +void emc_writel_per_ch(struct tegra_emc *emc, u32 val, int type, > + unsigned long offset); > +u32 emc1_readl(struct tegra_emc *emc, unsigned long offset); > + > +void do_clock_change(struct tegra_emc *emc, u32 clksrc); > +void emc_set_shadow_bypass(struct tegra_emc *emc, int set); > +void emc_timing_update(struct tegra_emc *emc, int dual_chan); > +u32 get_dll_state(struct emc_table *next_timing); > +struct emc_table *get_timing_from_freq(struct tegra_emc *emc, > + unsigned long rate); > +void set_over_temp_timing(struct tegra_emc *emc, struct emc_table *timing, > + unsigned long state); > int tegra_emc_dt_parse_pdata(struct platform_device *pdev, > struct emc_table **tables, > struct emc_table **derated_tables, > int *num_entries); > +u32 tegra210_actual_osc_clocks(u32 in); > +u32 tegra210_apply_periodic_compensation_trimmer(struct emc_table *next_timing, > + u32 offset); > +void tegra210_dll_disable(struct tegra_emc *emc, int channel_mode); > +void tegra210_dll_enable(struct tegra_emc *emc, int channel_mode); > +u32 tegra210_dll_prelock(struct tegra_emc *emc, int dvfs_with_training, > + u32 clksrc); > +u32 tegra210_dvfs_power_ramp_down(struct tegra_emc *emc, u32 clk, > + int flip_backward); > +u32 tegra210_dvfs_power_ramp_up(struct tegra_emc *emc, u32 clk, > + int flip_backward); > +void tegra210_update_emc_alt_timing(struct tegra_emc *emc, > + struct emc_table *current_timing); > +void tegra210_reset_dram_clktree_values(struct emc_table *table); > +void tegra210_start_periodic_compensation(struct tegra_emc *emc); > +int wait_for_update(struct tegra_emc *emc, u32 status_reg, u32 bit_mask, > + bool updated_state, int chan); > > #endif > diff --git a/drivers/memory/tegra/tegra210-emc.c b/drivers/memory/tegra/tegra210-emc.c > index 0c20bcd0e6de..26d0de0ab319 100644 > --- a/drivers/memory/tegra/tegra210-emc.c > +++ b/drivers/memory/tegra/tegra210-emc.c > @@ -20,6 +20,37 @@ > #define TEGRA_EMC_TABLE_MAX_SIZE 16 > #define TEGRA210_EMC_SUSPEND_RATE 204000000 > > +#define EMC0_EMC_DATA_BRLSHFT_0_INDEX 2 > +#define EMC1_EMC_DATA_BRLSHFT_0_INDEX 3 > +#define EMC0_EMC_DATA_BRLSHFT_1_INDEX 4 > +#define EMC1_EMC_DATA_BRLSHFT_1_INDEX 5 > + > +#define TRIM_REG(chan, rank, reg, byte) \ > + (((EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## reg ## \ > + _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte ## _MASK & \ > + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## \ > + rank ## _ ## reg ## _INDEX]) >> \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## reg ## \ > + _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte ## _SHIFT) \ > + + \ > + (((EMC_DATA_BRLSHFT_ ## rank ## _RANK ## rank ## _BYTE ## \ > + byte ## _DATA_BRLSHFT_MASK & \ > + next_timing->trim_perch_regs[EMC ## chan ## \ > + _EMC_DATA_BRLSHFT_ ## rank ## _INDEX]) >> \ > + EMC_DATA_BRLSHFT_ ## rank ## _RANK ## rank ## _BYTE ## \ > + byte ## _DATA_BRLSHFT_SHIFT) * 64)) > + > +#define CALC_TEMP(rank, reg, byte1, byte2, n) \ > + (((new[n] << EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## \ > + reg ## _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte1 ## _SHIFT) & \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## reg ## \ > + _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte1 ## _MASK) \ > + | \ > + ((new[n + 1] << EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ##\ > + reg ## _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte2 ## _SHIFT) & \ > + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## reg ## \ > + _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte2 ## _MASK)) \ > + > enum TEGRA_EMC_SOURCE { > TEGRA_EMC_SRC_PLLM, > TEGRA_EMC_SRC_PLLC, > @@ -32,6 +63,14 @@ enum TEGRA_EMC_SOURCE { > TEGRA_EMC_SRC_COUNT, > }; > > +enum { > + TEGRA_DRAM_OVER_TEMP_NONE = 0, > + TEGRA_DRAM_OVER_TEMP_REFRESH_X2, > + TEGRA_DRAM_OVER_TEMP_REFRESH_X4, > + TEGRA_DRAM_OVER_TEMP_THROTTLE, /* 4x Refresh + derating. */ > + TEGRA_DRAM_OVER_TEMP_MAX, > +}; > + > struct emc_sel { > struct clk *input; > u32 value; > @@ -76,6 +115,7 @@ static struct tegra_emc *tegra_emc; > static DEFINE_SPINLOCK(emc_access_lock); > static ktime_t clkchange_time; > static int clkchange_delay = 100; > +unsigned long dram_over_temp_state = TEGRA_DRAM_OVER_TEMP_NONE; > > static void emc_train(struct timer_list *tmr); > DEFINE_TIMER(emc_training_timer, emc_train); > @@ -102,11 +142,33 @@ static bool emc_suspend; > static unsigned long emc_resume_rate; > #endif > > +inline void emc_writel(struct tegra_emc *emc, u32 val, unsigned long offset) > +{ > + writel(val, emc->emc_base + offset); > +} > + > inline u32 emc_readl(struct tegra_emc *emc, unsigned long offset) > { > return readl(emc->emc_base + offset); > } > > +inline u32 emc1_readl(struct tegra_emc *emc, unsigned long offset) > +{ > + return readl(emc->emc1_base + offset); > +} Do you really need to insert a memory barrier on each readl/writel? Why not to use the relaxed versions? -- Dmitry