mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
First cut at utilities to scan spd.
This commit is contained in:
parent
68b925b9a4
commit
b101440e7d
4 changed files with 331 additions and 0 deletions
12
util/scanspd/Makefile
Normal file
12
util/scanspd/Makefile
Normal file
|
@ -0,0 +1,12 @@
|
|||
LINUXBIOS=../../
|
||||
CFLAGS += -O2 -g
|
||||
LDFLAGS += -g
|
||||
INCLUDE=
|
||||
|
||||
spd_82801: spd_82801.o pcibios.o
|
||||
|
||||
spd_82801.o: spd_82801.c
|
||||
cc -g -I. -O2 -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.o spd_82801
|
3
util/scanspd/README
Normal file
3
util/scanspd/README
Normal file
|
@ -0,0 +1,3 @@
|
|||
In here are programs to scan SPD dram for various chip types.
|
||||
|
||||
ron
|
54
util/scanspd/pcibios.c
Normal file
54
util/scanspd/pcibios.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned long u32;
|
||||
|
||||
#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3))
|
||||
|
||||
int pcibios_write_config_byte(unsigned char bus, int devfn, int where, unsigned char value)
|
||||
{
|
||||
outl(CONFIG_CMD(bus,devfn,where&0xfc), 0xCF8);
|
||||
outb(value, (0xCFC + (where&2)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_write_config_word(unsigned char bus, int devfn, int where, u16 value)
|
||||
{
|
||||
outl(CONFIG_CMD(bus,devfn,where&0xfc), 0xCF8);
|
||||
outw(value, (0xCFC + (where&2)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_write_config_dword(unsigned char bus, int devfn, int where, u32 value)
|
||||
{
|
||||
outl(CONFIG_CMD(bus,devfn,where&0xfc), 0xCF8);
|
||||
outl(value, 0xcfc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_read_config_byte(unsigned char bus, int devfn, int where, unsigned char *value)
|
||||
{
|
||||
outl(CONFIG_CMD(bus,devfn,(where&0xfc)), 0xCF8);
|
||||
*value = inw(0xCFC + (where&2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_read_config_word(unsigned char bus, int devfn, int where, u16 *value)
|
||||
{
|
||||
outl(CONFIG_CMD(bus,devfn,where&0xfc), 0xCF8);
|
||||
*value = inw(0xCFC + (where&2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_read_config_dword(unsigned char bus, int devfn, int where, u32 *value)
|
||||
{
|
||||
u32 retval;
|
||||
int i, j;
|
||||
outl(CONFIG_CMD(bus,devfn,where&0xfc), 0xCF8);
|
||||
retval = inl(0xCFC);
|
||||
*value = retval;
|
||||
return 0;
|
||||
}
|
||||
|
262
util/scanspd/spd_82801.c
Normal file
262
util/scanspd/spd_82801.c
Normal file
|
@ -0,0 +1,262 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/io.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* * $Id$*/
|
||||
/*
|
||||
* 82801Support code by Eric Beiderman of lnxi.com
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#include <smbus.h>
|
||||
#include <arch/io.h>
|
||||
#include <pci.h>
|
||||
#include <southbridge/intel/82801.h>
|
||||
#include "82801.h"
|
||||
#endif
|
||||
|
||||
int smbus_io_base;
|
||||
int smbus_devfn;
|
||||
#define SMBUS_BUS 0
|
||||
|
||||
#define SMBHSTSTAT 0x0
|
||||
#define SMBHSTCTL 0x2
|
||||
#define SMBHSTCMD 0x3
|
||||
#define SMBXMITADD 0x4
|
||||
#define SMBHSTDAT0 0x5
|
||||
#define SMBHSTDAT1 0x6
|
||||
#define SMBBLKDAT 0x7
|
||||
#define SMBTRNSADD 0x9
|
||||
#define SMBSLVDATA 0xa
|
||||
#define SMLINK_PIN_CTL 0xe
|
||||
#define SMBUS_PIN_CTL 0xf
|
||||
|
||||
/* Define register settings */
|
||||
#define HOST_RESET 0xfe
|
||||
#define DIMM_BASE 0xa0 // 1010000 is base for DIMM in SMBus
|
||||
#define READ_CMD 0x01 // 1 in the 0 bit of SMBHSTADD states to READ
|
||||
|
||||
void smbus_setup(void)
|
||||
{
|
||||
pcibios_read_config_dword(SMBUS_BUS, smbus_devfn, 0x20,
|
||||
&smbus_io_base);
|
||||
smbus_io_base &= ~3;
|
||||
pcibios_write_config_byte(SMBUS_BUS, smbus_devfn, 0x40, 1);
|
||||
pcibios_write_config_word(SMBUS_BUS, smbus_devfn, 0x4, 1);
|
||||
}
|
||||
|
||||
static void smbus_wait_until_ready(void)
|
||||
{
|
||||
volatile unsigned char c;
|
||||
|
||||
c = inb(smbus_io_base + SMBHSTSTAT);
|
||||
while((c & 1) == 1) {
|
||||
printf("c is 0x%x\n", c);
|
||||
c = inb(smbus_io_base + SMBHSTSTAT);
|
||||
/* nop */
|
||||
}
|
||||
}
|
||||
|
||||
void reset(void)
|
||||
{
|
||||
outb(HOST_RESET, smbus_io_base + SMBHSTSTAT);
|
||||
outb(HOST_RESET, smbus_io_base + SMBHSTSTAT);
|
||||
outb(HOST_RESET, smbus_io_base + SMBHSTSTAT);
|
||||
outb(HOST_RESET, smbus_io_base + SMBHSTSTAT);
|
||||
|
||||
smbus_wait_until_ready();
|
||||
printf("After reset status %#x\n", inb(smbus_io_base + SMBHSTSTAT));
|
||||
}
|
||||
|
||||
static void smbus_wait_until_done(void)
|
||||
{
|
||||
unsigned char byte;
|
||||
unsigned long giveup;
|
||||
do {
|
||||
byte = inb(smbus_io_base + SMBHSTSTAT);
|
||||
giveup++;
|
||||
if (giveup > 1000000)
|
||||
return;
|
||||
} while((byte &1) == 1);
|
||||
while( (byte & ~((1<<6)|(1<<0))) == 0) {
|
||||
byte = inb(smbus_io_base + SMBHSTSTAT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void smbus_print_error(unsigned char host_status_register)
|
||||
{
|
||||
|
||||
printf("smbus_error: 0x%02x\n", host_status_register);
|
||||
if (host_status_register & (1 << 7)) {
|
||||
printf("Byte Done Status\n");
|
||||
}
|
||||
if (host_status_register & (1 << 6)) {
|
||||
printf("In Use Status\n");
|
||||
}
|
||||
if (host_status_register & (1 << 5)) {
|
||||
printf("SMBus Alert Status\n");
|
||||
}
|
||||
if (host_status_register & (1 << 4)) {
|
||||
printf("Interrup/SMI# was Failed Bus Transaction\n");
|
||||
}
|
||||
if (host_status_register & (1 << 3)) {
|
||||
printf("Bus Error\n");
|
||||
}
|
||||
if (host_status_register & (1 << 2)) {
|
||||
printf("Device Error\n");
|
||||
}
|
||||
if (host_status_register & (1 << 1)) {
|
||||
printf("Interrupt/SMI# was Successful Completion\n");
|
||||
}
|
||||
if (host_status_register & (1 << 0)) {
|
||||
printf("Host Busy\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
|
||||
{
|
||||
unsigned char host_status_register;
|
||||
unsigned char byte;
|
||||
|
||||
reset();
|
||||
|
||||
smbus_wait_until_ready();
|
||||
|
||||
/* setup transaction */
|
||||
/* disable interrupts */
|
||||
outb(inb(smbus_io_base + SMBHSTCTL) & (~1), smbus_io_base + SMBHSTCTL);
|
||||
/* set the device I'm talking too */
|
||||
outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
|
||||
/* set the command/address... */
|
||||
outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
|
||||
/* set up for a byte data read */
|
||||
outb((inb(smbus_io_base + SMBHSTCTL) & 0xE3) | (0x2 << 2),
|
||||
smbus_io_base + SMBHSTCTL);
|
||||
|
||||
/* clear any lingering errors, so the transaction will run */
|
||||
outb(inb(smbus_io_base + SMBHSTSTAT), smbus_io_base + SMBHSTSTAT);
|
||||
|
||||
/* clear the data byte...*/
|
||||
outb(0, smbus_io_base + SMBHSTDAT0);
|
||||
|
||||
/* start the command */
|
||||
outb((inb(smbus_io_base + SMBHSTCTL) | 0x40),
|
||||
smbus_io_base + SMBHSTCTL);
|
||||
|
||||
/* poll for transaction completion */
|
||||
smbus_wait_until_done();
|
||||
|
||||
host_status_register = inb(smbus_io_base + SMBHSTSTAT);
|
||||
|
||||
/* Ignore the In Use Status... */
|
||||
host_status_register &= ~(1 << 6);
|
||||
|
||||
/* read results of transaction */
|
||||
byte = inb(smbus_io_base + SMBHSTDAT0);
|
||||
smbus_print_error(byte);
|
||||
|
||||
*result = byte;
|
||||
return host_status_register != 0x02;
|
||||
}
|
||||
/*
|
||||
* Scan SPD bus
|
||||
*
|
||||
*
|
||||
* Derived from ...
|
||||
* Copyright 2000 Silicon Integrated System Corporation
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* Reference:
|
||||
* 1. SiS 630 Specification
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
unsigned short acpi_base;
|
||||
|
||||
unsigned char
|
||||
read_spd(unsigned char slot, unsigned char index)
|
||||
{
|
||||
unsigned char value;
|
||||
|
||||
smbus_read_byte(0xA1 + (slot << 1), index, &value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
unsigned char b;
|
||||
unsigned short w;
|
||||
int slot;
|
||||
|
||||
|
||||
/* get io privilege access PCI configuration space */
|
||||
if (iopl(3) != 0) {
|
||||
perror("Can not set io priviliage");
|
||||
exit(1);
|
||||
}
|
||||
// Find the 801
|
||||
for (smbus_devfn = 0; smbus_devfn < 256; smbus_devfn++)
|
||||
{
|
||||
unsigned long val;
|
||||
pcibios_read_config_dword(0, smbus_devfn, 0, &val);
|
||||
if (val == 0x24438086)
|
||||
break;
|
||||
}
|
||||
|
||||
if (smbus_devfn == 256) {
|
||||
printf("smbus_devfn not found!\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
smbus_setup();
|
||||
reset();
|
||||
|
||||
for(slot = 1; slot < 0xff; slot += 2) {
|
||||
unsigned char val;
|
||||
if (slot == 0x6a)
|
||||
continue;
|
||||
smbus_read_byte(slot, 0, &val);
|
||||
printf("slot 0x%x val 0x%x\n", slot, val);
|
||||
}
|
||||
for(slot = 0; slot < 4; slot++) {
|
||||
printf("SLOT %d\n", slot);
|
||||
printf("Number of bytes used by module manufacturer 0x%02x\n",
|
||||
read_spd(slot, 0x00));
|
||||
|
||||
printf("Memory Type 0x%02x\n",
|
||||
read_spd(slot, 0x02));
|
||||
|
||||
printf("Number of Row Address bits 0x%02x\n",
|
||||
read_spd(slot, 0x03));
|
||||
|
||||
printf("Number of Column Address bits 0x%02x\n",
|
||||
read_spd(slot, 0x04));
|
||||
|
||||
printf("Number of Sides 0x%02x\n",
|
||||
read_spd(slot, 0x05));
|
||||
|
||||
printf("Number of Banks 0x%02x\n",
|
||||
read_spd(slot, 0x11));
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue