Example #1
0
static void ram_read32(u8 dimm_start, u32 offset)
{
	u32 reg32, base_addr = 32 * 1024 * 1024 * dimm_start;
	if (offset == 0x55aa55aa) {
		reg32 = read32(base_addr);
		PRINTK_DEBUG("  Reading RAM at 0x%08x => 0x%08x\n", base_addr, reg32);
		PRINTK_DEBUG("  Writing RAM at 0x%08x <= 0x%08x\n", base_addr, offset);
		write32(base_addr, offset);
		reg32 = read32(base_addr);
		PRINTK_DEBUG("  Reading RAM at 0x%08x => 0x%08x\n", base_addr, reg32);
	} else {
		PRINTK_DEBUG(" to 0x%08x\n", base_addr + offset);
		read32(base_addr + offset);
	}
}
Example #2
0
static void die_on_spd_error(int spd_return_value)
{
	if (spd_return_value < 0)
		PRINTK_DEBUG("Error reading SPD info: got %d\n", spd_return_value);
/*
	if (spd_return_value < 0)
		die("Error reading SPD info\n");
*/
}
Example #3
0
static void do_ram_command(u32 command)
{
	u32 reg32;

	/* Configure the RAM command. */
	reg32 = pci_read_config32(NORTHBRIDGE, DRC);
	/* Clear bits 29, 10-8, 6-4. */
	reg32 &= 0xdffff88f;
	reg32 |= command << 4;
	PRINTK_DEBUG("  Sending RAM command 0x%08x", reg32);
	pci_write_config32(NORTHBRIDGE, DRC, reg32);
}
Example #4
0
/**
 * Calculate the page size for each physical bank of the DIMM:
 *
 *   log2(page size) = (# columns) + log2(data width)
 *
 * NOTE: Page size is the total number of data bits in a row.
 *
 * @param dimm_socket_address SMBus address of DIMM socket to interrogate.
 * @return log2(page size) for each side of the DIMM.
 */
static struct dimm_size sdram_spd_get_page_size(u8 dimm_socket_address)
{
	uint16_t module_data_width;
	int value;
	struct dimm_size pgsz;

	pgsz.side1 = 0;
	pgsz.side2 = 0;

	// Side 1
	value = spd_read_byte(dimm_socket_address, SPD_NUM_COLUMNS);
	die_on_spd_error(value);

	pgsz.side1 = value & 0xf;	// # columns in bank 1

	/* Get the module data width and convert it to a power of two */
	value = spd_read_byte(dimm_socket_address, SPD_MODULE_DATA_WIDTH_MSB);
	die_on_spd_error(value);

	module_data_width = (value & 0xff) << 8;

	value = spd_read_byte(dimm_socket_address, SPD_MODULE_DATA_WIDTH_LSB);
	die_on_spd_error(value);

	module_data_width |= (value & 0xff);

	pgsz.side1 += log2(module_data_width);

	/* side two */
	value = spd_read_byte(dimm_socket_address, SPD_NUM_DIMM_BANKS);
	die_on_spd_error(value);

/*
	if (value > 2)
		die("Bad SPD value\n");
*/
	if (value > 2)
		PRINTK_DEBUG("Bad SPD value\n");

	if (value == 2) {
		pgsz.side2 = pgsz.side1;	// Assume symmetric banks until we know differently
		value = spd_read_byte(dimm_socket_address, SPD_NUM_COLUMNS);
		die_on_spd_error(value);

		if ((value & 0xf0) != 0) {
			// Asymmetric banks
			pgsz.side2 -= value & 0xf;	/* Subtract out columns on side 1 */
			pgsz.side2 += (value >> 4) & 0xf;	/* Add in columns on side 2 */
		}
Example #5
0
static void initialize_dimm_rows(void)
{
	int i, row;
	u8 dimm_start, dimm_end;
	unsigned device;

	dimm_start = 0;

	for (row = 0; row < (DIMM_SOCKETS * 2); row++) {

		switch (row) {
			case 0:
				device = DIMM0;
				break;
			case 1:
				device = DIMM0;
				break;
			case 2:
				device = DIMM0 + 1;
				break;
			case 3:
				device = DIMM0 + 1;
				break;
		}

		dimm_end = pci_read_config8(NORTHBRIDGE, DRB + row);

		if (dimm_end > dimm_start) {
			printk(BIOS_DEBUG, "Initializing SDRAM Row %u\n", row);

			/* NOP command */
			PRINTK_DEBUG(" NOP\n");
			do_ram_command(RAM_COMMAND_NOP);
			ram_read32(dimm_start, 0);
			udelay(200);

			/* Pre-charge all banks (at least 200 us after NOP) */
			PRINTK_DEBUG(" Pre-charging all banks\n");
			do_ram_command(RAM_COMMAND_PRECHARGE);
			ram_read32(dimm_start, 0);
			udelay(1);

			/* 8 CBR refreshes (Auto Refresh) */
			PRINTK_DEBUG(" 8 CBR refreshes\n");
			for (i = 0; i < 8; i++) {
				do_ram_command(RAM_COMMAND_CBR);
				ram_read32(dimm_start, 0);
				udelay(1);
			}

			/* MRS command */
			/* TODO: Set offset 0x1d0 according to DRT values */
			PRINTK_DEBUG(" MRS\n");
			do_ram_command(RAM_COMMAND_MRS);
			ram_read32(dimm_start, 0x1d0);
			udelay(2);

			/* Set GMCH-M Mode Select bits back to NORMAL operation mode */
			PRINTK_DEBUG(" Normal operation mode\n");
			do_ram_command(RAM_COMMAND_NORMAL);
			ram_read32(dimm_start, 0);
			udelay(1);

			/* Perform a dummy memory read/write cycle */
			PRINTK_DEBUG(" Performing dummy read/write\n");
			ram_read32(dimm_start, 0x55aa55aa);
			udelay(1);
		}
		/* Set the start of the next DIMM. */
		dimm_start = dimm_end;
	}
}