summaryrefslogtreecommitdiff
path: root/src/northbridge
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge')
-rw-r--r--src/northbridge/via/vt8623/northbridge.c91
-rw-r--r--src/northbridge/via/vt8623/raminit.c790
2 files changed, 609 insertions, 272 deletions
diff --git a/src/northbridge/via/vt8623/northbridge.c b/src/northbridge/via/vt8623/northbridge.c
index bfaaeac30f..7143c358da 100644
--- a/src/northbridge/via/vt8623/northbridge.c
+++ b/src/northbridge/via/vt8623/northbridge.c
@@ -10,6 +10,7 @@
#include <bitops.h>
#include <cpu/cpu.h>
#include <cpu/x86/mtrr.h>
+#include <cpu/x86/msr.h>
#include "chip.h"
#include "northbridge.h"
@@ -19,6 +20,18 @@
* slower than normal, ethernet drops packets).
* Apparently these registers govern some sort of bus master behavior.
*/
+static void dump_dev(device_t dev)
+{
+ int i,j;
+
+ for(i = 0; i < 256; i += 16) {
+ printk_debug("0x%x: ", i);
+ for(j = 0; j < 16; j++) {
+ printk_debug("%02x ", pci_read_config8(dev, i+j));
+ }
+ printk_debug("\n");
+ }
+}
static void northbridge_init(device_t dev)
{
device_t fb_dev;
@@ -44,21 +57,25 @@ static void northbridge_init(device_t dev)
/* Fixup GART and framebuffer addresses properly.
* First setup frame buffer properly.
*/
- fb = pci_read_config32(dev, 0x10); /* Base addres of framebuffer */
+ //fb = pci_read_config32(dev, 0x10); /* Base addres of framebuffer */
+ fb = 0xd0000000;
printk_debug("Frame buffer at %8x\n",fb);
c = pci_read_config8(dev, 0xe1) & 0xf0; /* size of vga */
c |= fb>>28; /* upper nibble of frame buffer address */
+ c = 0xdd;
pci_write_config8(dev, 0xe1, c);
- c = (fb>>20) | 1; /* enable framebuffer */
+ c = 0x81; /* enable framebuffer */
pci_write_config8(dev, 0xe0, c);
pci_write_config8(dev, 0xe2, 0x42); /* 'cos award does */
}
+ //dump_dev(dev);
}
+static void nullfunc(){}
static struct device_operations northbridge_operations = {
- .read_resources = pci_dev_read_resources,
+ .read_resources = nullfunc,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = northbridge_init
@@ -80,10 +97,11 @@ static void agp_init(device_t dev)
pci_write_config8(dev, 0x43, 0x44);
pci_write_config8(dev, 0x44, 0x34);
pci_write_config8(dev, 0x83, 0x02);
+ //dump_dev(dev);
}
static struct device_operations agp_operations = {
- .read_resources = pci_bus_read_resources,
+ .read_resources = nullfunc,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.init = agp_init,
@@ -100,12 +118,64 @@ static struct pci_driver agp_driver __pci_driver = {
static void vga_init(device_t dev)
{
// unsigned long fb;
+ msr_t clocks1,clocks2,instructions,setup;
printk_debug("VGA random fixup ...\n");
pci_write_config8(dev, 0x04, 0x07);
pci_write_config8(dev, 0x0d, 0x20);
+ pci_write_config32(dev,0x10,0xd8000008);
+ pci_write_config32(dev,0x14,0xdc000000);
+
+ //dump_dev(dev);
+
+ // set up performnce counters for debugging vga init sequence
+ //setup.lo = 0x1c0; // count instructions
+ //wrmsr(0x187,setup);
+ //instructions.hi = 0;
+ //instructions.lo = 0;
+ //wrmsr(0xc2,instructions);
+ //clocks1 = rdmsr(0x10);
+
+
+#if 0
+ /* code to make vga init go through the emulator - as of yet this does not workfor the epia-m */
+ dev->on_mainboard=1;
+ dev->rom_address = (void *)0xfffc0000;
+
+ pci_dev_init(dev);
+
+ call_bios_interrupt(0x10,0x4f1f,0x8003,1,0);
+
+ //clocks2 = rdmsr(0x10);
+ //instructions = rdmsr(0xc2);
+
+ printk_debug("Clocks 1 = %08x:%08x\n",clocks1.hi,clocks1.lo);
+ printk_debug("Clocks 2 = %08x:%08x\n",clocks2.hi,clocks2.lo);
+ printk_debug("Instructions = %08x:%08x\n",instructions.hi,instructions.lo);
+
+#else
+
+ /* code to make vga init run in real mode - does work but against the current Linuxbios philosophy */
+ printk_debug("INSTALL REAL-MODE IDT\n");
+ setup_realmode_idt();
+ printk_debug("DO THE VGA BIOS\n");
+ do_vgabios();
+
+ //clocks2 = rdmsr(0x10);
+ //instructions = rdmsr(0xc2);
- /* Set the vga mtrrs - disable for the moment */
+ //printk_debug("Clocks 1 = %08x:%08x\n",clocks1.hi,clocks1.lo);
+ //printk_debug("Clocks 2 = %08x:%08x\n",clocks2.hi,clocks2.lo);
+ //printk_debug("Instructions = %08x:%08x\n",instructions.hi,instructions.lo);
+
+ vga_enable_console();
+
+#endif
+
+
+ pci_write_config32(dev,0x30,0);
+
+ /* Set the vga mtrrs - disable for the moment as the add_var_mtrr function has vapourised */
#if 0
add_var_mtrr( 0xd0000000 >> 10, 0x08000000>>10, MTRR_TYPE_WRCOMB);
fb = pci_read_config32(dev,0x10); // get the fb address
@@ -113,8 +183,17 @@ static void vga_init(device_t dev)
#endif
}
+static void vga_read_resources(device_t dev)
+{
+
+ dev->rom_address = (void *)0xfffc0000;
+ dev->on_mainboard=1;
+ pci_dev_read_resources(dev);
+
+}
+
static struct device_operations vga_operations = {
- .read_resources = pci_dev_read_resources,
+ .read_resources = vga_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = vga_init,
diff --git a/src/northbridge/via/vt8623/raminit.c b/src/northbridge/via/vt8623/raminit.c
index 7371e09e57..750193231a 100644
--- a/src/northbridge/via/vt8623/raminit.c
+++ b/src/northbridge/via/vt8623/raminit.c
@@ -1,91 +1,50 @@
-#include <cpu/x86/mtrr.h>
-#include "raminit.h"
-
-/*
-This software and ancillary information (herein called SOFTWARE )
-called LinuxBIOS is made available under the terms described
-here. The SOFTWARE has been approved for release with associated
-LA-CC Number 00-34 . Unless otherwise indicated, this SOFTWARE has
-been authored by an employee or employees of the University of
-California, operator of the Los Alamos National Laboratory under
-Contract No. W-7405-ENG-36 with the U.S. Department of Energy. The
-U.S. Government has rights to use, reproduce, and distribute this
-SOFTWARE. The public may copy, distribute, prepare derivative works
-and publicly display this SOFTWARE without charge, provided that this
-Notice and any statement of authorship are reproduced on all copies.
-Neither the Government nor the University makes any warranty, express
-or implied, or assumes any liability or responsibility for the use of
-this SOFTWARE. If SOFTWARE is modified to produce derivative works,
-such modified SOFTWARE should be clearly marked, so as not to confuse
-it with the version available from LANL.
- */
-/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
- * rminnich@lanl.gov
- */
/*
- * 11/26/02 - kevinh@ispiri.com - The existing comments implied that
- * this didn't work yet. Therefore, I've updated it so that it works
- * correctly - at least on my VIA epia motherboard. 64MB DIMM in slot 0.
- */
-
-/* Added automatic detection of first equipped bank and its MA mapping type.
- * (Rest of configuration is done in C)
- * 5/19/03 by SONE Takeshi <ts1@tsn.or.jp>
+ * (C) Copyright 2005 Nick Barker <nick.barker9@btinternet.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
*/
-/* converted to C 9/2003 Ron Minnich */
-
-/* Set to 1 if your DIMMs are PC133 Note that I'm assuming CPU's FSB
- * frequency is 133MHz. If your CPU runs at another bus speed, you
- * might need to change some of register values.
- */
-#ifndef DIMM_PC133
-#define DIMM_PC133 0
-#endif
-
-// Set to 1 if your DIMMs are CL=2
-#ifndef DIMM_CL2
-#define DIMM_CL2 0
-#endif
+/*
+ Automatically detect and set up ddr dram on the CLE266 chipset.
+ Assumes DDR memory, though chipset also supports SDRAM
+ Assumes at least 266Mhz memory as no attempt is made to clock
+ the chipset down if slower memory is installed.
+ So far tested on:
+ 256 Mb 266Mhz 1 Bank (i.e. single sided)
+ 256 Mb 266Mhz 2 Bank (i.e. double sided)
+ 512 Mb 266Mhz 2 Bank (i.e. double sided)
+*/
+/* ported and enhanced from assembler level code in Linuxbios v1 */
+#include <cpu/x86/mtrr.h>
+#include "raminit.h"
-void dimm_read(unsigned long x)
+void dimm_read(unsigned long bank,unsigned long x)
{
- unsigned long eax;
+ //unsigned long eax;
volatile unsigned long y;
- eax = x;
- y = * (volatile unsigned long *) eax;
-
-}
+ //eax = x;
+ y = * (volatile unsigned long *) (x+ bank) ;
-void dimms_write(int x)
-{
- uint8_t c;
- unsigned long eax = x;
- for(c = 0; c < 6; c++) {
- *(volatile unsigned long *) eax = 0;
- eax += 0x10000000;
- }
}
-
-#ifdef DEBUG_SETNORTHB
-void setnorthb(device_t north, uint8_t reg, uint8_t val)
-{
- print_debug("setnorth: reg ");
- print_debug_hex8(reg);
- print_debug(" to ");
- print_debug_hex8(val);
- print_debug("\r\n");
- pci_write_config8(north, reg, val);
-}
-#else
-#define setnorthb pci_write_config8
-#endif
-
void
dumpnorth(device_t north)
{
@@ -100,246 +59,527 @@ dumpnorth(device_t north)
print_debug("\r\n");
}
}
+void print_val(char *str, int val)
+{
+ print_debug(str);
+ print_debug_hex8(val);
+}
-static void sdram_set_registers(const struct mem_controller *ctrl)
+static void ddr_ram_setup(const struct mem_controller *ctrl)
{
device_t north = (device_t) 0;
- uint8_t c, r;
+ uint8_t b, c, bank;
+ uint16_t i,j;
+ unsigned long bank_address;
print_err("vt8623 init starting\r\n");
north = pci_locate_device(PCI_ID(0x1106, 0x3123), 0);
north = 0;
- print_debug_hex32(north);
- print_debug(" is the north\r\n");
- print_debug_hex16(pci_read_config16(north, 0));
- print_debug(" ");
- print_debug_hex16(pci_read_config16(north, 2));
- print_debug("\r\n");
- /* All we are doing now is setting initial known-good values that will
- * be revised later as we read SPD
- */
pci_write_config8(north,0x75,0x08);
- /* since we only support epia-m at the moment, only ddr is supported */
/* setup cpu */
pci_write_config8(north,0x50,0xc8);
pci_write_config8(north,0x51,0xde);
pci_write_config8(north,0x52,0xcf);
pci_write_config8(north,0x53,0x88);
- pci_write_config8(north,0x55,0x07);
+ pci_write_config8(north,0x55,0x04);
- /* DRAM MA Map Type */
- pci_write_config8(north,0x58,0xe0);
+/*
+ DRAM MA Map Type Device 0 Offset 58
- /* DRAM bank 0 - 3 size = 512M */
- pci_write_config8(north,0x5a,0x10);
- pci_write_config8(north,0x5b,0x10);
- pci_write_config8(north,0x5c,0x10);
- pci_write_config8(north,0x5d,0x10);
+ Determine memory addressing based on the module's memory technology and
+ arrangement. See Table 4-9 of Intel's 82443GX datasheet for details.
- /* set DRAM timing for all banks */
- pci_write_config8(north,0x64,0xe6);
+ Bank 1/0 MA map type 58[7-5]
+ Bank 1/0 command rate 58[4]
+ Bank 3/2 MA map type 58[3-1]
+ Bank 3/2 command rate 58[0]
- /* set DRAM type to DDR */
- pci_write_config8(north,0x60,0x02);
+ Read SPD byte 17, Number of banks on SDRAM device.
+*/
+ c = 0;
+ b = smbus_read_byte(0xa0,17);
+ print_val("Detecting Memory\r\nNumber of Banks ",b);
- /* DRAM arbitration timer */
- pci_write_config8(north,0x65,0x32);
- pci_write_config8(north,0x66,0x01);
- pci_write_config8(north,0x68,0x59);
+ if( b != 2 ){ // not 16 Mb type
+
+/*
+ Read SPD byte 3, Number of row addresses.
+*/
+ b = smbus_read_byte(0xa0,3);
+ print_val("\r\nNumber of Rows ",b);
+ if( b >= 0x0d ){ // not 64/128Mb (rows <=12)
+/*
+ Read SPD byte 13, Primary DRAM width.
+*/
+ b = smbus_read_byte(0xa0,13);
+ print_val("\r\nPriamry DRAM width",b);
+ if( b != 4 ) // mot 64/128Mb (x4)
+ c = 0x80; // 256Mb
+ }
- /* DRAM Frequency */
- pci_write_config8(north,0x54,0xe0);
- pci_write_config8(north,0x69,0x2d);
+/*
+ 64/128Mb chip
- /* Enable CKE */
- pci_write_config8(north,0x6b,0x10);
+ Read SPD byte 4, Number of column addresses.
+*/
+ b = smbus_read_byte(0xa0,4);
+ print_val("\r\nNo Columns ",b);
+ if( b == 10 || b == 11 ) c |= 0x60; // 10/11 bit col addr
+ if( b == 9 ) c |= 0x40; // 9 bit col addr
+ if( b == 8 ) c |= 0x20; // 8 bit col addr
+
+ }
+ print_val("\r\nMA type ",c);
+ pci_write_config8(north,0x58,c);
+
+/*
+ DRAM bank size. See 4.3.1 pg 35
+
+ 5a->5d set to end address for each bank. 1 bit == 16MB
+ 5a = bank 0
+ 5b = bank 0 + b1
+ 5c = bank 0 + b1 + b2
+ 5d = bank 0 + b1 + b2 + b3
+*/
+
+// Read SPD byte 31 Module bank density
+ c = 0;
+ b = smbus_read_byte(0xa0,31);
+ if( b & 0x02 ) c = 0x80; // 2GB
+ else if( b & 0x01) c = 0x40; // 1GB
+ else if( b & 0x80) c = 0x20; // 512Mb
+ else if( b & 0x40) c = 0x10; // 256Mb
+ else if( b & 0x20) c = 0x08; // 128Mb
+ else if( b & 0x10) c = 0x04; // 64Mb
+ else if( b & 0x08) c = 0x02; // 32Mb
+ else if( b & 0x04) c = 0x01; // 16Mb / 4Gb
+ else c = 0x01; // Error, use default
+
+
+ print_val("\r\nBank 0 (*16 Mb) ",c);
+
+ // set bank zero size
+ pci_write_config8(north,0x5a,c);
+ // SPD byte 5 # of physical banks
+ b = smbus_read_byte(0xa0,5);
+
+ print_val("\r\nNo Physical Banks ",b);
+ if( b == 2)
+ c <<=1;
+
+ print_val("\r\nTotal Memory (*16 Mb) ",c);
+ // set banks 1,2,3
+ pci_write_config8(north,0x5b,c);
+ pci_write_config8(north,0x5c,c);
+ pci_write_config8(north,0x5d,c);
+
+
+ /* Read SPD byte 18 CAS Latency */
+ b = smbus_read_byte(0xa0,18);
+ print_debug("\r\nCAS Supported ");
+ if(b & 0x04)
+ print_debug("2 ");
+ if(b & 0x08)
+ print_debug("2.5 ");
+ if(b & 0x10)
+ print_debug("3");
+ print_val("\r\nCycle time at CL X (nS)",smbus_read_byte(0xa0,9));
+ print_val("\r\nCycle time at CL X-0.5 (nS)",smbus_read_byte(0xa0,23));
+ print_val("\r\nCycle time at CL X-1 (nS)",smbus_read_byte(0xa0,25));
- /* Disable DRAM refresh */
- pci_write_config8(north,0x6a,0x0);
- /* set heavy drive */
- pci_write_config8(north,0x6d,0x44);
+ if( b & 0x10 ){ // DDR offering optional CAS 3
+ print_debug("\r\nStarting at CAS 3");
+ c = 0x30;
+ /* see if we can better it */
+ if( b & 0x08 ){ // DDR mandatory CAS 2.5
+ if( smbus_read_byte(0xa0,23) <= 0x75 ){ // we can manage 133Mhz at CAS 2.5
+ print_debug("\r\nWe can do CAS 2.5");
+ c = 0x20;
+ }
+ }
+ if( b & 0x04 ){ // DDR mandatory CAS 2
+ if( smbus_read_byte(0xa0,25) <= 0x75 ){ // we can manage 133Mhz at CAS 2
+ print_debug("\r\nWe can do CAS 2");
+ c = 0x10;
+ }
+ }
+ }else{ // no optional CAS values just 2 & 2.5
+ print_debug("\r\nStarting at CAS 2.5");
+ c = 0x20; // assume CAS 2.5
+ if( b & 0x04){ // Should always happen
+ if( smbus_read_byte(0xa0,23) <= 0x75){ // we can manage 133Mhz at CAS 2
+ print_debug("\r\nWe can do CAS 2");
+ c = 0x10;
+ }
+ }
+ }
- pci_write_config8(north,0x61,0xff);
+/*
+ DRAM Timing Device 0 Offset 64
+ Row pre-charge 64[7]
+ RAS Pulse width 64[6]
+ CAS Latency 64[5,4]
-}
+ SDR DDR
+ 00 1T -
+ 01 2T 2T
+ 10 3T 2.5T
+ 11 - 3T
-/* slot is the dram slot. Return size of side0 in lower 16-bit,
- * side1 in upper 16-bit, in units of 8MB */
-static unsigned long
-spd_module_size(unsigned char slot)
-{
- /* for all the DRAMS, see if they are there and get the size of each
- * module. This is just a very early first cut at sizing.
- */
- /* we may run out of registers ... */
- unsigned int banks, rows, cols, reg;
- unsigned int value = 0;
- unsigned int module = ((0x50 + slot) << 1) + 1;
- /* is the module there? if byte 2 is not 4, then we'll assume it
- * is useless.
- */
- print_info("Slot ");
- print_info_hex8(slot);
- if (smbus_read_byte(module, 2) != 4) {
- print_info(" is empty\r\n");
- return 0;
- }
- print_info(" is SDRAM ");
-
- banks = smbus_read_byte(module, 17);
- /* we're going to assume symmetric banks. Sorry. */
- cols = smbus_read_byte(module, 4) & 0xf;
- rows = smbus_read_byte(module, 3) & 0xf;
- /* grand total. You have rows+cols addressing, * times of banks, times
- * width of data in bytes */
- /* Width is assumed to be 64 bits == 8 bytes */
- value = (1 << (cols + rows)) * banks * 8;
- print_info_hex32(value);
- print_info(" bytes ");
- /* Return in 8MB units */
- value >>= 23;
-
- /* We should have single or double side */
- if (smbus_read_byte(module, 5) == 2) {
- print_info("x2");
- value = (value << 16) | value;
- }
- print_info("\r\n");
- return value;
+ RAS/CAS delay 64[2]
+ Bank Interleave 64[1,0]
-}
-static int
-spd_num_chips(unsigned char slot)
-{
- unsigned int module = ((0x50 + slot) << 1) + 1;
- unsigned int width;
+ Determine row pre-charge time (tRP)
- width = smbus_read_byte(module, 13);
- if (width == 0)
- width = 8;
- return 64 / width;
-}
+ T nS SPD*4 SPD
+ 1T 7.5 0x1e
+ 2T 15 0x3c
+ 3T 22.5 0x5a
+ 4T 30 0x1e
+ 5T 37.5 0x25 .5?
+ 6T 45 0x2d
-static void sdram_set_spd_registers(const struct mem_controller *ctrl)
-{
-#define T133 7
- unsigned char Trp = 1, Tras = 1, casl = 2, val;
- unsigned char timing = 0xe4;
- /* read Trp */
- val = smbus_read_byte(0xa0, 27);
- if (val < 2*T133)
- Trp = 1;
- val = smbus_read_byte(0xa0, 30);
- if (val < 5*T133)
- Tras = 0;
- val = smbus_read_byte(0xa0, 18);
- if (val < 8)
- casl = 1;
- if (val < 4)
- casl = 0;
-
- val = (Trp << 7) | (Tras << 6) | (casl << 4) | 4;
-
- print_debug_hex8(val); print_debug(" is the computed timing\r\n");
- /* don't set it. Experience shows that this screwy chipset should just
- * be run with the most conservative timing.
- * pci_write_config8(0, 0x64, val);
- */
-}
-static void set_ma_mapping(device_t north, int slot, int type)
-{
- unsigned char reg, val;
- int shift;
-
- reg = 0x58 + slot/2;
- if (slot%2 >= 1)
- shift = 0;
- else
- shift = 4;
-
- val = pci_read_config8(north, reg);
- val &= ~(0xf << shift);
- val |= type << shift;
- pci_write_config8(north, reg, val);
-}
+ Read SPD byte 27, min row pre-charge time.
+*/
+ b = smbus_read_byte(0xa0,27);
+ print_val("\r\ntRP ",b);
+ if( b > 0x3c ) // set tRP = 3T
+ c |= 0x80;
-static void sdram_enable(int controllers, const struct mem_controller *ctrl)
-{
- unsigned char i;
- static const uint8_t ramregs[] = {
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x56, 0x57
- };
- device_t north = 0;
- uint32_t size, base, slot, ma;
-
- /* NOP command enable */
- pci_write_config8(north,0x6b,0x01);
+/*
+ Determine RAS to CAS delay (tRCD)
+
+ Read SPD byte 29, min row pre-charge time.
+*/
+
+ b = smbus_read_byte(0xa0,29);
+ print_val("\r\ntRCD ",b);
+ if( b > 0x3c ) // set tRCD = 3T
+ c |= 0x04;
+
+/*
+ Determine RAS pulse width (tRAS)
+
+
+ Read SPD byte 30, device min active to pre-charge time.
+*/
+
+ b = smbus_read_byte(0xa0,30);
+ print_val("\r\ntRAS ",b);
+ if( b > 0x25 ) // set tRAS = 6T
+ c |= 0x40;
+
+
+/*
+ Determine bank interleave
+
+ Read SPD byte 17, Number of banks on SDRAM device.
+*/
+ b = smbus_read_byte(0xa0,17);
+ if( b == 4) c |= 0x02;
+ else if (b == 2) c |= 0x01;
+
+
+ /* set DRAM timing for all banks */
+ pci_write_config8(north,0x64,c);
+
+ /* set DRAM type to DDR */
+ pci_write_config8(north,0x60,0x02);
+
+
+ /* DRAM arbitration timer */
+ pci_write_config8(north,0x65,0x32);
+
+
+/*
+ CPU Frequency Device 0 Offset 54
+
+ CPU Frequency 54[7,6] bootstraps at 0xc0 (133Mhz)
+ DRAM burst length = 8 54[5]
+*/
+ pci_write_config8(north,0x54,0xe0);
+
- /* read a double word from any addree of the dimm */
- dimm_read(0x1f000);
+/*
+ DRAM Clock Device 0 Offset 69
+
+ DRAM/CPU speed 69[7,6] (leave at default 00 == CPU)
+ Controller que > 2 69[5]
+ Controller que != 4 69[4]
+ DRAM 8k page size 69[3]
+ DRAM 4k page size 69[2]
+ Multiple page mode 69[0]
+*/
+
+ pci_write_config8(north,0x69,0x2d);
+
+ /* Delay >= 100ns after DRAM Frequency adjust, See 4.1.1.3 pg 15 */
+ udelay(200);
+
+
+ /* Enable CKE */
+ pci_write_config8(north,0x6b,0x10);
udelay(200);
- /* All bank precharge Command Enable */
- pci_write_config8(north,0x6b,0x02);
- dimm_read(0x1f000);
+ /* Disable DRAM refresh */
+ pci_write_config8(north,0x6a,0x0);
+
+
+ /* Set drive for 1 bank DDR (Table 4.4.2, pg 40) */
+ pci_write_config8(north,0x6d,0x044);
+ pci_write_config8(north,0x67,0x3a);
+
+ b = smbus_read_byte(0xa0,5); // SPD byte 5 # of physical banks
+ if( b > 1) {
+ // Increase drive control when there is more than 1 physical bank
+ pci_write_config8(north,0x6c,0x84); // Drive control: MA, DQS, MD/CKE
+ pci_write_config8(north,0x6d,0x55); // DC: Early clock select, DQM, CS#, MD
+ }
+ /* place frame buffer on last bank */
+ if( !b) b++; // make sure at least 1 bank reported
+ pci_write_config8(north,0xe3,b-1);
+
+ for( bank = 0 , bank_address=0; bank < b ; bank++){
+/*
+ DDR init described in Via BIOS Porting Guide. Pg 28 (4.2.3.1)
+*/
+
+
+ /* NOP command enable */
+ pci_write_config8(north,0x6b,0x11);
+
+ /* read a double word from any address of the dimm */
+ dimm_read(bank_address,0x1f000);
+ //udelay(200);
+
+ /* All bank precharge Command Enable */
+ pci_write_config8(north,0x6b,0x12);
+ dimm_read(bank_address,0x1f000);
+
+
+ /* MSR Enable */
+ pci_write_config8(north,0x6b,0x13);
+ dimm_read(bank_address,0x2000);
+ udelay(1);
+ dimm_read(bank_address,0x800);
+ udelay(1);
+
+ /* All banks precharge Command Enable */
+ pci_write_config8(north,0x6b,0x12);
+ dimm_read(bank_address,0x1f200);
+
+ /* CBR Cycle Enable */
+ pci_write_config8(north,0x6b,0x14);
+
+ /* Read 8 times */
+ dimm_read(bank_address,0x1f300);
+ udelay(100);
+ dimm_read(bank_address,0x1f400);
+ udelay(100);
+ dimm_read(bank_address,0x1f500);
+ udelay(100);
+ dimm_read(bank_address,0x1f600);
+ udelay(100);
+ dimm_read(bank_address,0x1f700);
+ udelay(100);
+ dimm_read(bank_address,0x1f800);
+ udelay(100);
+ dimm_read(bank_address,0x1f900);
+ udelay(100);
+ dimm_read(bank_address,0x1fa00);
+ udelay(100);
+
+ /* MSR Enable */
+ pci_write_config8(north,0x6b,0x13);
+
+/*
+ Mode Register Definition
+ with adjustement so that address calculation is correct - 64 bit technology, therefore
+ a0-a2 refer to byte within a 64 bit long word, and a3 is the first address line presented
+ to DIMM as a row or column address.
+
+ MR[9-7] CAS Latency
+ MR[6] Burst Type 0 = sequential, 1 = interleaved
+ MR[5-3] burst length 001 = 2, 010 = 4, 011 = 8, others reserved
+ MR[0-2] dont care
+
+ CAS Latency
+ 000 reserved
+ 001 reserved
+ 010 2
+ 011 3
+ 100 reserved
+ 101 1.5
+ 110 2.5
+ 111 reserved
+
+ CAS 2 0101011000 = 0x158
+ CAS 2.5 1101011000 = 0x358
+ CAS 3 0111011000 = 0x1d8
+
+*/
+ c = pci_read_config8(north,0x64);
+ if( (c & 0x30) == 0x10 )
+ dimm_read(bank_address,0x150);
+ else if((c & 0x30) == 0x20 )
+ dimm_read(bank_address,0x350);
+ else
+ dimm_read(bank_address,0x1d0);
+
+ //dimm_read(bank_address,0x350);
+
+ /* Normal SDRAM Mode */
+ pci_write_config8(north,0x6b,0x58 );
+
+
+ bank_address = pci_read_config8(north,0x5a+bank) * 0x1000000;
+ } // end of for each bank
+
+ /* Adjust DQS (data strobe output delay). See 4.2.3.2 pg 29 */
+ pci_write_config8(north,0x66,0x41);
+
+ /* determine low bond */
+ if( b == 2)
+ bank_address = pci_read_config8(north,0x5a) * 0x1000000;
+ else
+ bank_address = 0;
+
+ for(i = 0 ; i < 0x0ff; i++){
+ c = i ^ (i>>1); // convert to gray code
+ pci_write_config8(north,0x68,c);
+ // clear
+ *(volatile unsigned long*)(0x4000) = 0;
+ *(volatile unsigned long*)(0x4100+bank_address) = 0;
+ *(volatile unsigned long*)(0x4200) = 0;
+ *(volatile unsigned long*)(0x4300+bank_address) = 0;
+ *(volatile unsigned long*)(0x4400) = 0;
+ *(volatile unsigned long*)(0x4500+bank_address) = 0;
+
+
+ // fill
+ *(volatile unsigned long*)(0x4000) = 0x12345678;
+ *(volatile unsigned long*)(0x4100+bank_address) = 0x81234567;
+ *(volatile unsigned long*)(0x4200) = 0x78123456;
+ *(volatile unsigned long*)(0x4300+bank_address) = 0x67812345;
+ *(volatile unsigned long*)(0x4400) = 0x56781234;
+ *(volatile unsigned long*)(0x4500+bank_address) = 0x45678123;
+
+ // verify
+ if( *(volatile unsigned long*)(0x4000) != 0x12345678)
+ continue;
+
+ if( *(volatile unsigned long*)(0x4100+bank_address) != 0x81234567)
+ continue;
+
+ if( *(volatile unsigned long*)(0x4200) != 0x78123456)
+ continue;
+
+ if( *(volatile unsigned long*)(0x4300+bank_address) != 0x67812345)
+ continue;
+
+ if( *(volatile unsigned long*)(0x4400) != 0x56781234)
+ continue;
+
+ if( *(volatile unsigned long*)(0x4500+bank_address) != 0x45678123)
+ continue;
+
+ // if everything verified then found low bond
+ break;
+
+ }
+ print_val("\r\nLow Bond ",i);
+ if( i < 0xff ){
+ c = i++;
+ for( ; i <0xff ; i++){
+ pci_write_config8(north,0x68,i ^ (i>>1) );
+
+ // clear
+ *(volatile unsigned long*)(0x8000) = 0;
+ *(volatile unsigned long*)(0x8100+bank_address) = 0;
+ *(volatile unsigned long*)(0x8200) = 0x0;
+ *(volatile unsigned long*)(0x8300+bank_address) = 0;
+ *(volatile unsigned long*)(0x8400) = 0x0;
+ *(volatile unsigned long*)(0x8500+bank_address) = 0;
+
+ // fill
+ *(volatile unsigned long*)(0x8000) = 0x12345678;
+ *(volatile unsigned long*)(0x8100+bank_address) = 0x81234567;
+ *(volatile unsigned long*)(0x8200) = 0x78123456;
+ *(volatile unsigned long*)(0x8300+bank_address) = 0x67812345;
+ *(volatile unsigned long*)(0x8400) = 0x56781234;
+ *(volatile unsigned long*)(0x8500+bank_address) = 0x45678123;
+
+ // verify
+ if( *(volatile unsigned long*)(0x8000) != 0x12345678)
+ break;
+
+ if( *(volatile unsigned long*)(0x8100+bank_address) != 0x81234567)
+ break;
+
+ if( *(volatile unsigned long*)(0x8200) != 0x78123456)
+ break;
+
+ if( *(volatile unsigned long*)(0x8300+bank_address) != 0x67812345)
+ break;
+
+ if( *(volatile unsigned long*)(0x8400) != 0x56781234)
+ break;
+
+ if( *(volatile unsigned long*)(0x8500+bank_address) != 0x45678123)
+ break;
+
+ }
+ print_val(" High Bond",i);
+ c = ((i - c)<<1)/3 +c;
+ print_val(" Setting DQS delay",c);
+ c = c ^ (c>>1); // convert to gray code
+ pci_write_config8(north,0x68,c);
+ pci_write_config8(north,0x68,0x42);
+ }else{
+ print_debug("Unable to determine low bond - Setting default\r\n");
+ pci_write_config8(north,0x68,0x59);
+ }
- /* MSR Enable */
- pci_write_config8(north,0x6b,0x03);
- dimm_read(0x2000);
- dimm_read(0x800);
+ pci_write_config8(north,0x66,0x01);
+ pci_write_config8(north,0x55,0x07);
- /* All banks precharge Command Enable */
- pci_write_config8(north,0x6b,0x02);
- dimm_read(0x1f200);
- /* CBR Cycle Enable */
- pci_write_config8(north,0x6b,0x04);
- /* Read 8 times */
- dimm_read(0x1f300);
- udelay(100);
- dimm_read(0x1f400);
- udelay(100);
- dimm_read(0x1f500);
- udelay(100);
- dimm_read(0x1f600);
- udelay(100);
- dimm_read(0x1f700);
- udelay(100);
- dimm_read(0x1f800);
- udelay(100);
- dimm_read(0x1f900);
- udelay(100);
- dimm_read(0x1fa00);
- udelay(100);
+/*
+ DRAM refresh rate Device 0 Offset 6a
- /* MSR Enable */
- pci_write_config8(north,0x6b,0x03);
+ Units of 16 DRAM clock cycles. (See 4.4.1 pg 39)
- /* 0x150 if CAS Latency 2 or 0x350 CAS Latency 2.5 */
- dimm_read(0x350);
+ Rx69 (DRAM freq) Rx58 (chip tech) Rx6a
- /* Normal SDRAM Mode */
- pci_write_config8(north,0x6b,0x58 );
+ 133Mhz 64/128Mb 0x86
+ 133Mhz 256/512Mb 0x43
+ 100Mhz 64/128Mb 0x65
+ 100Mhz 256/512Mb 0x32
+*/
+ b = pci_read_config8(north,0x58);
+ if( b < 0x80 ) // 256 tech
+ pci_write_config8(north,0x6a,0x86);
+ else
+ pci_write_config8(north,0x6a,0x43);
- /* Set the refresh rate */
- pci_write_config8(north,0x6a,0x43);
- pci_write_config8(north,0x67,0x22);
+ pci_write_config8(north,0x61,0xff);
+ //pci_write_config8(north,0x67,0x22);
/* pci */
pci_write_config8(north,0x70,0x82);
@@ -351,14 +591,18 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
/* graphics aperture base */
+
pci_write_config8(north,0x13,0xd0);
- //pci_write_config8(north,0x56,0x10);
- //pci_write_config8(north,0x57,0x10);
+ //pci_write_config8(north,0xe1,0xdf);
+ //pci_write_config8(north,0xe2,0x42);
+ pci_write_config8(north,0xe0,0x00);
+
+ pci_write_config8(north,0x84,0x80);
+ pci_write_config16(north,0x80,0x610f);
+ pci_write_config32(north,0x88,0x00000002);
+
- pci_write_config8(north,0xe0,0x80);
- pci_write_config8(north,0xe1,0xdf);
- pci_write_config8(north,0xe2,0x42);
pci_write_config8(north,0xa8,0x04);
pci_write_config8(north,0xac,0x2f);
@@ -366,4 +610,18 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
print_err("vt8623 done\r\n");
dumpnorth(north);
+
+ print_err("AGP\r\n");
+ north = pci_locate_device(PCI_ID(0x1106, 0xb091), 0);
+ pci_write_config32(north,0x20,0xddf0dc00);
+ pci_write_config32(north,0x24,0xdbf0d800);
+ pci_write_config8(north,0x3e,0x0c);
+ //dumpnorth(north);
+
+ //print_err("VGA\n");
+ //north = pci_locate_device(PCI_ID(0x1106, 0x3122), 0);
+ //pci_write_config32(north,0x10,0xd8000008);
+ //pci_write_config32(north,0x14,0xdc000000);
+ //dumpnorth(north);
+
}