mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2024-11-23 08:26:23 -06:00
Add a way to handle hardware quirks at init or later in the code. Add ASUS TUSL2-C ASB100 Mux as (working) example (#77)
This commit is contained in:
parent
d901f9e8a1
commit
bc8235f50d
@ -22,6 +22,7 @@
|
||||
#include "cpuid.h"
|
||||
#include "cpuinfo.h"
|
||||
#include "hwctrl.h"
|
||||
#include "hwquirks.h"
|
||||
#include "io.h"
|
||||
#include "keyboard.h"
|
||||
#include "pmem.h"
|
||||
@ -219,6 +220,8 @@ static void global_init(void)
|
||||
|
||||
smbios_init();
|
||||
|
||||
quirks_init();
|
||||
|
||||
badram_init();
|
||||
|
||||
config_init();
|
||||
|
@ -20,6 +20,7 @@ SYS_OBJS = system/cpuid.o \
|
||||
system/ehci.o \
|
||||
system/font.o \
|
||||
system/hwctrl.o \
|
||||
system/hwquirks.o \
|
||||
system/keyboard.o \
|
||||
system/ohci.o \
|
||||
system/pci.o \
|
||||
|
@ -20,6 +20,7 @@ SYS_OBJS = system/cpuid.o \
|
||||
system/ehci.o \
|
||||
system/font.o \
|
||||
system/hwctrl.o \
|
||||
system/hwquirks.o \
|
||||
system/keyboard.o \
|
||||
system/ohci.o \
|
||||
system/pci.o \
|
||||
|
73
system/hwquirks.c
Normal file
73
system/hwquirks.c
Normal file
@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2004-2022 Samuel Demeulemeester
|
||||
//
|
||||
// ------------------------
|
||||
// This file is used to detect quirks on specific hardware
|
||||
// that require proprietary init here *OR* different code path
|
||||
// later in various part of the code.
|
||||
//
|
||||
// Please add a quick comment for every quirk added to the list.
|
||||
|
||||
#include "hwquirks.h"
|
||||
#include "io.h"
|
||||
#include "pci.h"
|
||||
#include "unistd.h"
|
||||
|
||||
quirk_t quirk;
|
||||
|
||||
// --------------------------------------
|
||||
// -- Private quirk-specific functions --
|
||||
// --------------------------------------
|
||||
|
||||
static void asus_tusl2_configure_mux(void)
|
||||
{
|
||||
uint8_t muxreg;
|
||||
|
||||
// Enter ASB100 Config Mode
|
||||
outb(0x87, 0x2E);
|
||||
outb(0x87, 0x2E);
|
||||
usleep(200);
|
||||
|
||||
// Write LPC Command to access Config Mode Reg
|
||||
lpc_outb(0x7, 0x8);
|
||||
|
||||
// Read Config Mode Register
|
||||
muxreg = lpc_inb(0xF1);
|
||||
|
||||
// Change Smbus Mux Channel & Write Config Mode Register
|
||||
muxreg &= 0xE7;
|
||||
muxreg |= 0x10;
|
||||
lpc_outb(0xF1, muxreg);
|
||||
usleep(200);
|
||||
|
||||
// Leave Config Mode
|
||||
outb(0xAA, 0x2E);
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
// -- Public function --
|
||||
// ---------------------
|
||||
|
||||
void quirks_init(void)
|
||||
{
|
||||
quirk.id = QUIRK_NONE;
|
||||
quirk.type = QUIRK_TYPE_NONE;
|
||||
quirk.root_vid = pci_config_read16(0, 0, 0, 0);
|
||||
quirk.root_did = pci_config_read16(0, 0, 0, 2);
|
||||
|
||||
// ------------------------
|
||||
// -- ASUS TUSL2-C Quirk --
|
||||
// ------------------------
|
||||
// This motherboard has an ASB100 ASIC with a SMBUS Mux Integrated.
|
||||
// To access SPD later in the code, we need to configure the mux.
|
||||
// PS: Detection via DMI is unreliable, so using Root PCI Registers
|
||||
if (quirk.root_vid == 0x8086 && quirk.root_did == 0x1130) { // Intel i815
|
||||
if (pci_config_read16(0, 0, 0, 0x2C) == 0x1043) { // ASUS
|
||||
if (pci_config_read16(0, 0, 0, 0x2E) == 0x8027) { // TUSL2-C
|
||||
quirk.id = QUIRK_TUSL2;
|
||||
quirk.type |= QUIRK_TYPE_SMBUS;
|
||||
asus_tusl2_configure_mux();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
system/hwquirks.h
Normal file
37
system/hwquirks.h
Normal file
@ -0,0 +1,37 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2004-2022 Sam Demeulemeester
|
||||
#ifndef _QUIRK_H_
|
||||
#define _QUIRK_H_
|
||||
/**
|
||||
*
|
||||
* Provides support for hardware quirks
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define QUIRK_TYPE_NONE 0b00000000
|
||||
#define QUIRK_TYPE_USB 0b00000001
|
||||
#define QUIRK_TYPE_SMP 0b00000010
|
||||
#define QUIRK_TYPE_SMBIOS 0b00000100
|
||||
#define QUIRK_TYPE_SMBUS 0b00001000
|
||||
#define QUIRK_TYPE_TIMER 0b00010000
|
||||
|
||||
typedef enum {
|
||||
QUIRK_NONE,
|
||||
QUIRK_TUSL2
|
||||
} quirk_id_t;
|
||||
|
||||
typedef struct {
|
||||
quirk_id_t id;
|
||||
uint8_t type;
|
||||
uint16_t root_vid;
|
||||
uint16_t root_did;
|
||||
} quirk_t;
|
||||
|
||||
extern quirk_t quirk;
|
||||
|
||||
void quirks_init(void);
|
||||
|
||||
#endif /* _QUIRK_H_ */
|
24
system/pci.c
24
system/pci.c
@ -244,6 +244,30 @@ void pci_config_write32(int bus, int dev, int func, int reg, uint32_t value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------
|
||||
// LPC Functions
|
||||
// -------------
|
||||
|
||||
void lpc_outb(uint8_t cmd, uint8_t data)
|
||||
{
|
||||
outb(cmd, 0x2E);
|
||||
usleep(100);
|
||||
outb(data, 0x2F);
|
||||
usleep(100);
|
||||
}
|
||||
|
||||
uint8_t lpc_inb(uint8_t reg)
|
||||
{
|
||||
outb(reg, 0x2E);
|
||||
usleep(100);
|
||||
return inb(0x2F);
|
||||
}
|
||||
|
||||
// ---------------------------------------
|
||||
// AMD System Management Network Functions
|
||||
// ---------------------------------------
|
||||
|
||||
uint32_t amd_smn_read(uint32_t adr)
|
||||
{
|
||||
pci_config_write32(0, 0, 0, 0x60, adr);
|
||||
|
@ -60,6 +60,13 @@ void pci_config_write16(int bus, int dev, int func, int reg, uint16_t value);
|
||||
void pci_config_write32(int bus, int dev, int func, int reg, uint32_t value);
|
||||
|
||||
|
||||
/**
|
||||
* Basic LPC Functions
|
||||
*/
|
||||
|
||||
void lpc_outb(uint8_t cmd, uint8_t data);
|
||||
uint8_t lpc_inb(uint8_t reg);
|
||||
|
||||
/*
|
||||
* Add some SNM related function (S.DEMEULEMEESTER)
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user