Example #1
0
u32 ddr3_init(void)
{
	struct ddr3_spd_cb spd_cb;

	if (ddr3_get_dimm_params_from_spd(&spd_cb)) {
		printf("Sorry, I don't know how to configure DDR3A.\n"
		       "Bye :(\n");
		for (;;)
			;
	}

	printf("Detected SO-DIMM [%s]\n", spd_cb.dimm_name);

	printf("DDR3 speed %d\n", spd_cb.ddrspdclock);
	if (spd_cb.ddrspdclock == 1600)
		init_pll(&ddr3_400);
	else
		init_pll(&ddr3_333);

	/* Reset DDR3 PHY after PLL enabled */
	ddr3_reset_ddrphy();

	spd_cb.phy_cfg.zq0cr1 |= 0x10000;
	spd_cb.phy_cfg.zq1cr1 |= 0x10000;
	spd_cb.phy_cfg.zq2cr1 |= 0x10000;
	ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &spd_cb.phy_cfg);
	ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &spd_cb.emif_cfg);

	printf("DRAM: %d GiB\n", spd_cb.ddr_size_gbyte);

	return (u32)spd_cb.ddr_size_gbyte;
}
Example #2
0
void clock_init(void)
{
	u32 osc = clock_get_osc_bits();

	/* Set PLLC dynramp_step A to 0x2b and B to 0xb (from U-Boot -- why? */
	write32(&clk_rst->pllc_misc2, 0x2b << 17 | 0xb << 9);

	/* Max out the AVP clock before everything else (need PLLC for that). */
	init_pll(&clk_rst->pllc_base, &clk_rst->pllc_misc,
		osc_table[osc].pllc, PLLC_MISC_LOCK_ENABLE);

	/* Typical ratios are 1:2:2 or 1:2:3 sclk:hclk:pclk (See: APB DMA
	 * features section in the TRM). */
	write32(&clk_rst->clk_sys_rate,
		TEGRA_HCLK_RATIO << HCLK_DIVISOR_SHIFT |
		TEGRA_PCLK_RATIO << PCLK_DIVISOR_SHIFT);
	write32(&clk_rst->pllc_out, CLK_DIVIDER(TEGRA_PLLC_KHZ, TEGRA_SCLK_KHZ)
		<< PLL_OUT_RATIO_SHIFT | PLL_OUT_CLKEN | PLL_OUT_RSTN);
	write32(&clk_rst->sclk_brst_pol,		/* sclk = 300 MHz */
		SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT |
		SCLK_SOURCE_PLLC_OUT1 << SCLK_RUN_SHIFT);

	/* Change the oscillator drive strength (from U-Boot -- why?) */
	clrsetbits_le32(&clk_rst->osc_ctrl, OSC_XOFS_MASK,
			OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT);

	/*
	 * Ambiguous quote from u-boot. TODO: what's this mean?
	 * "should update same value in PMC_OSC_EDPD_OVER XOFS
	 * field for warmboot "
	 */
	clrsetbits_le32(&pmc->osc_edpd_over, PMC_OSC_EDPD_OVER_XOFS_MASK,
			OSC_DRIVE_STRENGTH << PMC_OSC_EDPD_OVER_XOFS_SHIFT);

	/* Disable IDDQ for PLLX before we set it up (from U-Boot -- why?) */
	clrbits_le32(&clk_rst->pllx_misc3, PLLX_IDDQ_MASK);

	/* Set up PLLP_OUT(1|2|3|4) divisor to generate (9.6|48|102|204)MHz */
	write32(&clk_rst->pllp_outa,
		(CLK_DIVIDER(TEGRA_PLLP_KHZ, 9600) << PLL_OUT_RATIO_SHIFT |
		PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT1_SHIFT |
		(CLK_DIVIDER(TEGRA_PLLP_KHZ, 48000) << PLL_OUT_RATIO_SHIFT |
		PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT2_SHIFT);
	write32(&clk_rst->pllp_outb,
		(CLK_DIVIDER(TEGRA_PLLP_KHZ, 102000) << PLL_OUT_RATIO_SHIFT |
		PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT3_SHIFT |
		(CLK_DIVIDER(TEGRA_PLLP_KHZ, 204000) << PLL_OUT_RATIO_SHIFT |
		PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT4_SHIFT);

	/* init pllx */
	init_pll(&clk_rst->pllx_base, &clk_rst->pllx_misc,
		osc_table[osc].pllx, PLLPAXS_MISC_LOCK_ENABLE);

	/* init pllu */
	init_pll(&clk_rst->pllu_base, &clk_rst->pllu_misc,
		osc_table[osc].pllu, PLLUD_MISC_LOCK_ENABLE);

	init_utmip_pll();
	graphics_pll();
}
Example #3
0
/**
 * The T124 requires some special clock initialization, including setting up
 * the DVC I2C, turning on MSELECT and selecting the G CPU cluster
 */
void clock_init(void)
{
	u32 val;
	u32 osc = clock_get_osc_bits();

	/*
	 * On poweron, AVP clock source (also called system clock) is set to
	 * PLLP_out0 with frequency set at 1MHz. Before initializing PLLP, we
	 * need to move the system clock's source to CLK_M temporarily. And
	 * then switch it to PLLP_out4 (204MHz) at a later time.
	 */
	val = (SCLK_SOURCE_CLKM << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) |
		(SCLK_SOURCE_CLKM << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) |
		(SCLK_SOURCE_CLKM << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) |
		(SCLK_SOURCE_CLKM << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) |
		(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT);
	writel(val, &clk_rst->sclk_brst_pol);
	udelay(2);

	/* Set active CPU cluster to G */
	clrbits_le32(&flow->cluster_control, 1);

	/* Change the oscillator drive strength */
	val = readl(&clk_rst->osc_ctrl);
	val &= ~OSC_XOFS_MASK;
	val |= (OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT);
	writel(val, &clk_rst->osc_ctrl);

	/* Ambiguous quote from u-boot. TODO: what's this mean?
	 * "should update same value in PMC_OSC_EDPD_OVER XOFS
	   field for warmboot "*/
	val = readl(&pmc->osc_edpd_over);
	val &= ~PMC_OSC_EDPD_OVER_XOFS_MASK;
	val |= (OSC_DRIVE_STRENGTH << PMC_OSC_EDPD_OVER_XOFS_SHIFT);
	writel(val, &pmc->osc_edpd_over);

	/* Disable IDDQ for PLLX before we set it up (from U-Boot -- why?) */
	val = readl(&clk_rst->pllx_misc3);
	val &= ~PLLX_IDDQ_MASK;
	writel(val, &clk_rst->pllx_misc3);
	udelay(2);

	/* Set PLLC dynramp_step A to 0x2b and B to 0xb (from U-Boot -- why? */
	writel(0x2b << 17 | 0xb << 9, &clk_rst->pllc_misc2);

	adjust_pllp_out_freqs();

	init_pll(&clk_rst->pllx_base, &clk_rst->pllx_misc, osc_table[osc].pllx);
	init_pll(&clk_rst->pllp_base, &clk_rst->pllp_misc, osc_table[osc].pllp);
	init_pll(&clk_rst->pllc_base, &clk_rst->pllc_misc, osc_table[osc].pllc);
	init_pll(&clk_rst->plld_base, &clk_rst->plld_misc, osc_table[osc].plld);
	init_pll(&clk_rst->pllu_base, &clk_rst->pllu_misc, osc_table[osc].pllu);
	init_utmip_pll();

	val = (1 << CLK_SYS_RATE_AHB_RATE_SHIFT);
	writel(val, &clk_rst->clk_sys_rate);
}
Example #4
0
u32 ddr3_init(void)
{
	u32 ddr3_size;
	struct ddr3_spd_cb spd_cb;

	if (ddr3_get_dimm_params_from_spd(&spd_cb)) {
		printf("Sorry, I don't know how to configure DDR3A.\n"
		       "Bye :(\n");
		for (;;)
			;
	}

	printf("Detected SO-DIMM [%s]\n", spd_cb.dimm_name);

	if ((cpu_revision() > 1) ||
	    (__raw_readl(KS2_RSTCTRL_RSTYPE) & 0x1)) {
		printf("DDR3 speed %d\n", spd_cb.ddrspdclock);
		if (spd_cb.ddrspdclock == 1600)
			init_pll(&ddr3a_400);
		else
			init_pll(&ddr3a_333);
	}

	if (cpu_revision() > 0) {
		if (cpu_revision() > 1) {
			/* PG 2.0 */
			/* Reset DDR3A PHY after PLL enabled */
			ddr3_reset_ddrphy();
			spd_cb.phy_cfg.zq0cr1 |= 0x10000;
			spd_cb.phy_cfg.zq1cr1 |= 0x10000;
			spd_cb.phy_cfg.zq2cr1 |= 0x10000;
		}
		ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &(spd_cb.phy_cfg));

		ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &(spd_cb.emif_cfg));

		ddr3_size = spd_cb.ddr_size_gbyte;
	} else {
		ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &(spd_cb.phy_cfg));
		spd_cb.emif_cfg.sdcfg |= 0x1000;
		ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &(spd_cb.emif_cfg));
		ddr3_size = spd_cb.ddr_size_gbyte / 2;
	}
	printf("DRAM: %d GiB (includes reported below)\n", ddr3_size);

	/* Apply the workaround for PG 1.0 and 1.1 Silicons */
	if (cpu_revision() <= 1)
		ddr3_err_reset_workaround();

	return ddr3_size;
}
Example #5
0
/* Graphics just has to be different. There's a few more bits we
 * need to set in here, but it makes sense just to restrict all the
 * special bits to this one function.
 */
static void graphics_pll(void)
{
	int osc = clock_get_osc_bits();
	u32 *cfg = &clk_rst->plldp_ss_cfg;
	/* the vendor code sets the dither bit (28)
	 * an undocumented bit (24)
	 * and clamp while we mess with it (22)
	 * Dither is pretty important to display port
	 * so we really do need to handle these bits.
	 * I'm not willing to not clamp it, even if
	 * it might "mostly work" with it not set,
	 * I don't want to find out in a few months
	 * that it is needed.
	 */
	u32 scfg = (1<<28) | (1<<24) | (1<<22);
	write32(cfg, scfg);
	init_pll(&clk_rst->plldp_base, &clk_rst->plldp_misc,
		osc_table[osc].plldp, PLLDPD2_MISC_LOCK_ENABLE);
	/* leave dither and undoc bits set, release clamp */
	scfg = (1<<28) | (1<<24);
	write32(cfg, scfg);

	/* disp1 will be set when panel information (pixel clock) is
	 * retrieved (clock_display).
	 */
}
Example #6
0
void init_all(void)
{
	init_uart();
	init_pll();
	act8600_setting();
	init_ddr();
//	init_lcd();
	init_i2c();
//	init_pwm();
}
Example #7
0
void ddr3_init(void)
{
	init_pll(&ddr3_400);

	/* No SO-DIMM, 2GB discreet DDR */
	printf("DRAM: 2 GiB\n");
	ddr3_size = 2;

	/* Reset DDR3 PHY after PLL enabled */
	ddr3_reset_ddrphy();

	ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_2g);
	ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &ddr3_1600_2g);
}
Example #8
0
void init_ddr3(void)
{
	char dimm_name[32];
	u32 tmp;

	if (~(readl(K2L_PLL_CNTRL_BASE + MAIN_PLL_CTRL_RSTYPE) & 0x1))
		init_pll(&ddr3_400);

	/* No SO-DIMM, 2GB discreet DDR */
	printf("DRAM: 2 GiB\n");

	/* Reset DDR3 PHY after PLL enabled */
	reset_ddrphy(KS2_DEVICE_STATE_CTRL_BASE);

	init_ddrphy(K2L_DDR3_DDRPHYC, &ddr3phy_1600_2g);
	init_ddremif(K2L_DDR3_EMIF_CTRL_BASE, &ddr3_1600_2g);
}
Example #9
0
void hi6220_pll_init(void)
{
	uint32_t data;

	init_pll();
	init_freq();

	/*
	 * Init DDR with 533MHz. Otherwise, DDR initialization
	 * may fail on 800MHz on some boards.
	 */
	ddr_phy_reset();
	init_ddr(0);
	/* Init DDR with 800MHz. */
	ddr_phy_reset();
	init_ddr(1);


	ddrc_common_init(1);
	dienum_det_and_rowcol_cfg();
	detect_ddr_chip_info();

	data = mmio_read_32(0xf7032000 + 0x010);
	data &= ~0x1;
	mmio_write_32(0xf7032000 + 0x010, data);
	data = mmio_read_32(0xf7032000 + 0x010);

	/*
	 * Test memory access. Do not use address 0x0 because the compiler
	 * may assume it is not a valid address and generate incorrect code
	 * (GCC 4.9.1 without -fno-delete-null-pointer-checks for instance).
	 */
	mmio_write_32(0x4, 0xa5a55a5a);
	INFO("ddr test value:0x%x\n", mmio_read_32(0x4));
	init_ddrc_qos();

	init_mmc0_pll();
	reset_mmc0_clk();
	init_media_clk();

	dsb();

	init_mmc1_pll();
	reset_mmc1_clk();
}
Example #10
0
int main()
{
    TRISA = 0;
    TRISB = BIT(0)|BIT(1)|BIT(3)|BIT(7)|BIT(12);
	TRISC = 0;
    OUTER_LED = OFF;
    INNER_LED = OFF;

    init_pll();
    peripheral_pin_config();
    init_uart1();
    init_spi();
    init_adc();
    init_timer1();
            
    TX_string("Wait\r\n");
    delay(1000);
    TX_string("Start\r\n");
        
    T1CONbits.TON = 1; 
    
    //remove first trash reading
    tiltX = accelRead(XINCL);
    gRead = gyroRead(GRATE);    
    while(1)
    {
        if( newData == TRUE)
        {
            TX_snum5(gRead);
            TX('\t');
            TX_snum5(tilt);
            TX('\t');
            TX_snum5(x_00);
            TX_string("\r\n");
           
            OUTER_LED = OFF;            
            newData = FALSE;
        }
    }  
    return 0;      
};
Example #11
0
AMD
newAMD (REAL samprate,
	REAL f_initial,
	REAL f_lobound,
	REAL f_hibound,
	REAL f_bandwid,
	int size, COMPLEX * ivec, COMPLEX * ovec, AMMode mode, char *tag)
{
	AMD am = (AMD) safealloc (1, sizeof (AMDDesc), tag);

	am->size = size;
	am->ibuf = newCXB (size, ivec, tag);
	am->obuf = newCXB (size, ovec, tag);
	am->mode = mode;
	init_pll (am, samprate, f_initial, f_lobound, f_hibound, f_bandwid);

	am->lock.curr = 0.5;
	am->lock.prev = 1.0;
	am->dc = 0.0;

	return am;
}
Example #12
0
void clock_cpu0_config(void)
{
	u32 reg;
	u32 osc = clock_get_osc_bits();
	u32 timeout = 0;

	/* disable IDDQ */
	reg = read32(&clst_clk->pllx_misc3);
	reg &= ~PLLX_IDDQ;
	write32(&clst_clk->pllx_misc3, reg);

	/* init pllx */
	init_pll(&clst_clk->pllx_base, &clst_clk->pllx_misc,
		osc_table[osc].pllx, PLLPAXS_MISC_LOCK_ENABLE);

	/*
	 * Change CPU clock source to PLLX_OUT0_LJ
	 * when above pllx programming has taken effect.
	 */
	do {
		if (read32(&clst_clk->misc_ctrl) & CLK_SWITCH_MATCH) {
			write32(&clst_clk->cclk_brst_pol,
				(CC_CCLK_BRST_POL_PLLX_OUT0_LJ << 28));
			break;
		}

		/* wait and try again */
		if (timeout >= CLK_SWITCH_TIMEOUT_US) {
			printk(BIOS_ERR, "%s: PLLX programming timeout. "
				"Switching cpu clock has falied.\n",
				__func__);
			break;
		}
		udelay(10);
		timeout += 10;

	} while (1);
}
Example #13
0
int do_pll_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	if (argc != 5)
		goto pll_cmd_usage;

	if (strncmp(argv[1], "pa", 2) == 0)
		cmd_pll_data.pll = PASS_PLL;
#ifndef CONFIG_SOC_K2E
	else if (strncmp(argv[1], "arm", 3) == 0)
		cmd_pll_data.pll = TETRIS_PLL;
#endif
#ifdef CONFIG_SOC_K2HK
	else if (strncmp(argv[1], "ddr3a", 5) == 0)
		cmd_pll_data.pll = DDR3A_PLL;
	else if (strncmp(argv[1], "ddr3b", 5) == 0)
		cmd_pll_data.pll = DDR3B_PLL;
#else
	else if (strncmp(argv[1], "ddr3", 4) == 0)
		cmd_pll_data.pll = DDR3_PLL;
#endif
	else
		goto pll_cmd_usage;

	cmd_pll_data.pll_m   = simple_strtoul(argv[2], NULL, 10);
	cmd_pll_data.pll_d   = simple_strtoul(argv[3], NULL, 10);
	cmd_pll_data.pll_od  = simple_strtoul(argv[4], NULL, 10);

	printf("Trying to set pll %d; mult %d; div %d; OD %d\n",
	       cmd_pll_data.pll, cmd_pll_data.pll_m,
	       cmd_pll_data.pll_d, cmd_pll_data.pll_od);
	init_pll(&cmd_pll_data);

	return 0;

pll_cmd_usage:
	return cmd_usage(cmdtp);
}
Example #14
0
/* ---------------------------------------------------------------------------- */
FMD
newFMD(REAL samprate,
       REAL f_initial,
       REAL f_lobound,
       REAL f_hibound,
       REAL f_bandwid,
       int size,
       COMPLEX *ivec,
       COMPLEX *ovec,
       char *tag) {
  FMD fm = (FMD) safealloc(1, sizeof(FMDDesc), tag);

  fm->size = size;
  fm->ibuf = newCXB(size, ivec, tag);
  fm->obuf = newCXB(size, ovec, tag);

  init_pll(fm, samprate, f_initial, f_lobound, f_hibound, f_bandwid);

  fm->lock = 0.5;
  fm->afc = 0.0;
  fm->cvt = (REAL) (0.45 * samprate / (M_PI * f_bandwid));

  return fm;
}
Example #15
0
void main(void) {
	// Have to init the clock first
	init_clock();

	// These initialize variables
	// Mostly just zeroing them
	okay_to_transmit = FALSE;
	server_wants_header = FALSE;
	inside_non_blocking_interrupt = FALSE;
	last_connect_time = 0;
	check_in_period = 0;
	setup_button_pressed = FALSE;
	setup_button_time_trigger = 0;
	setup_button_time_duration = 0;
	main_mode = MAIN_MODE_INIT;
	init_internal_wattage_sensor();
	init_temperature_sensor();
	init_audio_sensor();
	init_light_sensor();
	uint8_t itor = 0;
	for (itor = 0; itor < NUMBER_OF_AUX_PORTS; itor++) {
		aux_sensor[itor] = 0;
	}

	// These initialize functions and interrupts
	init_timer();
	init_time();
	init_leds();
	init_relay();
	init_uart();
	init_transmits();
	init_buttons();
	init_roving(&roving_call_back);

	setup_button_time_trigger = new_time();
	setup_button_time_duration = new_time();
	time_set_seconds(setup_button_time_duration, 2);

	_enable_interrupts();

	// confirm roving works
	while (!enter_command_mode()) {
		reset_roving();
		wait(500);
	}
	init_adc();
	init_pll();

	// This is for the check in
	// If we are disconnected, we wait 5 seconds before trying to reconnect
	last_connect_time = new_time();
	check_in_period = new_time();
	time_set_seconds(check_in_period, 5);


	// And go!!!

	set_led_anim(led_start);

	// MAIN LOOP
	while(1) {
		handle_roving_input();

		// Check if it a long hold
		if(setup_button_pressed) {
			// If the button is pressed down
			if(time_cmp(global_time(), setup_button_time_trigger) >= 0) {
				// If enough time has passed
				if(in_setup_mode()) {
					leave_setup_mode();
				} else {
					start_setup_mode();
				}
				// Only want to check this once
				setup_button_pressed = FALSE;
			}
		}


		// MAIN BEHAVIOR
		// There is setup_mode and main_mode.
		// Setup mode is for configuring WiFi SSID and PASS
		// Main mode is for sampling
		if (in_setup_mode()) {
			if(main_mode != MAIN_MODE_SETUP) {
				stop_sampling();
				set_led_anim(led_setup_start);
				main_mode = MAIN_MODE_SETUP;
			}
			do_setup();

		} else if (in_main_mode()) { //regular mode
			if(main_mode != MAIN_MODE_SAMPLE) {
				set_led_anim(led_main_start);
				start_sampling();
				main_mode = MAIN_MODE_SAMPLE;
			}

			if(!is_associated()) {
				associate();
			} else if (!have_dhcp()) {
				get_dhcp();
			} else {
				if(is_connected()) set_led_anim(led_main_connected);
				else set_led_anim(led_main_assoc);

				if(!is_connected() && (time_cmp(global_time(), last_connect_time) >= 0) ) {
					// If we are not connected, and enough time has passed, connect
					connect();
					add_time_to_time(last_connect_time, check_in_period);
				}

				if(server_wants_header) {
					led_ping();
					exit_command_mode();
					transmit_header();
					wait(100);
				}

				if(okay_to_transmit && have_data_to_transmit()) {
					led_ping();
					exit_command_mode();
					transmit_data();
				}


			}
		} else {
			main_mode = MAIN_MODE_INIT;
			set_led_anim(led_error);
			stop_sampling();
		}
	}
}
Example #16
0
/*
 * Init PLLD clock source.
 *
 * @frequency: the requested plld frequency
 *
 * Return the plld frequency if success, otherwise return 0.
 */
u32
clock_display(u32 frequency)
{
	/**
	 * plld (fo) = vco >> p, where 500MHz < vco < 1000MHz
	 *           = (cf * n) >> p, where 1MHz < cf < 6MHz
	 *           = ((ref / m) * n) >> p
	 *
	 * Iterate the possible values of p (3 bits, 2^7) to find out a minimum
	 * safe vco, then find best (m, n). since m has only 5 bits, we can
	 * iterate all possible values.  Note Tegra 124 supports 11 bits for n,
	 * but our pll_fields has only 10 bits for n.
	 *
	 * Note values undershoot or overshoot target output frequency may not
	 * work if the values are not in "safe" range by panel specification.
	 */
	struct pllpad_dividers plld = { 0 };
	u32 ref = clock_get_pll_input_khz() * 1000, m, n, p = 0;
	u32 cf, vco, rounded_rate = frequency;
	u32 diff, best_diff;
	const u32 max_m = 1 << 5, max_n = 1 << 10, max_p = 1 << 3,
		  mhz = 1000 * 1000, min_vco = 500 * mhz, max_vco = 1000 * mhz,
		  min_cf = 1 * mhz, max_cf = 6 * mhz;

	for (vco = frequency; vco < min_vco && p < max_p; p++)
		vco <<= 1;

	if (vco < min_vco || vco > max_vco) {
		printk(BIOS_ERR, "%s: Cannot find out a supported VCO"
			" for Frequency (%u).\n", __func__, frequency);
		return 0;
	}

	plld.p = p;
	best_diff = vco;

	for (m = 1; m < max_m && best_diff; m++) {
		cf = ref / m;
		if (cf < min_cf)
			break;
		if (cf > max_cf)
			continue;

		n = vco / cf;
		if (n >= max_n)
			continue;

		diff = vco - n * cf;
		if (n + 1 < max_n && diff > cf / 2) {
			n++;
			diff = cf - diff;
		}

		if (diff >= best_diff)
			continue;

		best_diff = diff;
		plld.m = m;
		plld.n = n;
	}

	if (plld.n < 50)
		plld.cpcon = 2;
	else if (plld.n < 300)
		plld.cpcon = 3;
	else if (plld.n < 600)
		plld.cpcon = 8;
	else
		plld.cpcon = 12;

	if (best_diff) {
		printk(BIOS_WARNING, "%s: Failed to match output frequency %u, "
		       "best difference is %u.\n", __func__, frequency,
		       best_diff);
		rounded_rate = (ref / plld.m * plld.n) >> plld.p;
	}

	printk(BIOS_DEBUG, "%s: PLLD=%u ref=%u, m/n/p/cpcon=%u/%u/%u/%u\n",
	       __func__, rounded_rate, ref, plld.m, plld.n, plld.p, plld.cpcon);

	init_pll(&clk_rst->plld_base, &clk_rst->plld_misc, plld,
		 (PLLUD_MISC_LOCK_ENABLE | PLLD_MISC_CLK_ENABLE));

	return rounded_rate;
}
Example #17
0
void ddr3_init(void)
{
	char dimm_name[32];

	ddr3_get_dimm_params(dimm_name);

	printf("Detected SO-DIMM [%s]\n", dimm_name);

	if (!strcmp(dimm_name, "18KSF1G72HZ-1G6E2 ")) {
		init_pll(&ddr3a_400);
		if (cpu_revision() > 0) {
			if (cpu_revision() > 1) {
				/* PG 2.0 */
				/* Reset DDR3A PHY after PLL enabled */
				ddr3_reset_ddrphy();
				ddr3phy_1600_8g.zq0cr1 |= 0x10000;
				ddr3phy_1600_8g.zq1cr1 |= 0x10000;
				ddr3phy_1600_8g.zq2cr1 |= 0x10000;
				ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC,
						 &ddr3phy_1600_8g);
			} else {
				/* PG 1.1 */
				ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC,
						 &ddr3phy_1600_8g);
			}

			ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
					  &ddr3_1600_8g);
			printf("DRAM:  Capacity 8 GiB (includes reported below)\n");
			ddr3_size = 8;
		} else {
			ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_8g);
			ddr3_1600_8g.sdcfg |= 0x1000;
			ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
					  &ddr3_1600_8g);
			printf("DRAM:  Capacity 4 GiB (includes reported below)\n");
			ddr3_size = 4;
		}
	} else if (!strcmp(dimm_name, "SQR-SD3T-2G1333SED")) {
		init_pll(&ddr3a_333);
		if (cpu_revision() > 0) {
			if (cpu_revision() > 1) {
				/* PG 2.0 */
				/* Reset DDR3A PHY after PLL enabled */
				ddr3_reset_ddrphy();
				ddr3phy_1333_2g.zq0cr1 |= 0x10000;
				ddr3phy_1333_2g.zq1cr1 |= 0x10000;
				ddr3phy_1333_2g.zq2cr1 |= 0x10000;
				ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC,
						 &ddr3phy_1333_2g);
			} else {
				/* PG 1.1 */
				ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC,
						 &ddr3phy_1333_2g);
			}
			ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
					  &ddr3_1333_2g);
			ddr3_size = 2;
			printf("DRAM:  2 GiB");
		} else {
			ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1333_2g);
			ddr3_1333_2g.sdcfg |= 0x1000;
			ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
					  &ddr3_1333_2g);
			ddr3_size = 1;
			printf("DRAM:  1 GiB");
		}
	} else {
		printf("Unknown SO-DIMM. Cannot configure DDR3\n");
		while (1)
			;
	}

	/* Apply the workaround for PG 1.0 and 1.1 Silicons */
	if (cpu_revision() <= 1)
		ddr3_err_reset_workaround();
}