aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/via/cn700/raminit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/via/cn700/raminit.c')
-rw-r--r--src/northbridge/via/cn700/raminit.c473
1 files changed, 0 insertions, 473 deletions
diff --git a/src/northbridge/via/cn700/raminit.c b/src/northbridge/via/cn700/raminit.c
deleted file mode 100644
index e8a7a17814..0000000000
--- a/src/northbridge/via/cn700/raminit.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008 VIA Technologies, Inc.
- * (Written by Aaron Lwe <aaron.lwe@gmail.com> for VIA)
- * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <stdint.h>
-#include <arch/io.h>
-#include <northbridge/via/cn700/raminit.h>
-#include <console/console.h>
-#include <spd.h>
-#include <delay.h>
-#include "cn700.h"
-
-#if IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)
-#define PRINT_DEBUG_MEM(x) printk(BIOS_DEBUG, x)
-#define PRINT_DEBUG_MEM_HEX8(x) printk(BIOS_DEBUG, "%02x", x)
-#define PRINT_DEBUG_MEM_HEX16(x) printk(BIOS_DEBUG, "%04x", x)
-#define PRINT_DEBUG_MEM_HEX32(x) printk(BIOS_DEBUG, "%08x", x)
-#define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0))
-#else
-#define PRINT_DEBUG_MEM(x)
-#define PRINT_DEBUG_MEM_HEX8(x)
-#define PRINT_DEBUG_MEM_HEX16(x)
-#define PRINT_DEBUG_MEM_HEX32(x)
-#define DUMPNORTH()
-#endif
-
-static void do_ram_command(pci_devfn_t dev, u8 command)
-{
- u8 reg;
-
- /* TODO: Support for multiple DIMMs. */
-
- reg = pci_read_config8(dev, DRAM_MISC_CTL);
- reg &= 0xf8; /* Clear bits 2-0. */
- reg |= command;
- pci_write_config8(dev, DRAM_MISC_CTL, reg);
-}
-
-static void c7_pci_write_config8(pci_devfn_t dev, u8 reg, u8 val)
-{
- udelay(200);
- pci_write_config8(dev, reg, val);
-}
-
-/**
- * Configure the bus between the CPU and the northbridge. This might be able to
- * be moved to post-ram code in the future. For the most part, these registers
- * should not be messed around with. These are too complex to explain short of
- * copying the datasheets into the comments, but most of these values are from
- * the BIOS Porting Guide, so they should work on any board. If they don't,
- * try the values from your factory BIOS.
- *
- * TODO: Changing the DRAM frequency doesn't work (hard lockup).
- *
- * @param dev The northbridge's CPU Host Interface (D0F2).
- */
-static void c7_cpu_setup(pci_devfn_t dev)
-{
- /* Host bus interface registers (D0F2 0x50-0x67) */
- /* Request phase control */
- c7_pci_write_config8(dev, 0x50, 0x88);
- /* CPU Interface Control */
- c7_pci_write_config8(dev, 0x51, 0x7a);
- c7_pci_write_config8(dev, 0x52, 0x6f);
- /* Arbitration */
- c7_pci_write_config8(dev, 0x53, 0x88);
- /* Miscellaneous Control */
- c7_pci_write_config8(dev, 0x54, 0x1e);
- c7_pci_write_config8(dev, 0x55, 0x16);
- /* Write Policy */
- c7_pci_write_config8(dev, 0x56, 0x01);
- /* Miscellaneous Control */
- /*
- * DRAM Operating Frequency (bits 7:5)
- * 000 : 100MHz 001 : 133MHz
- * 010 : 166MHz 011 : 200MHz
- * 100 : 266MHz 101 : 333MHz
- * 110/111 : Reserved
- */
- /* CPU Miscellaneous Control */
- c7_pci_write_config8(dev, 0x59, 0x44);
-
- /* Write Policy */
- c7_pci_write_config8(dev, 0x5d, 0xb2);
- /* Bandwidth Timer */
- c7_pci_write_config8(dev, 0x5e, 0x88);
- /* CPU Miscellaneous Control */
- c7_pci_write_config8(dev, 0x5f, 0xc7);
-
- /* Line DRDY# Timing Control */
- c7_pci_write_config8(dev, 0x60, 0xff);
- c7_pci_write_config8(dev, 0x61, 0xff);
- c7_pci_write_config8(dev, 0x62, 0x0f);
- /* QW DRDY# Timing Control */
- c7_pci_write_config8(dev, 0x63, 0xff);
- c7_pci_write_config8(dev, 0x64, 0xff);
- c7_pci_write_config8(dev, 0x65, 0x0f);
- /* Read Line Burst DRDY# Timing Control */
- c7_pci_write_config8(dev, 0x66, 0xff);
- c7_pci_write_config8(dev, 0x67, 0x30);
-
- /* Host Bus I/O Circuit (see datasheet) */
- /* Host Address Pullup/down Driving */
- c7_pci_write_config8(dev, 0x70, 0x11);
- c7_pci_write_config8(dev, 0x71, 0x11);
- c7_pci_write_config8(dev, 0x72, 0x11);
- c7_pci_write_config8(dev, 0x73, 0x11);
- /* Miscellaneous Control */
- c7_pci_write_config8(dev, 0x74, 0x35);
- /* AGTL+ I/O Circuit */
- c7_pci_write_config8(dev, 0x75, 0x28);
- /* AGTL+ Compensation Status */
- c7_pci_write_config8(dev, 0x76, 0x74);
- /* AGTL+ Auto Compensation Offest */
- c7_pci_write_config8(dev, 0x77, 0x00);
- /* Host FSB CKG Control */
- c7_pci_write_config8(dev, 0x78, 0x0a);
- /* Address/Address Clock Output Delay Control */
- c7_pci_write_config8(dev, 0x79, 0xaa);
- /* Address Strobe Input Delay Control */
- c7_pci_write_config8(dev, 0x7a, 0x24);
- /* Address CKG Rising/Falling Time Control */
- c7_pci_write_config8(dev, 0x7b, 0xaa);
- /* Address CKG Clock Rising/Falling Time Control */
- c7_pci_write_config8(dev, 0x7c, 0x00);
- /* Undefined (can't remember why I did this) */
- c7_pci_write_config8(dev, 0x7d, 0x6d);
- c7_pci_write_config8(dev, 0x7e, 0x00);
- c7_pci_write_config8(dev, 0x7f, 0x00);
- c7_pci_write_config8(dev, 0x80, 0x1b);
- c7_pci_write_config8(dev, 0x81, 0x0a);
- c7_pci_write_config8(dev, 0x82, 0x0a);
- c7_pci_write_config8(dev, 0x83, 0x0a);
-}
-
-/**
- * Set up DRAM size according to SPD data. Eventually, DRAM timings should be
- * done in a similar manner.
- *
- * @param ctrl The northbridge devices and SPD addresses.
- */
-static void sdram_set_size(const struct mem_controller *ctrl)
-{
- u8 density, ranks, result, col;
-
- ranks = spd_read_byte(ctrl->channel0[0], SPD_NUM_DIMM_BANKS);
- ranks = (ranks & 0x07) + 1;
- density = spd_read_byte(ctrl->channel0[0],
- SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
- switch (density) {
- case 0x80:
- result = 0x08; /* 512MB / 64MB = 0x08 */
- break;
- case 0x40:
- result = 0x04;
- break;
- case 0x20:
- result = 0x02;
- break;
- case 0x10:
- result = 0xff; /* 16GB */
- break;
- case 0x08:
- result = 0xff; /* 8GB */
- break;
- case 0x04:
- result = 0xff; /* 4GB */
- break;
- case 0x02:
- result = 0x20; /* 2GB */
- break;
- case 0x01:
- result = 0x10; /* 1GB */
- break;
- default:
- result = 0;
- }
-
- switch (result) {
- case 0xff:
- die("DRAM module size too big, not supported by CN700\n");
- break;
- case 0:
- die("DRAM module has unknown density\n");
- break;
- default:
- printk(BIOS_DEBUG, "Found %iMB of ram\n", result * ranks * 64);
- }
-
- pci_write_config8(ctrl->d0f3, 0x40, result);
- pci_write_config8(ctrl->d0f3, 0x48, 0x00);
- if (ranks == 2) {
- pci_write_config8(ctrl->d0f3, 0x41, result * ranks);
- pci_write_config8(ctrl->d0f3, 0x49, result);
- }
- /* Size mirror */
- pci_write_config8(ctrl->d0f7, 0xe5, (result * ranks) << 2);
- pci_write_config8(ctrl->d0f7, 0x57, (result * ranks) << 2);
- /* Low Top Address */
- pci_write_config8(ctrl->d0f3, 0x84, 0x00);
- pci_write_config8(ctrl->d0f3, 0x85, (result * ranks) << 2);
- pci_write_config8(ctrl->d0f3, 0x88, (result * ranks) << 2);
-
- /* Physical-Virtual Mapping */
- if (ranks == 2)
- pci_write_config8(ctrl->d0f3, 0x54,
- 1 << 7 | 0 << 4 | 1 << 3 | 1 << 0);
- if (ranks == 1)
- pci_write_config8(ctrl->d0f3, 0x54, 1 << 7 | 0 << 4);
- pci_write_config8(ctrl->d0f3, 0x55, 0x00);
- /* Virtual rank interleave, disable */
- pci_write_config32(ctrl->d0f3, 0x58, 0x00);
-
- /* MA Map Type */
- result = spd_read_byte(ctrl->channel0[0], SPD_NUM_BANKS_PER_SDRAM);
- if (result == 8) {
- col = spd_read_byte(ctrl->channel0[0], SPD_NUM_COLUMNS);
- switch (col) {
- case 10:
- pci_write_config8(ctrl->d0f3, 0x50, 0xa0);
- break;
- case 11:
- pci_write_config8(ctrl->d0f3, 0x50, 0xc0);
- break;
- case 12:
- pci_write_config8(ctrl->d0f3, 0x50, 0xe0);
- break;
- }
- } else if (result == 4) {
- col = spd_read_byte(ctrl->channel0[0], SPD_NUM_COLUMNS);
- switch (col) {
- case 9:
- pci_write_config8(ctrl->d0f3, 0x50, 0x00);
- break;
- case 10:
- pci_write_config8(ctrl->d0f3, 0x50, 0x20);
- break;
- case 11:
- pci_write_config8(ctrl->d0f3, 0x50, 0x40);
- break;
- case 12:
- pci_write_config8(ctrl->d0f3, 0x50, 0x60);
- break;
- }
- }
- pci_write_config8(ctrl->d0f3, 0x51, 0x00);
-}
-
-/**
- * Set up various RAM and other control registers statically. Some of these may
- * not be needed, other should be done with SPD info, but that's a project for
- * the future.
- */
-static void sdram_set_registers(const struct mem_controller *ctrl)
-{
- u8 reg;
-
- /* Set WR = 5 */
- pci_write_config8(ctrl->d0f3, 0x61, 0xe0);
- /* Set CAS = 4 */
- pci_write_config8(ctrl->d0f3, 0x62, 0xfa);
- /* DRAM timing-3 */
- pci_write_config8(ctrl->d0f3, 0x63, 0xca);
- /* DRAM timing-4 */
- pci_write_config8(ctrl->d0f3, 0x64, 0xcc);
- /* DIMM command / Address Selection */
- pci_write_config8(ctrl->d0f3, 0x67, 0x00);
- /* Disable cross bank/multi page mode */
- pci_write_config8(ctrl->d0f3, 0x69, 0x00);
- /* Disable refresh now */
- pci_write_config8(ctrl->d0f3, 0x6a, 0x00);
-
- /* Frequency 100 MHz */
- pci_write_config8(ctrl->d0f3, 0x90, 0x00);
- pci_write_config8(ctrl->d0f2, 0x57, 0x18);
- /* Allow manual DLL reset */
- pci_write_config8(ctrl->d0f3, 0x6b, 0x10);
-
- /* Bank/Rank Interleave Address Select */
- pci_write_config8(ctrl->d0f3, 0x52, 0x33);
- pci_write_config8(ctrl->d0f3, 0x53, 0x3f);
-
- /* Set to DDR2 SDRAM, BL = 8 (0xc8, 0xc0 for bl = 4) */
- pci_write_config8(ctrl->d0f3, 0x6c, 0xc8);
-
- /* DRAM Bus Turn-Around Setting */
- pci_write_config8(ctrl->d0f3, 0x60, 0x03);
- /* DRAM Arbitration Control */
- pci_write_config8(ctrl->d0f3, 0x66, 0x80);
- /*
- * DQS Tuning: testing on a couple different boards has shown this is
- * static, or close enough that it can be. Which is good, because the
- * tuning function used too many registers.
- */
- /* DQS Output Delay for Channel A */
- pci_write_config8(ctrl->d0f3, 0x70, 0x00);
- /* MD Output Delay for Channel A */
- pci_write_config8(ctrl->d0f3, 0x71, 0x01);
- pci_write_config8(ctrl->d0f3, 0x73, 0x01);
-
- /* DRAM arbitration timer */
- pci_write_config8(ctrl->d0f3, 0x65, 0xd9);
-
- /* DRAM signal timing control */
- pci_write_config8(ctrl->d0f3, 0x74, 0x01);
- pci_write_config8(ctrl->d0f3, 0x75, 0x01);
- pci_write_config8(ctrl->d0f3, 0x76, 0x06);
- pci_write_config8(ctrl->d0f3, 0x77, 0x92);
- pci_write_config8(ctrl->d0f3, 0x78, 0x83);
- pci_write_config8(ctrl->d0f3, 0x79, 0x83);
- pci_write_config8(ctrl->d0f3, 0x7a, 0x00);
- pci_write_config8(ctrl->d0f3, 0x7b, 0x10);
-
- /* DRAM clocking control */
- pci_write_config8(ctrl->d0f3, 0x91, 0x01);
- /* CS/CKE Clock Phase Control */
- pci_write_config8(ctrl->d0f3, 0x92, 0x02);
- /* SCMD/MA Clock Phase Control */
- pci_write_config8(ctrl->d0f3, 0x93, 0x02);
- /* DCLKO Feedback Mode Output Control */
- pci_write_config8(ctrl->d0f3, 0x94, 0x00);
- pci_write_config8(ctrl->d0f3, 0x9d, 0x0f);
-
- /* SDRAM ODT Control */
- pci_write_config8(ctrl->d0f3, 0xda, 0x80);
- /* Channel A DQ/DQS CKG Output Delay Control */
- pci_write_config8(ctrl->d0f3, 0xdc, 0x54);
- /* Channel A DQ/DQS CKG Output Delay Control */
- pci_write_config8(ctrl->d0f3, 0xdd, 0x55);
- /* ODT lookup table */
- pci_write_config8(ctrl->d0f3, 0xd8, 0x01);
- pci_write_config8(ctrl->d0f3, 0xd9, 0x0a);
-
- /* DDR SDRAM control */
- pci_write_config8(ctrl->d0f3, 0x6d, 0xc0);
- pci_write_config8(ctrl->d0f3, 0x6f, 0x41);
-
- /* DQ/DQS Strength Control */
- pci_write_config8(ctrl->d0f3, 0xd0, 0xaa);
-
- /* Compensation Control */
- pci_write_config8(ctrl->d0f3, 0xd3, 0x01); /* Enable autocompensation */
- /* ODT (some are set with driving select above) */
- pci_write_config8(ctrl->d0f3, 0xd4, 0x80);
- pci_write_config8(ctrl->d0f3, 0xd5, 0x8a);
- /* Memory Pads Driving and Range Select */
- pci_write_config8(ctrl->d0f3, 0xd6, 0xaa);
-
- pci_write_config8(ctrl->d0f3, 0xe0, 0xee);
- pci_write_config8(ctrl->d0f3, 0xe2, 0xac);
- pci_write_config8(ctrl->d0f3, 0xe4, 0x66);
- pci_write_config8(ctrl->d0f3, 0xe6, 0x33);
- pci_write_config8(ctrl->d0f3, 0xe8, 0x86);
- /* DQS / DQ CKG Duty Cycle Control */
- pci_write_config8(ctrl->d0f3, 0xec, 0x00);
- /* MCLK Output Duty Control */
- pci_write_config8(ctrl->d0f3, 0xee, 0x00);
- /* DQS CKG Input Delay Control */
- pci_write_config8(ctrl->d0f3, 0xef, 0x10);
-
- /* DRAM duty control */
- pci_write_config8(ctrl->d0f3, 0xed, 0x10);
-
- /* SMM and APIC decoding, we do not use SMM */
- reg = 0x29;
- pci_write_config8(ctrl->d0f3, 0x86, reg);
- /* SMM and APIC decoding mirror */
- pci_write_config8(ctrl->d0f7, 0xe6, reg);
-
- /* DRAM module configuration */
- pci_write_config8(ctrl->d0f3, 0x6e, 0x89);
-}
-
-static void sdram_set_post(const struct mem_controller *ctrl)
-{
- pci_devfn_t dev = ctrl->d0f3;
-
- /* Enable multipage mode. */
- pci_write_config8(dev, 0x69, 0x03);
-
- /* Enable refresh. */
- pci_write_config8(dev, 0x6a, 0x32);
-
- /* VGA device. */
- pci_write_config16(dev, 0xa0, (1 << 15));
- pci_write_config16(dev, 0xa4, 0x0010);
-}
-
-static void sdram_enable(pci_devfn_t dev, u8 *rank_address)
-{
- u8 i;
-
- /* 1. Apply NOP. */
- PRINT_DEBUG_MEM("RAM Enable 1: Apply NOP\n");
- do_ram_command(dev, RAM_COMMAND_NOP);
- udelay(100);
- read32(rank_address + 0x10);
-
- /* 2. Precharge all. */
- udelay(400);
- PRINT_DEBUG_MEM("RAM Enable 2: Precharge all\n");
- do_ram_command(dev, RAM_COMMAND_PRECHARGE);
- read32(rank_address + 0x10);
-
- /* 3. Mode register set. */
- PRINT_DEBUG_MEM("RAM Enable 3: Mode register set\n");
- do_ram_command(dev, RAM_COMMAND_MRS);
- read32(rank_address + 0x120000); /* EMRS DLL Enable */
- read32(rank_address + 0x800); /* MRS DLL Reset */
-
- /* 4. Precharge all again. */
- PRINT_DEBUG_MEM("RAM Enable 4: Precharge all\n");
- do_ram_command(dev, RAM_COMMAND_PRECHARGE);
- read32(rank_address + 0x0);
-
- /* 5. Perform 8 refresh cycles. Wait tRC each time. */
- PRINT_DEBUG_MEM("RAM Enable 5: CBR\n");
- do_ram_command(dev, RAM_COMMAND_CBR);
- for (i = 0; i < 8; i++) {
- read32(rank_address + 0x20);
- udelay(100);
- }
-
- /* 6. Mode register set. */
- PRINT_DEBUG_MEM("RAM Enable 6: Mode register set\n");
- /* Safe value for now, BL = 8, WR = 5, CAS = 4 */
- /*
- * (E)MRS values are from the BPG. No direct explanation is given, but
- * they should somehow conform to the JEDEC DDR2 SDRAM Specification
- * (JESD79-2C).
- */
- do_ram_command(dev, RAM_COMMAND_MRS);
- read32(rank_address + 0x002258); /* MRS command */
- read32(rank_address + 0x121c20); /* EMRS OCD Default */
- read32(rank_address + 0x120020); /* EMRS OCD Calibration Mode Exit */
-
- /* 8. Normal operation */
- PRINT_DEBUG_MEM("RAM Enable 7: Normal operation\n");
- do_ram_command(dev, RAM_COMMAND_NORMAL);
- read32(rank_address + 0x30);
-}
-
-/*
- * Support one DIMM with up to 2 ranks.
- */
-void ddr_ram_setup(const struct mem_controller *ctrl)
-{
- u8 reg;
-
- c7_cpu_setup(ctrl->d0f2);
- sdram_set_registers(ctrl);
- sdram_set_size(ctrl);
- sdram_enable(ctrl->d0f3, (u8 *)0);
- reg = pci_read_config8(ctrl->d0f3, 0x41);
- if (reg != 0)
- sdram_enable(ctrl->d0f3,
- (u8 *)(pci_read_config8(ctrl->d0f3, 0x40) << 26));
- sdram_set_post(ctrl);
-}