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:
Sam Demeulemeester 2022-05-20 13:23:25 +02:00 committed by GitHub
parent d901f9e8a1
commit bc8235f50d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 146 additions and 0 deletions

View File

@ -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();

View File

@ -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 \

View File

@ -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
View 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
View 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_ */

View File

@ -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);

View File

@ -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)
*/