From 231da82b57187d8545c10d0321104ca30d7c11bd Mon Sep 17 00:00:00 2001 From: "Ronald G. Minnich" Date: Tue, 5 Aug 2003 21:46:36 +0000 Subject: [PATCH] E7505 --- src/mainboard/supermicro/x5dae/Config | 265 ++++++++++++++++++ src/mainboard/supermicro/x5dae/cmos.layout | 96 +++++++ src/mainboard/supermicro/x5dae/devices.c | 73 +++++ .../supermicro/x5dae/example-fallback.config | 104 +++++++ .../supermicro/x5dae/example-normal.config | 105 +++++++ src/mainboard/supermicro/x5dae/hardware.c | 25 ++ src/mainboard/supermicro/x5dae/irq_tables.c | 43 +++ src/mainboard/supermicro/x5dae/mainboard.c | 124 ++++++++ .../supermicro/x5dae/mainboard_raminit.inc | 1 + src/mainboard/supermicro/x5dae/mptable.c | 147 ++++++++++ .../supermicro/x5dae/pci_clk_reset.inc | 133 +++++++++ .../supermicro/x5dae/select_i2c_m1.inc | 17 ++ .../supermicro/x5dae/select_i2c_spd.inc | 17 ++ 13 files changed, 1150 insertions(+) create mode 100644 src/mainboard/supermicro/x5dae/Config create mode 100644 src/mainboard/supermicro/x5dae/cmos.layout create mode 100644 src/mainboard/supermicro/x5dae/devices.c create mode 100644 src/mainboard/supermicro/x5dae/example-fallback.config create mode 100644 src/mainboard/supermicro/x5dae/example-normal.config create mode 100644 src/mainboard/supermicro/x5dae/hardware.c create mode 100644 src/mainboard/supermicro/x5dae/irq_tables.c create mode 100644 src/mainboard/supermicro/x5dae/mainboard.c create mode 100644 src/mainboard/supermicro/x5dae/mainboard_raminit.inc create mode 100644 src/mainboard/supermicro/x5dae/mptable.c create mode 100644 src/mainboard/supermicro/x5dae/pci_clk_reset.inc create mode 100644 src/mainboard/supermicro/x5dae/select_i2c_m1.inc create mode 100644 src/mainboard/supermicro/x5dae/select_i2c_spd.inc diff --git a/src/mainboard/supermicro/x5dae/Config b/src/mainboard/supermicro/x5dae/Config new file mode 100644 index 0000000000..4ec4646e12 --- /dev/null +++ b/src/mainboard/supermicro/x5dae/Config @@ -0,0 +1,265 @@ + +## Set all of the defaults for an x86 architecture +## +arch i386 + +## +## Build our 16 bit and 32 bit linuxBIOS entry code +## +mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc +ldscript cpu/i386/entry16.lds +ldscript cpu/i386/entry32.lds + +## +## Build our reset vector (This is where linuxBIOS is entered) +## +mainboardinit cpu/i386/reset16.inc USE_FALLBACK_IMAGE +ldscript cpu/i386/reset16.lds USE_FALLBACK_IMAGE +mainboardinit cpu/i386/reset32.inc USE_NORMAL_IMAGE +ldscript cpu/i386/reset32.lds USE_NORMAL_IMAGE + +## +## Include an id string (For safe flashing) +## +mainboardinit arch/i386/lib/id.inc +ldscript arch/i386/lib/id.lds + +## This is the early phase of linuxBIOS startup +## Things are delicate and we test to see if we should +## failover to another image. +mainboardinit northbridge/intel/E7505/reset_test.inc +mainboardinit arch/i386/lib/noop_failover.inc USE_NORMAL_IMAGE +mainboardinit southbridge/intel/82801ca/cmos_failover.inc USE_FALLBACK_IMAGE +ldscript arch/i386/lib/failover.lds USE_FALLBACK_IMAGE + +### +### O.k. We aren't just an intermediary anymore! +### + +## +## Setup our mtrrs +## +mainboardinit cpu/i786/earlymtrr.inc + +## +## Setup the serial port +## +mainboardinit superio/winbond/w83627hf/setup_serial.inc +mainboardinit pc80/serial.inc +mainboardinit arch/i386/lib/console.inc +mainboardinit southbridge/intel/82801ca/watchdog_disable.inc + +## +## Reset pci clock for hardware bug work around +## +mainboardinit southbridge/intel/82801ca/smbus.inc +mainboardinit southbridge/intel/82801ca/smbus_write_block.inc +mainboardinit mainboard/supermicro/x5dpr/pci_clk_reset.inc + +## +## Smbus functions +## +mainboardinit southbridge/intel/82801ca/smbus_read_byte.inc +#mainboardinit southbridge/intel/82801ca/smbus_read_block.inc +#mainboardinit southbridge/intel/82801ca/smbus_print_block.inc +mainboardinit mainboard/supermicro/x5dpr/select_i2c_spd.inc + +## +## Setup RAM +## +mainboardinit ram/dump_northbridge.inc +#mainboardinit sdram/generic_dump_smbus.inc +mainboardinit sdram/generic_dump_spd.inc +mainboardinit mainboard/supermicro/x5dpr/mainboard_raminit.inc + +## +## Include the secondary Configuration files +## +northbridge intel/E7505 +southbridge intel/82801db +southbridge intel/82870 +nsuperio winbond/w83627hf com1={1} com2={1} floppy=1 lpt=1 keyboard=1 hwmonitor=1 +dir /src/pc80 +dir /src/superio/winbond/w83627hf +dir /src/ram/ +cpu p5 +cpu p6 +cpu i786 + +## +## Build the objects we have code for in this directory. +## +object mainboard.o +object devices.o +object mptable.o HAVE_MP_TABLE +object irq_tables.o HAVE_PIRQ_TABLE + + +### +### Build options +### + +## +## Number of consecutive times boot failures triggers a boot into fallback mode. +## +option MAX_REBOOT_CNT=8 + +## +## Location of the DIMM EEPROMS on the SMBUS +## This is fixed into a narrow range by the DIMM package standard. +## +option SMBUS_MEM_DEVICE_START=(0xa << 3) +option SMBUS_MEM_DEVICE_END=(SMBUS_MEM_DEVICE_START +3) +option SMBUS_MEM_DEVICE_INC=1 +option SMBUS_MEM_CHANNEL_OFF=4 + +## +## Customize our winbond superio chip for this motherboard +## +option SIO_BASE=0x2e +option SIO_SYSTEM_CLK_INPUT=SIO_SYSTEM_CLK_INPUT_48MHZ + +## +## Build code for the fallback boot +## +option HAVE_FALLBACK_BOOT=1 + +## +## Build code for using cache as RAM +## +#option USE_CACHE_RAM=0 + +## +## Delay timer options +## +option CONFIG_UDELAY_TSC=1 +option CONFIG_TSC_X86RDTSC_CALIBRATE_WITH_TIMER2=1 + +## +## Build code to reset the motherboard from linuxBIOS +## +option HAVE_HARD_RESET=1 + +## +## Build code to export a programmable irq routing table +## +option HAVE_PIRQ_TABLE=1 + + +## +## Do not build special code to the keyboard +## +option NO_KEYBOARD=1 + +## +## Build code to export an x86 MP table +## Useful for specifying IRQ routing values +## +option HAVE_MP_TABLE=1 + +## +## Build code to export a CMOS option tabe table +## +option HAVE_OPTION_TABLE=1 + +## +## Build code for SMP support +## Only worry about 2 micro processors +## +option SMP=1 +option MAX_CPUS=4 +option MAX_PHYSICAL_CPUS=2 + +## +## Build code to setup a generic IOAPIC +## +option IOAPIC=1 + +## +## MEMORY_HOLE instructs earlymtrr.inc to +## enable caching from 0-640KB and to disable +## caching from 640KB-1MB using fixed MTRRs +## +## Enabling this option breaks SMP because secondary +## CPU identification depends on only variable MTRRs +## being enabled. +## +nooption MEMORY_HOLE + +## +## Figure out which type of linuxBIOS image to build +## If we aren't a fallback image we must be a normal image +## This is useful for optional includes +## +option USE_FALLBACK_IMAGE=0 +expr USE_NORMAL_IMAGE=!USE_FALLBACK_IMAGE + +### +### LinuxBIOS layout values +### + +## ROM_SIZE is the size of boot ROM that this board will use. +option ROM_SIZE=524288 + +## ROM_IMAGE_SIZE is the amount of space to allow linuxBIOS to occupy. +option ROM_IMAGE_SIZE=49152 + +## LinuxBIOS C code runs at this location in RAM +option _RAMBASE=0x00008000 + +## For the trick of using cache as ram +## put the fake ram location at this address +option CACHE_RAM_BASE=0xfff70000 +option CACHE_RAM_SIZE=0x00010000 + +## +## Use a small 8K stack +## +option STACK_SIZE=0x2000 + +## +## Use a small 8K heap +## +option HEAP_SIZE=0x2000 + +## +## Clean up the motherboard id strings +## +option MAINBOARD_PART_NUMBER=X5DPR +option MAINBOARD_VENDOR=Supermicro + +option UPDATE_MICROCODE=1 +option CPU_FIXUP=1 + +## +## Only use the option table in a normal image +## +expr USE_OPTION_TABLE=!USE_FALLBACK_IMAGE + +## +## Compute the location and size of where this firmware image +## (linuxBIOS plus bootloader) will live in the boot rom chip. +## +expr ROM_SECTION_SIZE =(USE_FALLBACK_IMAGE*65536)+(USE_NORMAL_IMAGE*(ROM_SIZE - 65536)) +expr ROM_SECTION_OFFSET=(USE_FALLBACK_IMAGE*(ROM_SIZE-65536))+(USE_NORMAL_IMAGE*0) + + +## +## Compute the start location and size size of +## The linuxBIOS bootloader. +## +expr ZKERNEL_START =(0xffffffff - ROM_SIZE + ROM_SECTION_OFFSET + 1) +expr PAYLOAD_SIZE =ROM_SECTION_SIZE - ROM_IMAGE_SIZE + +## +## Compute where this copy of linuxBIOS will start in the boot rom +## +expr _ROMBASE =ZKERNEL_START + PAYLOAD_SIZE + +## +## Compute a range of ROM that can cached to speed of linuxBIOS, +## execution speed. +## +expr XIP_ROM_SIZE = 65536 +expr XIP_ROM_BASE = _ROMBASE + ROM_IMAGE_SIZE - XIP_ROM_SIZE diff --git a/src/mainboard/supermicro/x5dae/cmos.layout b/src/mainboard/supermicro/x5dae/cmos.layout new file mode 100644 index 0000000000..7c9c1655b6 --- /dev/null +++ b/src/mainboard/supermicro/x5dae/cmos.layout @@ -0,0 +1,96 @@ +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +#96 288 r 0 temporary_filler +0 384 r 0 reserved_memory +384 1 e 4 boot_option +385 1 e 4 last_boot +386 1 e 1 ECC_memory +388 4 r 0 reboot_bits +392 3 e 5 baud_rate +395 1 e 2 hyper_threading +396 1 e 1 thermal_monitoring +397 1 e 1 remap_memory_high +400 1 e 1 power_on_after_fail +#402 1 e 2 hda_disk +#403 1 e 2 hdb_disk +#404 1 e 2 hdc_disk +#405 1 e 2 hdd_disk +#408 4 e 9 CPU_clock_speed +412 4 e 6 debug_level +416 4 e 7 boot_first +420 4 e 7 boot_second +424 4 e 7 boot_third +428 4 h 0 boot_index +432 8 h 0 boot_countdown +1008 16 h 0 check_sum + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 FallBack +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Network +7 1 HDD +7 2 Floppy +7 8 Fallback_Network +7 9 Fallback_HDD +7 10 Fallback_Floppy +#7 3 ROM +#9 15 800MHZ +#9 11 900MHZ +#9 13 1GHZ +#9 9 1.1GHZ +#9 14 1.2GHZ +#9 10 1.3GHZ +#9 12 1.4GHZ +#9 8 1.5GHZ +#9 7 1.6GHZ +#9 3 1.7GHZ +#9 5 1.8GHZ +#9 1 1.9GHZ +#9 6 2.0GHZ +#9 2 2.1GHZ +#9 4 2.2GHZ +#9 0 2.3GHZ + +checksums + +checksum 392 1007 1008 diff --git a/src/mainboard/supermicro/x5dae/devices.c b/src/mainboard/supermicro/x5dae/devices.c new file mode 100644 index 0000000000..7be2f80294 --- /dev/null +++ b/src/mainboard/supermicro/x5dae/devices.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +struct cdev { + unsigned int devfn; + struct cdev *next; + struct cdev *children; + void *private; +}; +static struct cdev nodev; + +#define DEV(NAME, DEVICE, FUNCTION, NEXT, CHILDREN, PRIVATE) \ +static struct cdev NEXT; \ +static struct cdev CHILDREN; \ +static struct cdev NAME = { \ + .devfn = PCI_DEVFN(DEVICE, FUNCTION), \ + .next = &NEXT, \ + .children = &CHILDREN, \ + .private = PRIVATE, \ +} + +DEV(dev0_2_0, 0x02, 0, dev0_1f_0, dev1_1c_0, 0); +DEV(dev0_1f_0, 0x1f, 0, nodev, nodev, 0); +DEV(dev1_1c_0, 0x1c, 0, dev1_1e_0, nodev, 0); +DEV(dev1_1e_0, 0x1e, 0, nodev, nodev, 0); + +static void add_dev_list(struct pci_dev *bus, struct cdev *dev); + +static void add_device(struct pci_dev *bus, struct cdev *dev) +{ + struct pci_dev *pdev; + +#if 0 + printk_debug("Adding%s %02x.%01x\n", + (dev->children == &nodev)?"":" bus", + PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); +#endif + + pdev = malloc(sizeof(*pdev)); + if (!pdev) + goto no_mem; + + memset(pdev, 0, sizeof(*pdev)); + pdev->bus = bus; + pdev->devfn = dev->devfn; + + /* Add to the list of devices on the parent bus. */ + pdev->sibling = bus->children; + bus->children = pdev; + + /* Add any children we might have */ + add_dev_list(pdev, dev->children); + return; + no_mem: + printk_err("PCI: out of memory.\n"); + return; +} + +static void add_dev_list(struct pci_dev *bus, struct cdev *dev) +{ + while(dev != &nodev) { + add_device(bus, dev); + dev = dev->next; + } +} +void enumerate_static_devices(void) +{ + struct cdev *dev = &dev0_2_0; + add_dev_list(&pci_root, dev); +} diff --git a/src/mainboard/supermicro/x5dae/example-fallback.config b/src/mainboard/supermicro/x5dae/example-fallback.config new file mode 100644 index 0000000000..5b495b14e8 --- /dev/null +++ b/src/mainboard/supermicro/x5dae/example-fallback.config @@ -0,0 +1,104 @@ +## This will make a target directory of ./fallback +## This is relative to where the configuration file resides in the filesystem +target ./fallback + +mainboard supermicro/x5dpr + +## Build a fallback not a normal image. +option USE_FALLBACK_IMAGE=1 + +## Build an image for a 512KB rom +## ./fallback/romimage is just the last 64KB which we reserve for the fallback image. +option ROM_SIZE=524288 +#option ROM_SIZE=1048576 + +## Select the maximum size the linuxBIOS code can compile to. +## Allow linuxBIOS to be up to 48KB in size +option ROM_IMAGE_SIZE=49152 + + +## +### The Serial Console +## +## Hardware flow control is currently ignored. + +## Enable the Serial Console +option SERIAL_CONSOLE=1 + +## Select the serial console baud rate. +option TTYS0_BAUD=115200 +#option TTYS0_BAUD=57600 +#option TTYS0_BAUD=38400 +#option TTYS0_BAUD=19200 +#option TTYS0_BAUD=9600 +#option TTYS0_BAUD=4800 +#option TTYS0_BAUD=2400 +#option TTYS0_BAUD=1200 + +# Select the serial console base port +option TTYS0_BASE=0x3f8 + +# Select the serial protocol +# This defaults to 8 data bits, 1 stop bit, and no parity +option TTYS0_LCS=0x3 + + +## +### Select the linuxBIOS loglevel +## +## EMERG 1 system is unusable +## ALERT 2 action must be taken immediately +## CRIT 3 critical conditions +## ERR 4 error conditions +## WARNING 5 warning conditions +## NOTICE 6 normal but significant condition +## INFO 7 informational +## DEBUG 8 debug-level messages +## SPEW 9 Way too many details + +## Request this level of debugging output +option DEFAULT_CONSOLE_LOGLEVEL=9 +## At a maximum only compile in this level of debugging +option MAXIMUM_CONSOLE_LOGLEVEL=6 + +## Use the elf bootloader +option USE_ELF_BOOT=1 + +## Select the boot device +option USE_GENERIC_ROM=1 +#option BOOT_FLOPPY=1 +#option USE_SERIAL_FILL_INBUF=1 +#option BOOT_IDE=1 + +# Load etherboot with the elf bootloader +# The payload command is relative the build directory +# So .. is the directory this config file resides in +payload ../eepro100.ebi + + +## +## Cpu Speed +## +option CPU_CLOCK_MULTIPLIER=XEON_X8 +#option CPU_CLOCK_MULTIPLIER=XEON_X9 +#option CPU_CLOCK_MULTIPLIER=XEON_X10 +#option CPU_CLOCK_MULTIPLIER=XEON_X11 +#option CPU_CLOCK_MULTIPLIER=XEON_X12 +#option CPU_CLOCK_MULTIPLIER=XEON_X13 +#option CPU_CLOCK_MULTIPLIER=XEON_X14 +#option CPU_CLOCK_MULTIPLIER=XEON_X15 +#option CPU_CLOCK_MULTIPLIER=XEON_X16 +#option CPU_CLOCK_MULTIPLIER=XEON_X17 +#option CPU_CLOCK_MULTIPLIER=XEON_X18 +#option CPU_CLOCK_MULTIPLIER=XEON_X19 +#option CPU_CLOCK_MULTIPLIER=XEON_X19 +#option CPU_CLOCK_MULTIPLIER=XEON_X20 +#option CPU_CLOCK_MULTIPLIER=XEON_X21 +#option CPU_CLOCK_MULTIPLIER=XEON_X22 +#option CPU_CLOCK_MULTIPLIER=XEON_X23 + +## +## Select power on after power fail setting +option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON +#option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON + diff --git a/src/mainboard/supermicro/x5dae/example-normal.config b/src/mainboard/supermicro/x5dae/example-normal.config new file mode 100644 index 0000000000..ed7037abb1 --- /dev/null +++ b/src/mainboard/supermicro/x5dae/example-normal.config @@ -0,0 +1,105 @@ +## This will make a target directory of ./normal +## This is relative to where the configuration file resides in the filesystem +target ./normal + +mainboard supermicro/x5dpr + +## Build a normal not a fallback image. +option USE_FALLBACK_IMAGE=0 + +## Build an image for a 512KB rom +## ./normal/romimage is the entire rom image except for the last 64KB +## which are reserved for the fallback image. +option ROM_SIZE=524288 +#option ROM_SIZE=1048576 + +## Select the maximum size the linuxBIOS code can compile to. +## Allow linuxBIOS to be up to 48KB in size +option ROM_IMAGE_SIZE=49152 + + +## +### The Serial Console +## +## Hardware flow control is currently ignored. + +## Enable the Serial Console +option SERIAL_CONSOLE=1 + +## Select the serial console baud rate. +option TTYS0_BAUD=115200 +#option TTYS0_BAUD=57600 +#option TTYS0_BAUD=38400 +#option TTYS0_BAUD=19200 +#option TTYS0_BAUD=9600 +#option TTYS0_BAUD=4800 +#option TTYS0_BAUD=2400 +#option TTYS0_BAUD=1200 + +# Select the serial console base port +option TTYS0_BASE=0x3f8 + +# Select the serial protocol +# This defaults to 8 data bits, 1 stop bit, and no parity +option TTYS0_LCS=0x3 + + +## +### Select the linuxBIOS loglevel +## +## EMERG 1 system is unusable +## ALERT 2 action must be taken immediately +## CRIT 3 critical conditions +## ERR 4 error conditions +## WARNING 5 warning conditions +## NOTICE 6 normal but significant condition +## INFO 7 informational +## DEBUG 8 debug-level messages +## SPEW 9 Way too many details + +## Request this level of debugging output +option DEFAULT_CONSOLE_LOGLEVEL=9 +## At a maximum only compile in this level of debugging +option MAXIMUM_CONSOLE_LOGLEVEL=8 + +## Use the elf bootloader +option USE_ELF_BOOT=1 + +## Select the boot device +option USE_GENERIC_ROM=1 +#option BOOT_FLOPPY=1 +#option USE_SERIAL_FILL_INBUF=1 +#option BOOT_IDE=1 + +# Load etherboot with the elf bootloader +# The payload command is relative the build directory +# So .. is the directory this config file resides in +payload ../eepro100.ebi + + +## +## Cpu Speed +## +#option CPU_CLOCK_MULTIPLIER=XEON_X8 +#option CPU_CLOCK_MULTIPLIER=XEON_X9 +#option CPU_CLOCK_MULTIPLIER=XEON_X10 +#option CPU_CLOCK_MULTIPLIER=XEON_X11 +#option CPU_CLOCK_MULTIPLIER=XEON_X12 +#option CPU_CLOCK_MULTIPLIER=XEON_X13 +#option CPU_CLOCK_MULTIPLIER=XEON_X14 +#option CPU_CLOCK_MULTIPLIER=XEON_X15 +#option CPU_CLOCK_MULTIPLIER=XEON_X16 +option CPU_CLOCK_MULTIPLIER=XEON_X17 +#option CPU_CLOCK_MULTIPLIER=XEON_X18 +#option CPU_CLOCK_MULTIPLIER=XEON_X19 +#option CPU_CLOCK_MULTIPLIER=XEON_X19 +#option CPU_CLOCK_MULTIPLIER=XEON_X20 +#option CPU_CLOCK_MULTIPLIER=XEON_X21 +#option CPU_CLOCK_MULTIPLIER=XEON_X22 +#option CPU_CLOCK_MULTIPLIER=XEON_X23 + +## +## Select power on after power fail setting +option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON +#option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON + diff --git a/src/mainboard/supermicro/x5dae/hardware.c b/src/mainboard/supermicro/x5dae/hardware.c new file mode 100644 index 0000000000..541732acd7 --- /dev/null +++ b/src/mainboard/supermicro/x5dae/hardware.c @@ -0,0 +1,25 @@ +#include +#include + +struct pci_bus pci_root = { + .children = &bus1; +}; +struct pci_dev dev0_2_0 = { + .bus = &pci_root, + .devfn = PCI_DEVFN(2,0), +}; +struct pci_bus bus1 = { + .parent = &pci_root, + .self = &dev0_2_0, +}; +struct pci_dev dev1_1c_0 = { + .bus = &bus1, + .devfn = PCI_DEVFN(0x1c, 0), + /* Hang ioapic information off of here */ +}; +struct pci_dev dev1_1e_0 = { + .bus = &bus1, + .devfn = PCI_DEVFN(0x1e, 0), + /* Hang ioapic information off of here */ +}; + diff --git a/src/mainboard/supermicro/x5dae/irq_tables.c b/src/mainboard/supermicro/x5dae/irq_tables.c new file mode 100644 index 0000000000..0c23b742a9 --- /dev/null +++ b/src/mainboard/supermicro/x5dae/irq_tables.c @@ -0,0 +1,43 @@ +/* PCI: Interrupt Routing Table found at 0x4011ce40 size = 416 */ + +#include + +const struct irq_routing_table intel_irq_routing_table = { + 0x52495024, /* u32 signature */ + 0x0100, /* u16 version */ + 416, /* u16 Table size 32+(16*devices) */ + 0x00, /* u8 Bus 0 */ + 0xf8, /* u8 Device 1, Function 0 */ + 0x0000, /* u16 reserve IRQ for PCI */ + 0x8086, /* u16 Vendor */ + 0x122e, /* Device ID */ + 0x00000000, /* u32 miniport_data */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */ + 0x94, /* u8 checksum - mod 256 checksum must give zero */ + { /* bus, devfn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */ + {0x00, 0x00, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x00, 0x10, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x01, 0xe8, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x02, 0x08, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x01, 0x00}, + {0x02, 0x18, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x0a, 0x00}, + {0x02, 0x10, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x03, 0x00}, + {0x01, 0xf8, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x03, 0x08, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x02, 0x00}, + {0x03, 0x10, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x05, 0x00}, + {0x03, 0x18, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x06, 0x00}, + {0x03, 0x20, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x0b, 0x00}, + {0x00, 0x20, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x10, 0xe8, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x11, 0x08, {{0x63, 0xdcb8}, {0x63, 0xdcb8}, {0x63, 0xdcb8}, {0x63, 0xdcb8}}, 0x03, 0x00}, + {0x10, 0xf8, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x12, 0x08, {{0x63, 0xdcb8}, {0x63, 0xdcb8}, {0x63, 0xdcb8}, {0x63, 0xdcb8}}, 0x04, 0x00}, + {0x00, 0xf0, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x04, 0x08, {{0x60, 0xdcb8}, {0x60, 0xdcb8}, {0x60, 0xdcb8}, {0x60, 0xdcb8}}, 0x07, 0x00}, + {0x04, 0x10, {{0x61, 0xdcb8}, {0x61, 0xdcb8}, {0x61, 0xdcb8}, {0x61, 0xdcb8}}, 0x08, 0x00}, + {0x04, 0x18, {{0x62, 0xdcb8}, {0x62, 0xdcb8}, {0x62, 0xdcb8}, {0x62, 0xdcb8}}, 0x09, 0x00}, + {0x00, 0xe8, {{0x60, 0xdcb8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x00, 0xe9, {{0x00, 0xdef8}, {0x63, 0xdcb8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x00, 0xea, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x62, 0xdcb8}, {0x00, 0xdef8}}, 0x00, 0x00}, + {0x00, 0xf8, {{0x62, 0xdcb8}, {0x61, 0xdcb8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00} + } +}; diff --git a/src/mainboard/supermicro/x5dae/mainboard.c b/src/mainboard/supermicro/x5dae/mainboard.c new file mode 100644 index 0000000000..f9362956dd --- /dev/null +++ b/src/mainboard/supermicro/x5dae/mainboard.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +unsigned long initial_apicid[MAX_CPUS] = +{ + 0, 6, 1, 7 +}; + +#ifndef CPU_CLOCK_MULTIPLIER +#define CPU_CLOCK_MULTIPLIER XEON_X17 +#endif + +#define MAINBOARD_POWER_OFF 0 +#define MAINBOARD_POWER_ON 1 + +#ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL +#define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON +#endif + +static void set_power_on_after_power_fail(int setting) +{ + switch(setting) { + case MAINBOARD_POWER_ON: + default: + ich3_power_after_power_fail(1); + w83627hf_power_after_power_fail(POWER_ON); + break; + case MAINBOARD_POWER_OFF: + ich3_power_after_power_fail(0); + w83627hf_power_after_power_fail(POWER_OFF); + break; + + } +} + +static void set_thermal_monitoring(int thermal_monitoring) +{ + int tm_high,tm_low; + + rdmsr(MISC_ENABLE,tm_low,tm_high); + if(thermal_monitoring != THERMAL_MONITORING_OFF) { + tm_low |= THERMAL_MONITORING_SET; + } + else { + tm_low &= ~THERMAL_MONITORING_SET; + } + wrmsr(MISC_ENABLE,tm_low,tm_high); + return; +} + +static void enable_perr_serr(void) +{ +#if 0 + uint8_t data61,data70,data74; + data61=inb(0x61); + data70=inb(0x70); + data74=inb(0x74); + printk_debug("Temp Test 70 = %x, 74 = %x, 61 = %x\n",data70,data74, + data61); +#endif + return; +} +void mainboard_fixup(void) +{ + int cpu_clock_multiplier; + int power_on_after_power_fail; + int thermal_monitoring; + + w83627hf_power_led(LED_ON); + ich3_enable_ioapic(); + p64h2_enable_ioapic(); + p64h2_setup_pcibridge(); + ich3_enable_serial_irqs(); + ich3_enable_ide(1,1); + ich3_rtc_init(); + ich3_lpc_route_dma(0xff); + isa_dma_init(); + ich3_1e0_misc(); + ich3_1f0_misc(); + +#if 0 /* CPU clock option is not presently used */ + cpu_clock_multiplier = CPU_CLOCK_MULTIPLIER; + if(get_option(&cpu_clock_multiplier, "CPU_clock_speed")) + cpu_clock_multiplier = CPU_CLOCK_MULTIPLIER; + ich3_set_cpu_multiplier(cpu_clock_multiplier); +#endif + + power_on_after_power_fail = MAINBOARD_POWER_ON_AFTER_POWER_FAIL; + if(get_option(&power_on_after_power_fail, "power_on_after_fail")) + power_on_after_power_fail = MAINBOARD_POWER_ON_AFTER_POWER_FAIL; + set_power_on_after_power_fail(power_on_after_power_fail); + + thermal_monitoring = THERMAL_MONITORING_OFF; + if(get_option(&thermal_monitoring, "thermal_monitoring")) + thermal_monitoring = THERMAL_MONITORING_OFF; + set_thermal_monitoring(thermal_monitoring); + + enable_perr_serr(); + + return; +} + +void hard_reset(void) +{ + ich3_hard_reset(); +} + diff --git a/src/mainboard/supermicro/x5dae/mainboard_raminit.inc b/src/mainboard/supermicro/x5dae/mainboard_raminit.inc new file mode 100644 index 0000000000..8d1c8b69c3 --- /dev/null +++ b/src/mainboard/supermicro/x5dae/mainboard_raminit.inc @@ -0,0 +1 @@ + diff --git a/src/mainboard/supermicro/x5dae/mptable.c b/src/mainboard/supermicro/x5dae/mptable.c new file mode 100644 index 0000000000..ef6e9b10b8 --- /dev/null +++ b/src/mainboard/supermicro/x5dae/mptable.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include + +void *smp_write_config_table(void *v, unsigned long * processor_map) +{ + static const char sig[4] = "PCMP"; + static const char oem[8] = "LNXI "; + static const char productid[12] = "X5DPR "; + struct mp_config_table *mc; + + mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN); + memset(mc, 0, sizeof(*mc)); + + memcpy(mc->mpc_signature, sig, sizeof(sig)); + mc->mpc_length = sizeof(*mc); /* initially just the header */ + mc->mpc_spec = 0x04; + mc->mpc_checksum = 0; /* not yet computed */ + memcpy(mc->mpc_oem, oem, sizeof(oem)); + memcpy(mc->mpc_productid, productid, sizeof(productid)); + mc->mpc_oemptr = 0; + mc->mpc_oemsize = 0; + mc->mpc_entry_count = 0; /* No entries yet... */ + mc->mpc_lapic = LAPIC_ADDR; + mc->mpe_length = 0; + mc->mpe_checksum = 0; + mc->reserved = 0; + + smp_write_processors(mc, processor_map); + + smp_write_bus(mc, 0, "PCI "); + smp_write_bus(mc, 1, "PCI "); + smp_write_bus(mc, 2, "PCI "); + smp_write_bus(mc, 3, "PCI "); + smp_write_bus(mc, 4, "PCI "); + smp_write_bus(mc, 5, "ISA "); + + /* FIXME better IOAPIC handling */ + + smp_write_ioapic(mc, 2, 0x20, 0xfec00000); + { + struct pci_dev *dev; + uint32_t base; + /* 1:1e.0 */ + dev = pci_find_slot(1, PCI_DEVFN(0x1e,0)); + if (dev) { + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &base); + base &= PCI_BASE_ADDRESS_MEM_MASK; + smp_write_ioapic(mc, 3, 0x20, base); + } + /* 1:1c.0 */ + dev = pci_find_slot(1, PCI_DEVFN(0x1c,0)); + if (dev) { + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &base); + base &= PCI_BASE_ADDRESS_MEM_MASK; + smp_write_ioapic(mc, 4, 0x20, base); + } + } + + /* ISA backward compatibility interrupts */ + smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x00, 0x02, 0x00); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x01, 0x02, 0x01); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x00, 0x02, 0x02); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x03, 0x02, 0x03); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x04, 0x02, 0x04); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x05, 0x02, 0x05); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x06, 0x02, 0x06); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x07, 0x02, 0x07); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x08, 0x02, 0x08); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x09, 0x02, 0x09); + + /* USB Controller */ + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x00, (0x1d<<2)|1, 0x02, 0x13); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x00, (0x1d<<2)|0, 0x02, 0x10); + + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x06, 0x0c, 0x02, 0x0c); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x0d, 0x02, 0x0d); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x0e, 0x02, 0x0e); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x0f, 0x02, 0x0f); + + /* USB Controller */ + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x00, (0x1d<<2)|2, 0x02, 0x12); + + /* Onboard 82559 Ethernet */ + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x02, (0x3<<2)|0, 0x04, 0x06); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x02, (0x3<<2)|1, 0x04, 0x07); + + /* PCI slot 1 */ + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x03, (1<<2)|0, 0x03, 0x00); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x03, (1<<2)|1, 0x03, 0x01); + + /* Slot 2 */ + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x02, (1<<2)|0, 0x04, 0x00); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x02, (1<<2)|1, 0x04, 0x01); + + /* VGA */ + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, + 0x04, (1<<2)|0, 0x02, 0x10); + + /* Standard local interrupt assignments */ + smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x00, MP_APIC_ALL, 0x00); + smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, + 0x05, 0x00, MP_APIC_ALL, 0x01); + + /* There is no extension information... */ + + /* Compute the checksums */ + mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length); + mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length); + printk_debug("Wrote the mp table end at: %p - %p\n", + mc, smp_next_mpe_entry(mc)); + return smp_next_mpe_entry(mc); +} + +unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map) +{ + void *v; + v = smp_write_floating_table(addr); + return (unsigned long)smp_write_config_table(v, processor_map); +} + diff --git a/src/mainboard/supermicro/x5dae/pci_clk_reset.inc b/src/mainboard/supermicro/x5dae/pci_clk_reset.inc new file mode 100644 index 0000000000..fdba672d9a --- /dev/null +++ b/src/mainboard/supermicro/x5dae/pci_clk_reset.inc @@ -0,0 +1,133 @@ +/* The algorithm is as follows: + */ +#include +#include + + +#define PM_DEVFN ((0x1f <<3) + 0) + + .section ".rom.data" + +pci_clk_stop_beg: + .byte 0x08, 0x47, 0x7f, 0xc7, 0x38 +pci_clk_stop_end: + +pci_clk_start_beg: + .byte 0x08, 0x47, 0x7f, 0xc7, 0x3f +pci_clk_start_end: + +pci_clk_restart_msg: + .asciz "Restarting pci clocks\r\n" +pci_clk_power_msg: + .asciz "Power failed\r\n" + + .previous + + /* The PC64H2 has a known errata where there is a race + * between getting a good level, and getting a clock signal. + * Nasting things normally boot failure while readding the pci + * bus happen when this errata is hit. + * + * Thw work around is to stop and restart the 66Mhz reference clock + * the PC64H2. And to do this I need to talk to the reference clock + * generator in this case a cypress CY28329. + * + * The I2C interface on the Cyrpess chip is fragile. If you talk + * to it wrong or if you talk to it long enough after getting power, + * it will not talk to you. So I have to be very careful. What is + * especially bad is that sometimes a failed attempt to talk + * to the Cypress chip will lock the i2c/smbus controller on + * the ICH3. So I cannot talk to i2c EEPROM on memory dimms + * to detect how much memory I have. + * + * Placing the motherboard in soft power off is not enough to get the + * cypress chip talking again. So I only attempt the PC64H2 + * errata work around when I boot up immediate after the + * motherboard has lost power. + * + * This procedure appears to navigate the cascading mines of + * the hardware bugs. + */ +__reboot_ck: + /* See if power is failed, making it is safe to talk to the + * cypress chip. + */ + movl $((PM_DEVFN << 8) + 0xA4), %eax + PCI_READ_CONFIG_DWORD + + /* If power has not failed get, skip the errata work around */ + testl $(1 << 1), %eax + jz __continue_booting + + /* Clear the power failed bit, so I don't apply this + * work around when it is not safe. + */ + movl $((PM_DEVFN << 8) + 0xA4), %eax + movl $(1 << 1), %ecx + PCI_WRITE_CONFIG_DWORD + + /* Report that I have detected a power failure */ + CONSOLE_INFO_TX_STRING($pci_clk_power_msg) + + /* Attempt to write to the cypress chip and bail out if this + * fails. + */ + /* stop the clocks */ + movb $0x69, %bl + movb $0x00, %bh + movb $(pci_clk_stop_end - pci_clk_stop_beg), %cl + movl $(pci_clk_stop_beg), %esi + /* stop the pci clock */ + CALLSP(smbus_write_block) + jc __continue_booting + + /* wait for about 100us */ + movl $0x2c, %ecx + rdmsr + andl $0xff000000,%eax + shrl $10, %eax /* this gives the ticks for 160usec */ + movl %eax, %ebx + rdtsc + addl %ebx, %eax + adcl $0, %edx + movl %eax, %ebx + movl %edx, %ecx +1: rdtsc + subl %ebx, %eax + sbbl %ecx, %edx + jb 1b + + /* Add an extra delay to display this message */ + CONSOLE_INFO_TX_STRING($pci_clk_restart_msg) + + /* restart the clocks */ + movb $0x69, %bl + movb $0x00, %bh + movb $(pci_clk_start_end - pci_clk_start_beg), %cl + movl $(pci_clk_start_beg), %esi + /* start the pci clock */ + CALLSP(smbus_write_block) + + /* Set boot_option to last_boot, so I don't fallback by accident */ + movb $RTC_BOOT_BYTE, %al + outb %al, $0x70 + inb $0x71, %al + movb %al, %bl + shrb $1, %bl + andb $1, %bl + andb $0xfe, %al + orb %bl, %al + outb %al, $0x71 + + /* reboot the motherboard */ + movw $0x0cf9, %dx + inb %dx, %al + andb $~((1 <<3)|(1<<2)), %al + orb $(1<<1), %al + outb %al, %dx + orb $(1<<2), %al + outb %al, %dx +2: hlt + jmp 2b + +__continue_booting: diff --git a/src/mainboard/supermicro/x5dae/select_i2c_m1.inc b/src/mainboard/supermicro/x5dae/select_i2c_m1.inc new file mode 100644 index 0000000000..fd78933f5d --- /dev/null +++ b/src/mainboard/supermicro/x5dae/select_i2c_m1.inc @@ -0,0 +1,17 @@ + SIO_ENTER_PNP_MODE() + + SIO_READ_CONFIG($0x2b) + movb %al, %bl + orb $0x30, %bl + SIO_WRITE_CONFIG(%bl, $0x2b) + + /* Enable the GPIO device */ + SIO_SET_LOGICAL_DEVICE($GPIO_PORT2_DEVICE) + SIO_WRITE_CONFIG($1, $0x30) + + SIO_READ_CONFIG($0xf0) + movb %al, %bl + orb $(1 << 3), %bl + SIO_WRITE_CONFIG(%bl, $0xf0) + + SIO_EXIT_PNP_MODE() diff --git a/src/mainboard/supermicro/x5dae/select_i2c_spd.inc b/src/mainboard/supermicro/x5dae/select_i2c_spd.inc new file mode 100644 index 0000000000..ffe5557d4b --- /dev/null +++ b/src/mainboard/supermicro/x5dae/select_i2c_spd.inc @@ -0,0 +1,17 @@ + SIO_ENTER_PNP_MODE() + + SIO_READ_CONFIG($0x2b) + movb %al, %bl + orb $0x30, %bl + SIO_WRITE_CONFIG(%bl, $0x2b) + + /* Enable the GPIO device */ + SIO_SET_LOGICAL_DEVICE($GPIO_PORT2_DEVICE) + SIO_WRITE_CONFIG($1, $0x30) + + SIO_READ_CONFIG($0xf0) + movb %al, %bl + andb $~(1 << 3), %bl + SIO_WRITE_CONFIG(%bl, $0xf0) + + SIO_EXIT_PNP_MODE()