diff options
Diffstat (limited to 'src/northbridge/via/cn700/raminit.c')
-rw-r--r-- | src/northbridge/via/cn700/raminit.c | 473 |
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); -} |