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 "cpuid.h"
|
||||||
#include "cpuinfo.h"
|
#include "cpuinfo.h"
|
||||||
#include "hwctrl.h"
|
#include "hwctrl.h"
|
||||||
|
#include "hwquirks.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "pmem.h"
|
#include "pmem.h"
|
||||||
|
@ -219,6 +220,8 @@ static void global_init(void)
|
||||||
|
|
||||||
smbios_init();
|
smbios_init();
|
||||||
|
|
||||||
|
quirks_init();
|
||||||
|
|
||||||
badram_init();
|
badram_init();
|
||||||
|
|
||||||
config_init();
|
config_init();
|
||||||
|
|
|
@ -20,6 +20,7 @@ SYS_OBJS = system/cpuid.o \
|
||||||
system/ehci.o \
|
system/ehci.o \
|
||||||
system/font.o \
|
system/font.o \
|
||||||
system/hwctrl.o \
|
system/hwctrl.o \
|
||||||
|
system/hwquirks.o \
|
||||||
system/keyboard.o \
|
system/keyboard.o \
|
||||||
system/ohci.o \
|
system/ohci.o \
|
||||||
system/pci.o \
|
system/pci.o \
|
||||||
|
|
|
@ -20,6 +20,7 @@ SYS_OBJS = system/cpuid.o \
|
||||||
system/ehci.o \
|
system/ehci.o \
|
||||||
system/font.o \
|
system/font.o \
|
||||||
system/hwctrl.o \
|
system/hwctrl.o \
|
||||||
|
system/hwquirks.o \
|
||||||
system/keyboard.o \
|
system/keyboard.o \
|
||||||
system/ohci.o \
|
system/ohci.o \
|
||||||
system/pci.o \
|
system/pci.o \
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
uint32_t amd_smn_read(uint32_t adr)
|
||||||
{
|
{
|
||||||
pci_config_write32(0, 0, 0, 0x60, 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);
|
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)
|
* Add some SNM related function (S.DEMEULEMEESTER)
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue