Skip to content
Snippets Groups Projects
emif.h 36.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • #define SDRAM_TEMP_LESS_LOW_SHUTDOWN			0x0
    #define SDRAM_TEMP_LESS_4X_REFRESH_AND_TIMINGS		0x1
    #define SDRAM_TEMP_LESS_2X_REFRESH_AND_TIMINGS		0x2
    #define SDRAM_TEMP_NOMINAL				0x3
    #define SDRAM_TEMP_RESERVED_4				0x4
    #define SDRAM_TEMP_HIGH_DERATE_REFRESH			0x5
    #define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS	0x6
    #define SDRAM_TEMP_VERY_HIGH_SHUTDOWN			0x7
    
    #define LPDDR2_MANUFACTURER_SAMSUNG	1
    #define LPDDR2_MANUFACTURER_QIMONDA	2
    #define LPDDR2_MANUFACTURER_ELPIDA	3
    #define LPDDR2_MANUFACTURER_ETRON	4
    #define LPDDR2_MANUFACTURER_NANYA	5
    #define LPDDR2_MANUFACTURER_HYNIX	6
    #define LPDDR2_MANUFACTURER_MOSEL	7
    #define LPDDR2_MANUFACTURER_WINBOND	8
    #define LPDDR2_MANUFACTURER_ESMT	9
    #define LPDDR2_MANUFACTURER_SPANSION 11
    #define LPDDR2_MANUFACTURER_SST		12
    #define LPDDR2_MANUFACTURER_ZMOS	13
    #define LPDDR2_MANUFACTURER_INTEL	14
    #define LPDDR2_MANUFACTURER_NUMONYX	254
    #define LPDDR2_MANUFACTURER_MICRON	255
    
    /* MR8 register fields */
    #define MR8_TYPE_SHIFT		0x0
    #define MR8_TYPE_MASK		0x3
    #define MR8_DENSITY_SHIFT	0x2
    #define MR8_DENSITY_MASK	(0xF << 0x2)
    #define MR8_IO_WIDTH_SHIFT	0x6
    #define MR8_IO_WIDTH_MASK	(0x3 << 0x6)
    
    
    /* SDRAM TYPE */
    #define EMIF_SDRAM_TYPE_DDR2	0x2
    #define EMIF_SDRAM_TYPE_DDR3	0x3
    #define EMIF_SDRAM_TYPE_LPDDR2	0x4
    
    
    struct lpddr2_addressing {
    	u8	num_banks;
    	u8	t_REFI_us_x10;
    	u8	row_sz[2]; /* One entry each for x32 and x16 */
    	u8	col_sz[2]; /* One entry each for x32 and x16 */
    };
    
    /* Structure for timings from the DDR datasheet */
    struct lpddr2_ac_timings {
    	u32 max_freq;
    	u8 RL;
    	u8 tRPab;
    	u8 tRCD;
    	u8 tWR;
    	u8 tRASmin;
    	u8 tRRD;
    	u8 tWTRx2;
    	u8 tXSR;
    	u8 tXPx2;
    	u8 tRFCab;
    	u8 tRTPx2;
    	u8 tCKE;
    	u8 tCKESR;
    	u8 tZQCS;
    	u32 tZQCL;
    	u32 tZQINIT;
    	u8 tDQSCKMAXx2;
    	u8 tRASmax;
    	u8 tFAW;
    
    };
    
    /*
     * Min tCK values for some of the parameters:
     * If the calculated clock cycles for the respective parameter is
     * less than the corresponding min tCK value, we need to set the min
     * tCK value. This may happen at lower frequencies.
     */
    struct lpddr2_min_tck {
    	u32 tRL;
    	u32 tRP_AB;
    	u32 tRCD;
    	u32 tWR;
    	u32 tRAS_MIN;
    	u32 tRRD;
    	u32 tWTR;
    	u32 tXP;
    	u32 tRTP;
    	u8  tCKE;
    	u32 tCKESR;
    	u32 tFAW;
    };
    
    struct lpddr2_device_details {
    	u8	type;
    	u8	density;
    	u8	io_width;
    	u8	manufacturer;
    };
    
    struct lpddr2_device_timings {
    	const struct lpddr2_ac_timings **ac_timings;
    	const struct lpddr2_min_tck *min_tck;
    };
    
    /* Details of the devices connected to each chip-select of an EMIF instance */
    struct emif_device_details {
    	const struct lpddr2_device_details *cs0_device_details;
    	const struct lpddr2_device_details *cs1_device_details;
    	const struct lpddr2_device_timings *cs0_device_timings;
    	const struct lpddr2_device_timings *cs1_device_timings;
    };
    
    /*
     * Structure containing shadow of important registers in EMIF
     * The calculation function fills in this structure to be later used for
     * initialization and DVFS
     */
    struct emif_regs {
    	u32 freq;
    	u32 sdram_config_init;
    	u32 sdram_config;
    
    	u32 ref_ctrl;
    	u32 sdram_tim1;
    	u32 sdram_tim2;
    	u32 sdram_tim3;
    	u32 read_idle_ctrl;
    	u32 zq_config;
    	u32 temp_alert_config;
    	u32 emif_ddr_phy_ctlr_1_init;
    	u32 emif_ddr_phy_ctlr_1;
    
    	u32 emif_ddr_ext_phy_ctrl_1;
    	u32 emif_ddr_ext_phy_ctrl_2;
    	u32 emif_ddr_ext_phy_ctrl_3;
    	u32 emif_ddr_ext_phy_ctrl_4;
    	u32 emif_ddr_ext_phy_ctrl_5;
    
    	u32 emif_rd_wr_lvl_rmp_win;
    	u32 emif_rd_wr_lvl_rmp_ctl;
    	u32 emif_rd_wr_lvl_ctl;
    	u32 emif_rd_wr_exec_thresh;
    
    struct lpddr2_mr_regs {
    	s8 mr1;
    	s8 mr2;
    	s8 mr3;
    	s8 mr10;
    	s8 mr16;
    };
    
    
    struct read_write_regs {
    	u32 read_reg;
    	u32 write_reg;
    };
    
    
    static inline u32 get_emif_rev(u32 base)
    {
    	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
    
    	return (readl(&emif->emif_mod_id_rev) & EMIF_REG_MAJOR_REVISION_MASK)
    		>> EMIF_REG_MAJOR_REVISION_SHIFT;
    }
    
    
    /*
     * Get SDRAM type connected to EMIF.
     * Assuming similar SDRAM parts are connected to both EMIF's
     * which is typically the case. So it is sufficient to get
     * SDRAM type from EMIF1.
     */
    static inline u32 emif_sdram_type(void)
    {
    	struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
    
    	return (readl(&emif->emif_sdram_config) &
    		EMIF_REG_SDRAM_TYPE_MASK) >> EMIF_REG_SDRAM_TYPE_SHIFT;
    }
    
    
    /* assert macros */
    #if defined(DEBUG)
    #define emif_assert(c)	({ if (!(c)) for (;;); })
    #else
    #define emif_assert(c)	({ if (0) hang(); })
    #endif
    
    #ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
    void emif_get_reg_dump(u32 emif_nr, const struct emif_regs **regs);
    void emif_get_dmm_regs(const struct dmm_lisa_map_regs **dmm_lisa_regs);
    #else
    struct lpddr2_device_details *emif_get_device_details(u32 emif_nr, u8 cs,
    			struct lpddr2_device_details *lpddr2_dev_details);
    void emif_get_device_timings(u32 emif_nr,
    		const struct lpddr2_device_timings **cs0_device_timings,
    		const struct lpddr2_device_timings **cs1_device_timings);
    #endif
    
    
    void do_ext_phy_settings(u32 base, const struct emif_regs *regs);
    
    void get_lpddr2_mr_regs(const struct lpddr2_mr_regs **regs);
    
    #ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
    extern u32 *const T_num;
    extern u32 *const T_den;
    #endif
    
    
    void config_data_eye_leveling_samples(u32 emif_base);
    
    u32 emif_sdram_type(void);
    
    const struct read_write_regs *get_bug_regs(u32 *iterations);