Al Boldi wrote:
> Uwe Hermann wrote:
>> On Sun, Feb 25, 2007 at 07:40:55PM -0500, Corey Osgood wrote:
>>> Uwe Hermann wrote:
>>>> On Thu, Dec 07, 2006 at 08:02:17PM +0100, Shaddam Corrino IV wrote:
>>>>> Any news on 440BX platform?
>>>> Hm, not yet. I'm stuck a bit as I cannot get the RAM to work when
>>>> hardcoding the registers. As soon as that works it's only a matter of
>>>> (not too much) time to get the generic code to work.
>>> Have you had any luck with this? I'm tinkering around with my asus p2-99
>>> (440zx) while I wait for a POST card to come in for the other toy.
>> Nope, sorry. I tried on a Gigabyte GA-6BXC and on an Asus P2B board, but
>> I can't seem to find out where the problem lies.
>>
>> Is anybody with such a board out there who could test/debug my code?
>
> Of course. Can you post a tarball link?
I'm currently playing with the raminit.c that I've attached, it's from
one of his old posts. Uwe, have you done anything more since this? And
do you have a new northbridge.c also? Mine's a hack from what was there
(fixing regs, etc), I have no idea if it works right or not.
>
>> Maybe I'm just too stupid to see an obious error...
>
> What I can't understand, why does v1 work whereas v2 doesn't?
>
Probably because the code currently in the svn looks for the vt8601, and
attempts to program the wrong registers :-p And btw, there's a big
difference between another set of eyes catching something and just being
stupid. Just out of curiousity, in sdram_set_registers, are those values
you decided to send, or ones from a running system?
> Can you post a working v1 tarball link as well?
>
http://www.openbios.org/viewvc/trunk/LinuxBIOSv1.tar.gz?view=tar
-Corey
#include <spd.h>
#include <sdram_mode.h>
#include "i440bx.h"
/*-----------------------------------------------------------------------------
Definitions.
-----------------------------------------------------------------------------*/
/* Uncomment this to enable local debugging messages. */
#define DEBUG_RAM_CONFIG 1
/* Debugging macros. */
#if defined(DEBUG_RAM_CONFIG)
#define RAM_DEBUG_MESSAGE(x) print_debug(x)
#define RAM_DEBUG_HEX32(x) print_debug_hex32(x)
#define RAM_DEBUG_HEX8(x) print_debug_hex8(x)
#define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0))
#else
#define RAM_DEBUG_MESSAGE(x)
#define RAM_DEBUG_HEX32(x)
#define RAM_DEBUG_HEX8(x)
#define DUMPNORTH()
#endif
/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
#define RAM_COMMAND_NORMAL 0x0
#define RAM_COMMAND_NOP 0x1
#define RAM_COMMAND_PRECHARGE 0x2
#define RAM_COMMAND_MRS 0x3
#define RAM_COMMAND_CBR 0x4
/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
* defined in DRAMC[2:0].
*
* [0] == Normal 15.625 us -> 15.6 us
* [1] == Reduced(.25X) 3.9 us -> 7.8 ns
* [2] == Reduced(.5X) 7.8 us -> 7.8 us
* [3] == Extended(2x) 31.3 us -> 31.2 us
* [4] == Extended(4x) 62.5 us -> 62.4 us
* [5] == Extended(8x) 125 us -> 124.8 us
*/
static const uint32_t refresh_rate_map[] = {
1, 5, 5, 2, 3, 4
};
/*-----------------------------------------------------------------------------
Delay functions.
-----------------------------------------------------------------------------*/
#define SLOW_DOWN_IO inb(0x80);
static void do_delay(void)
{
int i;
for (i = 0; i < 16; i++) {
SLOW_DOWN_IO
}
}
#define DO_DELAY do_delay();
#define EXTRA_DELAY DO_DELAY
/*-----------------------------------------------------------------------------
SDRAM configuration functions.
-----------------------------------------------------------------------------*/
static void do_ram_command(const struct mem_controller *ctrl,
uint32_t command, uint16_t jedec_mode_bits)
{
int i;
uint16_t reg;
/* Configure the RAM command. */
reg = pci_read_config16(ctrl->d0, SDRAMC);
reg &= 0xff1f; /* Clear bits 7-5. */
reg |= (uint16_t)(command << 5);
pci_write_config16(ctrl->d0, SDRAMC, reg);
/* RAM_COMMAND_NORMAL affects only the memory controller and
doesn't need to be "sent" to the DIMMs. */
/* if (command == RAM_COMMAND_NORMAL) return; */
/* Note: 2^23 == 8 MB (440BX stores multiples of 8 MB in DRB regs). */
/* We shift 8 by 23 to make a total of 64 MB. */
RAM_DEBUG_MESSAGE(" Sending RAM command to 0x");
RAM_DEBUG_HEX32((0x8 << 23) + jedec_mode_bits);
RAM_DEBUG_MESSAGE("\r\n");
/* read32(0x0 + jedec_mode_bits); */
read32((0x8 << 23) + jedec_mode_bits);
}
/*-----------------------------------------------------------------------------
DIMM-independant configuration functions.
-----------------------------------------------------------------------------*/
static void spd_enable_refresh(const struct mem_controller *ctrl)
{
uint8_t reg;
int i, value;
reg = pci_read_config8(ctrl->d0, DRAMC);
for (i = 0; i < MAX_DIMM_SOCKETS_PER_CHANNEL; i++) {
value = spd_read_byte(ctrl->channel0[i], SPD_REFRESH);
if (value < 0) continue;
reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
}
pci_write_config8(ctrl->d0, DRAMC, reg);
}
/*-----------------------------------------------------------------------------
Public interface.
-----------------------------------------------------------------------------*/
static void sdram_set_registers(const struct mem_controller *ctrl)
{
RAM_DEBUG_MESSAGE("Northbridge prior to SDRAM init:\r\n");
DUMPNORTH();
pci_write_config8(ctrl->d0, PAM0, 0x10);
pci_write_config8(ctrl->d0, PAM1, 0x11);
pci_write_config8(ctrl->d0, PAM2, 0x01);
pci_write_config8(ctrl->d0, PAM3, 0x00);
pci_write_config8(ctrl->d0, PAM4, 0x00);
pci_write_config8(ctrl->d0, PAM5, 0x00);
pci_write_config8(ctrl->d0, PAM6, 0x00);
pci_write_config8(ctrl->d0, 0x13, 0xd8);
pci_write_config8(ctrl->d0, 0x92, 0x00);
pci_write_config8(ctrl->d0, 0x0d, 0x40);
pci_write_config8(ctrl->d0, 0x13, 0xd8);
pci_write_config8(ctrl->d0, DRAMT, 0x00);
pci_write_config8(ctrl->d0, 0x6d, 0x2a);
pci_write_config8(ctrl->d0, 0x70, 0x20);
pci_write_config8(ctrl->d0, SMRAM, 0x0a);
pci_write_config8(ctrl->d0, 0x80, 0x02);
pci_write_config8(ctrl->d0, 0x90, 0x98);
pci_write_config8(ctrl->d0, 0x91, 0xcc);
pci_write_config8(ctrl->d0, 0xb0, 0x80);
pci_write_config8(ctrl->d0, 0xb1, 0x20);
pci_write_config8(ctrl->d0, 0xb4, 0x30);
pci_write_config8(ctrl->d0, 0xba, 0x45);
pci_write_config8(ctrl->d0, 0xbb, 0x03);
pci_write_config8(ctrl->d0, 0xbc, 0x20);
pci_write_config8(ctrl->d0, 0xbd, 0x10);
pci_write_config8(ctrl->d0, 0xc4, 0xff);
pci_write_config8(ctrl->d0, 0xc5, 0xfd);
pci_write_config8(ctrl->d0, 0xc6, 0xff);
pci_write_config8(ctrl->d0, 0xc7, 0xff);
pci_write_config8(ctrl->d0, 0xc8, 0x18);
pci_write_config8(ctrl->d0, 0xc9, 0x0c);
pci_write_config8(ctrl->d0, 0xca, 0xff);
pci_write_config8(ctrl->d0, 0xcb, 0xff);
pci_write_config8(ctrl->d0, 0xcc, 0x61);
pci_write_config8(ctrl->d0, 0xe0, 0x4c);
pci_write_config8(ctrl->d0, 0xe1, 0xad);
pci_write_config8(ctrl->d0, 0xe2, 0xff);
pci_write_config8(ctrl->d0, 0xe3, 0xbb);
pci_write_config8(ctrl->d0, 0xe4, 0x8a);
pci_write_config8(ctrl->d0, 0xe5, 0x3e);
pci_write_config8(ctrl->d0, 0xe6, 0x00);
/* pci_write_config8(ctrl->d0, 0xe7, 0x80); */
pci_write_config8(ctrl->d0, 0xe8, 0x2c);
pci_write_config8(ctrl->d0, 0xe9, 0xd3);
pci_write_config8(ctrl->d0, 0xea, 0xf7);
pci_write_config8(ctrl->d0, 0xeb, 0xcf);
pci_write_config8(ctrl->d0, 0xec, 0x9d);
pci_write_config8(ctrl->d0, 0xed, 0x3e);
pci_write_config8(ctrl->d0, 0xee, 0x00);
pci_write_config8(ctrl->d0, 0xef, 0x00);
/* Now set bit 7 of 0xe7 (must come last). */
pci_write_config8(ctrl->d0, 0xe7, 0x80);
pci_write_config8(ctrl->d0, 0xf0, 0x40);
pci_write_config8(ctrl->d0, 0xf1, 0x01);
pci_write_config8(ctrl->d0, 0xf7, 0x60);
/* TODO: Do this later? */
pci_write_config8(ctrl->d0, PMCR, 0x10);
}
static void sdram_set_spd_registers(const struct mem_controller *ctrl)
{
pci_write_config8(ctrl->d0, DRB0, 0x00);
pci_write_config8(ctrl->d0, DRB1, 0x00);
pci_write_config8(ctrl->d0, DRB2, 0x00);
pci_write_config8(ctrl->d0, DRB3, 0x00);
pci_write_config8(ctrl->d0, DRB4, 0x00);
pci_write_config8(ctrl->d0, DRB5, 0x00);
pci_write_config8(ctrl->d0, DRB6, 0x08);
pci_write_config8(ctrl->d0, DRB7, 0x08);
/* Don't enable refresh for now. */
pci_write_config8(ctrl->d0, DRAMC, 0x08);
pci_write_config16(ctrl->d0, RPS, 0x1000);
pci_write_config16(ctrl->d0, SDRAMC, 0x0110);
pci_write_config16(ctrl->d0, PGPOL, 0xff23);
pci_write_config32(ctrl->d0, NBXCFG, 0xff008a0c);
}
static void sdram_enable(int controllers, const struct mem_controller *ctrl)
{
/* 1. & 2. Power up and start clocks. */
RAM_DEBUG_MESSAGE("Ram Enable 1: Power up\r\n");
RAM_DEBUG_MESSAGE("Ram Enable 2: Start clocks\r\n");
/* A 200us delay is needed. */
DO_DELAY
EXTRA_DELAY
/* 3. Apply NOP. */
RAM_DEBUG_MESSAGE("Ram Enable 3: Apply NOP\r\n");
do_ram_command(ctrl, RAM_COMMAND_NOP, 0);
EXTRA_DELAY
/* 4. Precharge all. */
RAM_DEBUG_MESSAGE("Ram Enable 4: Precharge all\r\n");
do_ram_command(ctrl, RAM_COMMAND_PRECHARGE, 0);
EXTRA_DELAY
/* 5. Issue EMRS to enable DLL (not needed on 440BX). */
/* 6. Reset DLL (not needed on 440BX). */
/* 7. Precharge all (not needed on 440BX). */
/* 8. Perform eight AUTO REFRESH / CBR cycles. */
RAM_DEBUG_MESSAGE("Ram Enable 8: CBR\r\n");
do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
EXTRA_DELAY
do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
EXTRA_DELAY
do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
EXTRA_DELAY
do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
EXTRA_DELAY
do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
EXTRA_DELAY
do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
EXTRA_DELAY
do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
EXTRA_DELAY
do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
EXTRA_DELAY
/* 9. Mode register set. */
RAM_DEBUG_MESSAGE("Ram Enable 9: Mode register set\r\n");
do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0);
/* do_ram_command(ctrl, RAM_COMMAND_MRS, 0x150); */
/* do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0 ^ 0xff8); */
EXTRA_DELAY
EXTRA_DELAY
/* 10. DDR Receive FIFO Resync (not needed on 440BX). */
/* 11. Normal operation. */
RAM_DEBUG_MESSAGE("Ram Enable 11: Normal operation\r\n");
do_ram_command(ctrl, RAM_COMMAND_NORMAL, 0);
EXTRA_DELAY
/* Finally enable refresh. */
RAM_DEBUG_MESSAGE("Finally enabling refresh\r\n");
spd_enable_refresh(ctrl);
EXTRA_DELAY
RAM_DEBUG_MESSAGE("Northbridge following SDRAM init:\r\n");
DUMPNORTH();
}
--
linuxbios mailing list
[email protected]
http://www.openbios.org/mailman/listinfo/linuxbios