Skip to content
Snippets Groups Projects
emif-common.c 36.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	if (!(is_lpddr2_sdram_present(base, cs, lpddr2_dev_details)))
    		return NULL;
    
    	display_sdram_details(emif_num(base), cs, lpddr2_dev_details);
    
    	return lpddr2_dev_details;
    }
    #endif /* CONFIG_SYS_AUTOMATIC_SDRAM_DETECTION */
    
    
    Aneesh V's avatar
    Aneesh V committed
    static void do_sdram_init(u32 base)
    {
    	const struct emif_regs *regs;
    	u32 in_sdram, emif_nr;
    
    	debug(">>do_sdram_init() %x\n", base);
    
    	in_sdram = running_from_sdram();
    
    	emif_nr = (base == EMIF1_BASE) ? 1 : 2;
    
    #ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
    
    Aneesh V's avatar
    Aneesh V committed
    	emif_get_reg_dump(emif_nr, &regs);
    	if (!regs) {
    		debug("EMIF: reg dump not provided\n");
    		return;
    	}
    
    #else
    	/*
    	 * The user has not provided the register values. We need to
    	 * calculate it based on the timings and the DDR frequency
    	 */
    	struct emif_device_details dev_details;
    	struct emif_regs calculated_regs;
    
    	/*
    	 * Get device details:
    	 * - Discovered if CONFIG_SYS_AUTOMATIC_SDRAM_DETECTION is set
    	 * - Obtained from user otherwise
    	 */
    	struct lpddr2_device_details cs0_dev_details, cs1_dev_details;
    
    	emif_reset_phy(base);
    
    	dev_details.cs0_device_details = emif_get_device_details(emif_nr, CS0,
    
    						&cs0_dev_details);
    
    	dev_details.cs1_device_details = emif_get_device_details(emif_nr, CS1,
    
    						&cs1_dev_details);
    	emif_reset_phy(base);
    
    
    	/* Return if no devices on this EMIF */
    	if (!dev_details.cs0_device_details &&
    	    !dev_details.cs1_device_details) {
    		return;
    	}
    
    	/*
    	 * Get device timings:
    	 * - Default timings specified by JESD209-2 if
    	 *   CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS is set
    	 * - Obtained from user otherwise
    	 */
    	emif_get_device_timings(emif_nr, &dev_details.cs0_device_timings,
    				&dev_details.cs1_device_timings);
    
    	/* Calculate the register values */
    
    	emif_calculate_regs(&dev_details, omap_ddr_clk(), &calculated_regs);
    
    	regs = &calculated_regs;
    #endif /* CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS */
    
    Aneesh V's avatar
    Aneesh V committed
    
    	/*
    	 * Initializing the LPDDR2 device can not happen from SDRAM.
    	 * Changing the timing registers in EMIF can happen(going from one
    	 * OPP to another)
    	 */
    
    	if (!(in_sdram || warm_reset())) {
    
    		if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2)
    
    			lpddr2_init(base, regs);
    		else
    			ddr3_init(base, regs);
    	}
    
    	if (warm_reset() && (emif_sdram_type() == EMIF_SDRAM_TYPE_DDR3)) {
    		set_lpmode_selfrefresh(base);
    		emif_reset_phy(base);
    		ddr3_leveling(base, regs);
    	}
    
    Aneesh V's avatar
    Aneesh V committed
    
    	/* Write to the shadow registers */
    	emif_update_timings(base, regs);
    
    	debug("<<do_sdram_init() %x\n", base);
    }
    
    
    void emif_post_init_config(u32 base)
    
    Aneesh V's avatar
    Aneesh V committed
    {
    	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
    
    Aneesh V's avatar
    Aneesh V committed
    	/* reset phy on ES2.0 */
    
    	if (omap_rev == OMAP4430_ES2_0)
    
    Aneesh V's avatar
    Aneesh V committed
    		emif_reset_phy(base);
    
    	/* Put EMIF back in smart idle on ES1.0 */
    
    	if (omap_rev == OMAP4430_ES1_0)
    
    Aneesh V's avatar
    Aneesh V committed
    		writel(0x80000000, &emif->emif_pwr_mgmt_ctrl);
    }
    
    
    Aneesh V's avatar
    Aneesh V committed
    {
    	const struct dmm_lisa_map_regs *lisa_map_regs;
    
    	u32 i, section, valid;
    
    #ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
    
    Aneesh V's avatar
    Aneesh V committed
    	emif_get_dmm_regs(&lisa_map_regs);
    
    #else
    	u32 emif1_size, emif2_size, mapped_size, section_map = 0;
    	u32 section_cnt, sys_addr;
    	struct dmm_lisa_map_regs lis_map_regs_calculated = {0};
    
    	mapped_size = 0;
    	section_cnt = 3;
    	sys_addr = CONFIG_SYS_SDRAM_BASE;
    
    	emif1_size = get_emif_mem_size(EMIF1_BASE);
    	emif2_size = get_emif_mem_size(EMIF2_BASE);
    
    	debug("emif1_size 0x%x emif2_size 0x%x\n", emif1_size, emif2_size);
    
    	if (!emif1_size && !emif2_size)
    		return;
    
    	/* symmetric interleaved section */
    	if (emif1_size && emif2_size) {
    		mapped_size = min(emif1_size, emif2_size);
    		section_map = DMM_LISA_MAP_INTERLEAVED_BASE_VAL;
    
    		section_map |= 0 << EMIF_SDRC_ADDR_SHIFT;
    
    		/* only MSB */
    		section_map |= (sys_addr >> 24) <<
    
    		section_map |= get_dmm_section_size_map(mapped_size * 2)
    
    		lis_map_regs_calculated.dmm_lisa_map_3 = section_map;
    		emif1_size -= mapped_size;
    		emif2_size -= mapped_size;
    		sys_addr += (mapped_size * 2);
    		section_cnt--;
    	}
    
    	/*
    	 * Single EMIF section(we can have a maximum of 1 single EMIF
    	 * section- either EMIF1 or EMIF2 or none, but not both)
    	 */
    	if (emif1_size) {
    		section_map = DMM_LISA_MAP_EMIF1_ONLY_BASE_VAL;
    		section_map |= get_dmm_section_size_map(emif1_size)
    
    		/* only MSB */
    		section_map |= (mapped_size >> 24) <<
    
    		/* only MSB */
    
    		section_map |= (sys_addr >> 24) << EMIF_SYS_ADDR_SHIFT;
    
    		section_cnt--;
    	}
    	if (emif2_size) {
    		section_map = DMM_LISA_MAP_EMIF2_ONLY_BASE_VAL;
    		section_map |= get_dmm_section_size_map(emif2_size) <<
    
    		/* only MSB */
    
    		section_map |= mapped_size >> 24 << EMIF_SDRC_ADDR_SHIFT;
    
    		/* only MSB */
    
    		section_map |= sys_addr >> 24 << EMIF_SYS_ADDR_SHIFT;
    
    		section_cnt--;
    	}
    
    	if (section_cnt == 2) {
    		/* Only 1 section - either symmetric or single EMIF */
    		lis_map_regs_calculated.dmm_lisa_map_3 = section_map;
    		lis_map_regs_calculated.dmm_lisa_map_2 = 0;
    		lis_map_regs_calculated.dmm_lisa_map_1 = 0;
    	} else {
    		/* 2 sections - 1 symmetric, 1 single EMIF */
    		lis_map_regs_calculated.dmm_lisa_map_2 = section_map;
    		lis_map_regs_calculated.dmm_lisa_map_1 = 0;
    	}
    
    	/* TRAP for invalid TILER mappings in section 0 */
    	lis_map_regs_calculated.dmm_lisa_map_0 = DMM_LISA_MAP_0_INVAL_ADDR_TRAP;
    
    	lisa_map_regs = &lis_map_regs_calculated;
    #endif
    
    Aneesh V's avatar
    Aneesh V committed
    	struct dmm_lisa_map_regs *hw_lisa_map_regs =
    	    (struct dmm_lisa_map_regs *)base;
    
    	writel(0, &hw_lisa_map_regs->dmm_lisa_map_3);
    	writel(0, &hw_lisa_map_regs->dmm_lisa_map_2);
    	writel(0, &hw_lisa_map_regs->dmm_lisa_map_1);
    	writel(0, &hw_lisa_map_regs->dmm_lisa_map_0);
    
    	writel(lisa_map_regs->dmm_lisa_map_3,
    		&hw_lisa_map_regs->dmm_lisa_map_3);
    	writel(lisa_map_regs->dmm_lisa_map_2,
    		&hw_lisa_map_regs->dmm_lisa_map_2);
    	writel(lisa_map_regs->dmm_lisa_map_1,
    		&hw_lisa_map_regs->dmm_lisa_map_1);
    	writel(lisa_map_regs->dmm_lisa_map_0,
    		&hw_lisa_map_regs->dmm_lisa_map_0);
    
    	if (lisa_map_regs->is_ma_present) {
    
    		hw_lisa_map_regs =
    
    		    (struct dmm_lisa_map_regs *)MA_BASE;
    
    
    		writel(lisa_map_regs->dmm_lisa_map_3,
    			&hw_lisa_map_regs->dmm_lisa_map_3);
    		writel(lisa_map_regs->dmm_lisa_map_2,
    			&hw_lisa_map_regs->dmm_lisa_map_2);
    		writel(lisa_map_regs->dmm_lisa_map_1,
    			&hw_lisa_map_regs->dmm_lisa_map_1);
    		writel(lisa_map_regs->dmm_lisa_map_0,
    			&hw_lisa_map_regs->dmm_lisa_map_0);
    	}
    
    
    	/*
    	 * EMIF should be configured only when
    	 * memory is mapped on it. Using emif1_enabled
    	 * and emif2_enabled variables for this.
    	 */
    	emif1_enabled = 0;
    	emif2_enabled = 0;
    	for (i = 0; i < 4; i++) {
    		section	= __raw_readl(DMM_BASE + i*4);
    		valid = (section & EMIF_SDRC_MAP_MASK) >>
    			(EMIF_SDRC_MAP_SHIFT);
    		if (valid == 3) {
    			emif1_enabled = 1;
    			emif2_enabled = 1;
    			break;
    		} else if (valid == 1) {
    			emif1_enabled = 1;
    		} else if (valid == 2) {
    			emif2_enabled = 1;
    		}
    	}
    
    
    Aneesh V's avatar
    Aneesh V committed
    }
    
    /*
     * SDRAM initialization:
     * SDRAM initialization has two parts:
     * 1. Configuring the SDRAM device
     * 2. Update the AC timings related parameters in the EMIF module
     * (1) should be done only once and should not be done while we are
     * running from SDRAM.
     * (2) can and should be done more than once if OPP changes.
     * Particularly, this may be needed when we boot without SPL and
     * and using Configuration Header(CH). ROM code supports only at 50% OPP
     * at boot (low power boot). So u-boot has to switch to OPP100 and update
     * the frequency. So,
     * Doing (1) and (2) makes sense - first time initialization
     * Doing (2) and not (1) makes sense - OPP change (when using CH)
     * Doing (1) and not (2) doen't make sense
     * See do_sdram_init() for the details
     */
    void sdram_init(void)
    {
    	u32 in_sdram, size_prog, size_detect;
    
    	u32 sdram_type = emif_sdram_type();
    
    Aneesh V's avatar
    Aneesh V committed
    
    	debug(">>sdram_init()\n");
    
    
    	if (omap_hw_init_context() == OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL)
    
    Aneesh V's avatar
    Aneesh V committed
    		return;
    
    	in_sdram = running_from_sdram();
    	debug("in_sdram = %d\n", in_sdram);
    
    
    	if (!in_sdram) {
    		if ((sdram_type == EMIF_SDRAM_TYPE_LPDDR2) && !warm_reset())
    
    			bypass_dpll((*prcm)->cm_clkmode_dpll_core);
    
    		else if (sdram_type == EMIF_SDRAM_TYPE_DDR3)
    
    			writel(CM_DLL_CTRL_NO_OVERRIDE, (*prcm)->cm_dll_ctrl);
    
    	if (emif1_enabled)
    		do_sdram_init(EMIF1_BASE);
    
    	if (emif2_enabled)
    		do_sdram_init(EMIF2_BASE);
    
    
    	if (!(in_sdram || warm_reset())) {
    
    		if (emif1_enabled)
    			emif_post_init_config(EMIF1_BASE);
    		if (emif2_enabled)
    			emif_post_init_config(EMIF2_BASE);
    
    Aneesh V's avatar
    Aneesh V committed
    	}
    
    	/* for the shadow registers to take effect */
    
    	if (sdram_type == EMIF_SDRAM_TYPE_LPDDR2)
    
    		freq_update_core();
    
    Aneesh V's avatar
    Aneesh V committed
    
    	/* Do some testing after the init */
    	if (!in_sdram) {
    
    		size_prog = omap_sdram_size();
    
    		size_prog = log_2_n_round_down(size_prog);
    		size_prog = (1 << size_prog);
    
    
    Aneesh V's avatar
    Aneesh V committed
    		size_detect = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
    						size_prog);
    		/* Compare with the size programmed */
    		if (size_detect != size_prog) {
    			printf("SDRAM: identified size not same as expected"
    				" size identified: %x expected: %x\n",
    				size_detect,
    				size_prog);
    		} else
    			debug("get_ram_size() successful");
    	}
    
    	debug("<<sdram_init()\n");
    }