mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2025-02-25 18:55:23 -06:00
Add SMBUS support for Intel 82371AB (PIIX4) and AMD Bulldozer/Kabini (SB800/900)
This commit is contained in:
parent
6b253adb9a
commit
e0cee8e2c3
133
system/smbus.c
133
system/smbus.c
@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2004-2022 Samuel Demeulemeester
|
||||
//
|
||||
|
||||
#include "display.h"
|
||||
|
||||
@ -20,7 +19,7 @@
|
||||
ram_info ram = { 0, 0, 0, 0, 0, "N/A"};
|
||||
|
||||
int smbdev, smbfun;
|
||||
unsigned short smbusbase;
|
||||
unsigned short smbusbase = 0;
|
||||
|
||||
static int8_t spd_page = -1;
|
||||
static int8_t last_adr = -1;
|
||||
@ -36,12 +35,23 @@ static void print_spdi(spd_info spdi, uint8_t lidx);
|
||||
|
||||
static int find_smb_controller(void);
|
||||
|
||||
static void amd_sb_get_smb(void);
|
||||
static void fch_zen_get_smb(void);
|
||||
|
||||
static void piix4_get_smb(void);
|
||||
static void ich5_get_smb(void);
|
||||
static uint8_t ich5_process(void);
|
||||
static uint8_t ich5_read_spd_byte(uint8_t adr, uint16_t cmd);
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// WARNING: Be careful when adding a controller ID!
|
||||
// Incorrect SMB accesses (ie: on bank switch) can brick your
|
||||
// motherboard or your memory module.
|
||||
// ----
|
||||
// No Pull Request including a new SMBUS Controller will be
|
||||
// accepted without a proof (screenshot) that it has been
|
||||
// tested successfully on a real motherboard.
|
||||
// ----------------------------------------------------------
|
||||
|
||||
static const struct pci_smbus_controller smbcontrollers[] = {
|
||||
{0x8086, 0x2413, "82801AA (ICH)", ich5_get_smb, ich5_read_spd_byte},
|
||||
{0x8086, 0x2423, "82801AB (ICH)", ich5_get_smb, ich5_read_spd_byte},
|
||||
@ -103,7 +113,7 @@ static const struct pci_smbus_controller smbcontrollers[] = {
|
||||
{0x8086, 0x54A3, "Alder Lake-M (PCH)", ich5_get_smb, ich5_read_spd_byte},
|
||||
|
||||
// AMD SMBUS
|
||||
{0x1022, 0x780B, "AMD FCH", NULL, NULL},
|
||||
{0x1022, 0x780B, "AMD SB800/900", amd_sb_get_smb, ich5_read_spd_byte},
|
||||
{0x1022, 0x790B, "AMD FCH (Zen)", fch_zen_get_smb, ich5_read_spd_byte},
|
||||
{0, 0, "", NULL, NULL}
|
||||
};
|
||||
@ -125,6 +135,10 @@ void print_smbus_startup_info(void) {
|
||||
|
||||
smbcontrollers[index].get_adr();
|
||||
|
||||
if (smbusbase == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (spdidx = 0; spdidx < MAX_SPD_SLOT; spdidx++) {
|
||||
|
||||
if (get_spd(index, spdidx, 0) != 0xFF) {
|
||||
@ -1213,16 +1227,29 @@ static int find_smb_controller(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// i801 / ICH5 Access
|
||||
// ------------------
|
||||
// ----------------------
|
||||
// PIIX4 SMBUS Controller
|
||||
// ----------------------
|
||||
|
||||
static void piix4_get_smb(void)
|
||||
{
|
||||
uint16_t x = pci_config_read16(0, smbdev, smbfun, 0x90) & 0xFFF0;
|
||||
|
||||
if (x != 0) {
|
||||
smbusbase = x;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
// i801 / ICH5 SMBUS Controller
|
||||
// ----------------------------
|
||||
|
||||
static void ich5_get_smb(void)
|
||||
{
|
||||
unsigned long x;
|
||||
uint16_t x;
|
||||
|
||||
x = pci_config_read16(0, smbdev, smbfun, 0x20);
|
||||
smbusbase = (unsigned short) x & 0xFFF0;
|
||||
smbusbase = x & 0xFFF0;
|
||||
|
||||
// Enable I2C Bus
|
||||
uint8_t temp = pci_config_read8(0, smbdev, smbfun, 0x40);
|
||||
@ -1235,6 +1262,63 @@ static void ich5_get_smb(void)
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// AMD SMBUS Controller
|
||||
// --------------------
|
||||
|
||||
static void amd_sb_get_smb(void)
|
||||
{
|
||||
uint8_t rev_id;
|
||||
uint16_t pm_reg;
|
||||
|
||||
rev_id = pci_config_read8(0, smbdev, smbfun, 0x08);
|
||||
|
||||
// AMD did the switch between PIIX4 and proprietary SMBase Access somewhere
|
||||
// between rev 0x30 and 0x3A. Assume 0x3A (Tested OK on AM1 SoC)
|
||||
if (rev_id < 0x3A) {
|
||||
// Older AMD SouthBridge (SB700 & older) use PIIX4 registers
|
||||
piix4_get_smb();
|
||||
} else {
|
||||
// Newer AMD SouthBridge (SB800 up to Zen) uses specific registers
|
||||
__outb(AMD_SMBUS_BASE_REG + 1, AMD_INDEX_IO_PORT);
|
||||
pm_reg = __inb(AMD_DATA_IO_PORT) << 8;
|
||||
__outb(AMD_SMBUS_BASE_REG, AMD_INDEX_IO_PORT);
|
||||
pm_reg |= __inb(AMD_DATA_IO_PORT) & 0xE0;
|
||||
|
||||
if (pm_reg != 0xFFE0 && pm_reg != 0) {
|
||||
smbusbase = pm_reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fch_zen_get_smb(void)
|
||||
{
|
||||
uint16_t pm_reg;
|
||||
|
||||
__outb(AMD_PM_INDEX + 1, AMD_INDEX_IO_PORT);
|
||||
pm_reg = __inb(AMD_DATA_IO_PORT) << 8;
|
||||
__outb(AMD_PM_INDEX, AMD_INDEX_IO_PORT);
|
||||
pm_reg |= __inb(AMD_DATA_IO_PORT);
|
||||
|
||||
printf(22,0,"pmreg: 0x%x",pm_reg);
|
||||
|
||||
// Special case for AMD Cezanne (get smb address in memory)
|
||||
if (imc_type == IMC_K19_CZN && pm_reg == 0xFFFF) {
|
||||
smbusbase = ((*(const uint32_t *)(0xFED80000 + 0x300) >> 8) & 0xFF) << 8;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if IO Smbus is enabled.
|
||||
if ((pm_reg & 0x10) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pm_reg & 0xFF00) != 0) {
|
||||
smbusbase = pm_reg & 0xFF00;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************
|
||||
/ ***************************** WARNING *****************************
|
||||
/ ************************************************************************************
|
||||
@ -1334,34 +1418,3 @@ static uint8_t ich5_process(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// AMD SMBUS Controller
|
||||
// --------------------
|
||||
|
||||
static void fch_zen_get_smb(void)
|
||||
{
|
||||
uint16_t pm_reg;
|
||||
|
||||
smbusbase = 0;
|
||||
|
||||
__outb(AMD_PM_INDEX + 1, AMD_INDEX_IO_PORT);
|
||||
pm_reg = __inb(AMD_DATA_IO_PORT) << 8;
|
||||
__outb(AMD_PM_INDEX, AMD_INDEX_IO_PORT);
|
||||
pm_reg |= __inb(AMD_DATA_IO_PORT);
|
||||
|
||||
// Special case for AMD Cezanne (get smb address in memory)
|
||||
if (imc_type == IMC_K19_CZN && pm_reg == 0xFFFF) {
|
||||
smbusbase = ((*(const uint32_t *)(0xFED80000 + 0x300) >> 8) & 0xFF) << 8;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if IO Smbus is enabled.
|
||||
if ((pm_reg & 0x10) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pm_reg & 0xFF00) != 0) {
|
||||
smbusbase = pm_reg & 0xFF00;
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
/* AMD-Specific constants */
|
||||
#define AMD_INDEX_IO_PORT 0xCD6
|
||||
#define AMD_DATA_IO_PORT 0xCD7
|
||||
#define AMD_SMBUS_BASE_REG 0x2C
|
||||
#define AMD_PM_INDEX 0x00
|
||||
|
||||
#define SPD5_MR11 11
|
||||
|
Loading…
Reference in New Issue
Block a user