mail.coreboot.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
List overview
Download
coreboot-gerrit
May 2014
----- 2024 -----
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
coreboot-gerrit@coreboot.org
1 participants
1066 discussions
Start a n
N
ew thread
Patch set updated for coreboot: d0479e0 i915_reg: Declare LVDS register values.
by Vladimir Serbinenko
01 Jun '14
01 Jun '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5319
-gerrit commit d0479e0e0e3694c60acc414a6aba899b265180a0 Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sun Mar 2 17:45:09 2014 +0100 i915_reg: Declare LVDS register values. Change-Id: If8b3578c4fa31bf9f09c0053a5cac7ebc993b634 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- 3rdparty | 2 +- src/drivers/intel/gma/i915_reg.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/3rdparty b/3rdparty index 324ec3c..45f0c04 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit 324ec3cb642a278d6d97ae809bc6098045bc6e65 +Subproject commit 45f0c04fd788fb29d9e303b2b2d1657ddb03448a diff --git a/src/drivers/intel/gma/i915_reg.h b/src/drivers/intel/gma/i915_reg.h index 155df4d..cbb0628 100644 --- a/src/drivers/intel/gma/i915_reg.h +++ b/src/drivers/intel/gma/i915_reg.h @@ -959,6 +959,11 @@ #define DVOC_ON (1<<31) #define LVDS 0x61180 #define LVDS_ON (1<<31) +#define LVDS_CLOCK_A_POWERUP_ALL (3 << 8) +#define LVDS_CLOCK_B_POWERUP_ALL (3 << 4) +#define LVDS_CLOCK_BOTH_POWERUP_ALL (3 << 2) +#define LVDS_BORDER_ENABLE (1 << 15) +#define LVDS_DETECTED (1 << 1) /* Scratch pad debug 0 reg: */
1
0
0
0
Patch set updated for coreboot: 53b232e lenovo/x60: Support digitizer on X60t and X201t.
by Vladimir Serbinenko
31 May '14
31 May '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5239
-gerrit commit 53b232e4b3e5260576092e21180d7c02de7aa699 Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sat Feb 15 17:00:46 2014 +0100 lenovo/x60: Support digitizer on X60t and X201t. Change-Id: I5b0399a8edca3b73aa7d515d2c446c31b3239fa5 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- src/drivers/Kconfig | 1 + src/drivers/Makefile.inc | 1 + src/drivers/lenovo/Kconfig | 29 ++++++ src/drivers/lenovo/Makefile.inc | 1 + src/drivers/lenovo/lenovo.h | 3 + src/drivers/lenovo/wacom.c | 176 ++++++++++++++++++++++++++++++++ src/mainboard/lenovo/Kconfig | 4 +- src/mainboard/lenovo/x201/Kconfig | 4 +- src/mainboard/lenovo/x201/acpi_tables.c | 2 + src/mainboard/lenovo/x201/devicetree.cb | 14 +++ src/mainboard/lenovo/x201/romstage.c | 2 +- src/mainboard/lenovo/x60/Kconfig | 3 +- src/mainboard/lenovo/x60/acpi_tables.c | 2 + src/mainboard/lenovo/x60/devicetree.cb | 7 +- 14 files changed, 242 insertions(+), 7 deletions(-) diff --git a/src/drivers/Kconfig b/src/drivers/Kconfig index 874ec75..42d1583 100644 --- a/src/drivers/Kconfig +++ b/src/drivers/Kconfig @@ -26,6 +26,7 @@ source src/drivers/i2c/Kconfig source src/drivers/ics/Kconfig source src/drivers/intel/Kconfig source src/drivers/ipmi/Kconfig +source src/drivers/lenovo/Kconfig source src/drivers/maxim/Kconfig source src/drivers/parade/Kconfig if PC80_SYSTEM diff --git a/src/drivers/Makefile.inc b/src/drivers/Makefile.inc index 66fe7b8..cb26643 100644 --- a/src/drivers/Makefile.inc +++ b/src/drivers/Makefile.inc @@ -23,6 +23,7 @@ subdirs-y += emulation subdirs-y += generic subdirs-y += i2c subdirs-y += intel +subdirs-y += lenovo subdirs-y += maxim subdirs-y += net subdirs-y += parade diff --git a/src/drivers/lenovo/Kconfig b/src/drivers/lenovo/Kconfig new file mode 100644 index 0000000..30bacb9 --- /dev/null +++ b/src/drivers/lenovo/Kconfig @@ -0,0 +1,29 @@ +config DRIVERS_LENOVO_WACOM + bool + default n + +if DRIVERS_LENOVO_WACOM + +choice + prompt "Digitizer" + default DIGITIZER_AUTODETECT + +config DIGITIZER_AUTODETECT + bool "Autodetect" + help + The presence of digitizer is inferred from model number stored in + AT24RF chip. + +config DIGITIZER_PRESENT + bool "Present" + help + The digitizer is assumed to be present. + +config DIGITIZER_ABSENT + bool "Absent" + help + The digitizer is assumed to be absent. + +endchoice + +endif diff --git a/src/drivers/lenovo/Makefile.inc b/src/drivers/lenovo/Makefile.inc new file mode 100644 index 0000000..c50db5b --- /dev/null +++ b/src/drivers/lenovo/Makefile.inc @@ -0,0 +1 @@ +ramstage-$(CONFIG_DRIVERS_LENOVO_WACOM) += wacom.c diff --git a/src/drivers/lenovo/lenovo.h b/src/drivers/lenovo/lenovo.h new file mode 100644 index 0000000..4c44119 --- /dev/null +++ b/src/drivers/lenovo/lenovo.h @@ -0,0 +1,3 @@ +int drivers_lenovo_is_wacom_present(void); +void drivers_lenovo_serial_ports_ssdt_generate(const char *scope, + int have_dock_serial); diff --git a/src/drivers/lenovo/wacom.c b/src/drivers/lenovo/wacom.c new file mode 100644 index 0000000..33a2879 --- /dev/null +++ b/src/drivers/lenovo/wacom.c @@ -0,0 +1,176 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Vladimir Serbinenko + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2, or (at your + * option) any later version, of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <types.h> +#include <console/console.h> +#include <arch/acpi.h> +#include <arch/acpigen.h> +#include <device/device.h> +#include <device/pnp.h> +#include <string.h> +#include "lenovo.h" +#include "drivers/i2c/at24rf08c/lenovo.h" + +static const char tablet_numbers[][5] = { + /* X60t. */ + "6363", "6364", "6365", "6366", + "6367", "6368", "7762", "7763", + "7764", "7767", "7768", "7769", + /* X201t. */ + "0053", "0831", "2985", "3093", + "3113", "3144", "3239", "4184", + "7448", "7449", "7450", "7453", + "2263", "2266", +}; + +int +drivers_lenovo_is_wacom_present(void) +{ + const char *pn; + int i; + static int result = -1; + device_t superio; + u8 sioid; + + if (result != -1) + return result; + + if (IS_ENABLED(CONFIG_DIGITIZER_PRESENT)) { + printk (BIOS_INFO, "Digitizer state forced as present\n"); + return (result = 1); + } + + if (IS_ENABLED(CONFIG_DIGITIZER_ABSENT)) { + printk (BIOS_INFO, "Digitizer state forced as absent\n"); + return (result = 0); + } + + superio = dev_find_slot_pnp (0x164e, 3); + if (!superio) { + printk (BIOS_INFO, "No Super I/O, skipping wacom\n"); + return (result = 0); + } + + /* Probe ID. */ + sioid = pnp_read_config(superio, 0x20); + if (sioid == 0xff) { + printk (BIOS_INFO, "Super I/O probe failed, skipping wacom\n"); + return (result = 0); + } + + pn = lenovo_mainboard_partnumber(); + if (!pn) + return (result = 0); + printk (BIOS_DEBUG, "Lenovo P/N is %s\n", pn); + for (i = 0; i < ARRAY_SIZE (tablet_numbers); i++) + if (memcmp (tablet_numbers[i], pn, 4) == 0) { + printk (BIOS_DEBUG, "Lenovo P/N %s is a tablet\n", pn); + return (result = 1); + } + printk (BIOS_DEBUG, "Lenovo P/N %s is not a tablet\n", pn); + return (result = 0); +} + +void +drivers_lenovo_serial_ports_ssdt_generate(const char *scope, + int have_dock_serial) +{ + int scopelen, devicelen, reslen, methodlen; + + scopelen = acpigen_write_scope(scope); + + if (drivers_lenovo_is_wacom_present()) { + /* Device op. */ + scopelen += acpigen_emit_byte(0x5b); + scopelen += acpigen_emit_byte(0x82); + devicelen = acpigen_write_len_f(); + devicelen += acpigen_emit_namestring("DTR"); + + devicelen += acpigen_write_name("_HID"); + devicelen += acpigen_emit_eisaid("WACF004"); + + devicelen += acpigen_write_name("_CRS"); + + reslen = acpigen_write_resourcetemplate_header(); + reslen += acpigen_write_io16(0x200, 0x200, 1, 8, 1); + reslen += acpigen_write_irq((1 << 5)); + + devicelen += reslen; + devicelen += acpigen_write_resourcetemplate_footer(reslen); + + /* method op */ + devicelen += acpigen_emit_byte(0x14); + methodlen = acpigen_write_len_f(); + methodlen += acpigen_emit_namestring("_STA"); + /* no fnarg */ + methodlen += acpigen_emit_byte(0x00); + /* return */ + methodlen += acpigen_emit_byte(0xa4); + methodlen += acpigen_write_byte(0xf); + + acpigen_patch_len(methodlen); + devicelen += methodlen; + + acpigen_patch_len(devicelen - 1); + scopelen += devicelen; + } + + if (have_dock_serial) { + /* Device op. */ + scopelen += acpigen_emit_byte(0x5b); + scopelen += acpigen_emit_byte(0x82); + devicelen = acpigen_write_len_f(); + devicelen += acpigen_emit_namestring("COMA"); + + devicelen += acpigen_write_name("_HID"); + devicelen += acpigen_emit_eisaid("PNP0501"); + devicelen += acpigen_write_name("_UID"); + /* Byte */ + devicelen += acpigen_write_byte(0x2); + + devicelen += acpigen_write_name("_CRS"); + + reslen = acpigen_write_resourcetemplate_header(); + reslen += acpigen_write_io16(0x3f8, 0x3f8, 1, 8, 1); + reslen += acpigen_write_irq(1 << 4); + + devicelen += reslen; + devicelen += acpigen_write_resourcetemplate_footer(reslen); + + /* method op */ + devicelen += acpigen_emit_byte(0x14); + methodlen = acpigen_write_len_f(); + methodlen += acpigen_emit_namestring("_STA"); + /* no fnarg */ + methodlen += acpigen_emit_byte(0x00); + /* return */ + methodlen += acpigen_emit_byte(0xa4); + methodlen += acpigen_write_byte(0xf); + acpigen_patch_len(methodlen); + + devicelen += methodlen; + + acpigen_patch_len(devicelen - 1); + scopelen += devicelen; + } + + acpigen_patch_len(scopelen - 1); +} diff --git a/src/mainboard/lenovo/Kconfig b/src/mainboard/lenovo/Kconfig index c1dec85..583efc8 100644 --- a/src/mainboard/lenovo/Kconfig +++ b/src/mainboard/lenovo/Kconfig @@ -4,7 +4,7 @@ choice prompt "Mainboard model" config BOARD_LENOVO_X60 - bool "ThinkPad X60 / X60s" + bool "ThinkPad X60 / X60s / X60t" help The following X60 series ThinkPad machines have been verified to work correctly: @@ -13,7 +13,7 @@ config BOARD_LENOVO_X60 ThinkPad X60 (Model 1709) config BOARD_LENOVO_X201 - bool "ThinkPad X201" + bool "ThinkPad X201 / X201s / X201t" help Lenovo X201 laptop. Consult wiki for details. diff --git a/src/mainboard/lenovo/x201/Kconfig b/src/mainboard/lenovo/x201/Kconfig index 50df47b..61038c4 100644 --- a/src/mainboard/lenovo/x201/Kconfig +++ b/src/mainboard/lenovo/x201/Kconfig @@ -17,6 +17,8 @@ config BOARD_SPECIFIC_OPTIONS # dummy select EARLY_CBMEM_INIT select MAINBOARD_HAS_NATIVE_VGA_INIT select MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG + select SUPERIO_NSC_PC87382 + select DRIVERS_LENOVO_WACOM config MAINBOARD_DIR string @@ -28,7 +30,7 @@ config MAINBOARD_PART_NUMBER config MAINBOARD_VERSION string - default "ThinkPad X201" + default "ThinkPad X201 / X201s / X201t" config MAINBOARD_VENDOR string diff --git a/src/mainboard/lenovo/x201/acpi_tables.c b/src/mainboard/lenovo/x201/acpi_tables.c index 165de0d..b6e99dd 100644 --- a/src/mainboard/lenovo/x201/acpi_tables.c +++ b/src/mainboard/lenovo/x201/acpi_tables.c @@ -31,6 +31,7 @@ #include <device/pci.h> #include <device/pci_ids.h> #include "southbridge/intel/ibexpeak/nvs.h" +#include "drivers/lenovo/lenovo.h" extern const unsigned char AmlCode[]; #if CONFIG_HAVE_ACPI_SLIC @@ -93,6 +94,7 @@ unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { generate_cpu_entries(); + drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 0); return (unsigned long)(acpigen_get_current()); } diff --git a/src/mainboard/lenovo/x201/devicetree.cb b/src/mainboard/lenovo/x201/devicetree.cb index 9053f89..1db5bf0 100644 --- a/src/mainboard/lenovo/x201/devicetree.cb +++ b/src/mainboard/lenovo/x201/devicetree.cb @@ -143,6 +143,20 @@ chip northbridge/intel/nehalem end device pci 1f.0 on # PCI-LPC bridge subsystemid 0x17aa 0x2166 + chip superio/nsc/pc87382 + device pnp 164e.3 on # Digitizer + io 0x60 = 0x200 + irq 0x29 = 0xb0 + irq 0x70 = 0x5 + irq 0xf0 = 0x82 + end + # IR, not connected + device pnp 164e.2 off end + # GPIO, not connected + device pnp 164e.7 off end + # DLPC, not connected + device pnp 164e.19 off end + end end device pci 1f.2 on # IDE/SATA subsystemid 0x17aa 0x2168 diff --git a/src/mainboard/lenovo/x201/romstage.c b/src/mainboard/lenovo/x201/romstage.c index 1237a5c..f74b441 100644 --- a/src/mainboard/lenovo/x201/romstage.c +++ b/src/mainboard/lenovo/x201/romstage.c @@ -53,7 +53,7 @@ static void pch_enable_lpc(void) /* Enable EC, PS/2 Keyboard/Mouse */ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN | - COMA_LPC_EN); + COMA_LPC_EN | GAMEL_LPC_EN); pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); diff --git a/src/mainboard/lenovo/x60/Kconfig b/src/mainboard/lenovo/x60/Kconfig index 5abb14c..d64692c 100644 --- a/src/mainboard/lenovo/x60/Kconfig +++ b/src/mainboard/lenovo/x60/Kconfig @@ -24,6 +24,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select MAINBOARD_HAS_NATIVE_VGA_INIT select EARLY_CBMEM_INIT select H8_DOCK_EARLY_INIT + select DRIVERS_LENOVO_WACOM config MAINBOARD_DIR string @@ -39,7 +40,7 @@ config DCACHE_RAM_SIZE config MAINBOARD_PART_NUMBER string - default "ThinkPad X60 / X60s" + default "ThinkPad X60 / X60s / X60t" config MMCONF_BASE_ADDRESS hex diff --git a/src/mainboard/lenovo/x60/acpi_tables.c b/src/mainboard/lenovo/x60/acpi_tables.c index f6ed4ae..cf07067 100644 --- a/src/mainboard/lenovo/x60/acpi_tables.c +++ b/src/mainboard/lenovo/x60/acpi_tables.c @@ -29,6 +29,7 @@ #include <device/device.h> #include <device/pci.h> #include <device/pci_ids.h> +#include "drivers/lenovo/lenovo.h" extern const unsigned char AmlCode[]; #if CONFIG_HAVE_ACPI_SLIC @@ -86,6 +87,7 @@ unsigned long acpi_fill_madt(unsigned long current) unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { generate_cpu_entries(); + drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 1); return (unsigned long) (acpigen_get_current()); } diff --git a/src/mainboard/lenovo/x60/devicetree.cb b/src/mainboard/lenovo/x60/devicetree.cb index fbef3bf..81648bd 100644 --- a/src/mainboard/lenovo/x60/devicetree.cb +++ b/src/mainboard/lenovo/x60/devicetree.cb @@ -127,8 +127,11 @@ chip northbridge/intel/i945 io 0x60 = 0x2f8 end - device pnp 164e.3 off # Serial Port - io 0x60 = 0x3f8 + device pnp 164e.3 on # Digitizer + io 0x60 = 0x200 + irq 0x29 = 0xb0 + irq 0x70 = 0x5 + irq 0xf0 = 0x82 end device pnp 164e.7 on # GPIO
1
0
0
0
Patch set updated for coreboot: 0213656 lenovo/t60: Enable Infrared port.
by Vladimir Serbinenko
31 May '14
31 May '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5243
-gerrit commit 0213656713116c3228e5a32758564c054a6fbebc Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sat Feb 15 19:17:10 2014 +0100 lenovo/t60: Enable Infrared port. Change-Id: I10f05334328c9929a99352185d286a7a17898801 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- src/mainboard/lenovo/t60/acpi/superio.asl | 16 ++++++++++++++++ src/mainboard/lenovo/t60/devicetree.cb | 4 ++++ src/mainboard/lenovo/t60/romstage.c | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/mainboard/lenovo/t60/acpi/superio.asl b/src/mainboard/lenovo/t60/acpi/superio.asl index e69de29..a0d8e0a 100644 --- a/src/mainboard/lenovo/t60/acpi/superio.asl +++ b/src/mainboard/lenovo/t60/acpi/superio.asl @@ -0,0 +1,16 @@ + Device (FIR) // Infrared + { + Name(_HID, EISAID("IBM0071")) + Name(_CID, EISAID("PNP0511")) + + Name(_CRS, ResourceTemplate() + { + IO (Decode16, 0x2f8, 0x2f8, 0x01, 0x08) + IRQNoFlags () {3} + }) + + Method (_STA, 0) + { + Return (0xf) + } + } diff --git a/src/mainboard/lenovo/t60/devicetree.cb b/src/mainboard/lenovo/t60/devicetree.cb index f092380..5e80cb7 100644 --- a/src/mainboard/lenovo/t60/devicetree.cb +++ b/src/mainboard/lenovo/t60/devicetree.cb @@ -148,6 +148,10 @@ chip northbridge/intel/i945 chip superio/nsc/pc87382 device pnp 164e.2 on # IR io 0x60 = 0x2f8 + irq 0x29 = 0xb0 + irq 0x70 = 0x3 + drq 0x74 = 0x1 + irq 0xf0 = 0x82 end device pnp 164e.3 off # Serial Port diff --git a/src/mainboard/lenovo/t60/romstage.c b/src/mainboard/lenovo/t60/romstage.c index dae917c..237e967 100644 --- a/src/mainboard/lenovo/t60/romstage.c +++ b/src/mainboard/lenovo/t60/romstage.c @@ -79,7 +79,7 @@ static void ich7_enable_lpc(void) // decode range pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x80, 0x0210); // decode range - pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1f0d); + pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1f0f); /* range 0x1600 - 0x167f */ pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x84, 0x1601);
1
0
0
0
Patch set updated for coreboot: df0d7ed lenovo/x60: Enable Infrared port.
by Vladimir Serbinenko
31 May '14
31 May '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5242
-gerrit commit df0d7ed12c811e5f8d8a9c8a2aa5e4cf039a3910 Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sat Feb 15 19:13:00 2014 +0100 lenovo/x60: Enable Infrared port. Change-Id: I8ce0195bc85a983627826b31eb9879c3dbc80dd9 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- src/drivers/lenovo/lenovo.h | 3 ++- src/drivers/lenovo/wacom.c | 44 ++++++++++++++++++++++++++++++++- src/mainboard/lenovo/x201/acpi_tables.c | 2 +- src/mainboard/lenovo/x60/acpi_tables.c | 2 +- src/mainboard/lenovo/x60/devicetree.cb | 4 +++ src/mainboard/lenovo/x60/romstage.c | 2 +- 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/drivers/lenovo/lenovo.h b/src/drivers/lenovo/lenovo.h index 4c44119..06b52e5 100644 --- a/src/drivers/lenovo/lenovo.h +++ b/src/drivers/lenovo/lenovo.h @@ -1,3 +1,4 @@ int drivers_lenovo_is_wacom_present(void); void drivers_lenovo_serial_ports_ssdt_generate(const char *scope, - int have_dock_serial); + int have_dock_serial, + int have_infrared); diff --git a/src/drivers/lenovo/wacom.c b/src/drivers/lenovo/wacom.c index 33a2879..ccccefd 100644 --- a/src/drivers/lenovo/wacom.c +++ b/src/drivers/lenovo/wacom.c @@ -91,7 +91,8 @@ drivers_lenovo_is_wacom_present(void) void drivers_lenovo_serial_ports_ssdt_generate(const char *scope, - int have_dock_serial) + int have_dock_serial, + int have_infrared) { int scopelen, devicelen, reslen, methodlen; @@ -133,6 +134,47 @@ drivers_lenovo_serial_ports_ssdt_generate(const char *scope, scopelen += devicelen; } + if (have_infrared) { + /* Device op. */ + scopelen += acpigen_emit_byte(0x5b); + scopelen += acpigen_emit_byte(0x82); + devicelen = acpigen_write_len_f(); + devicelen += acpigen_emit_namestring("FIR"); + + devicelen += acpigen_write_name("_HID"); + devicelen += acpigen_emit_eisaid("IBM0071"); + devicelen += acpigen_write_name("_CID"); + devicelen += acpigen_emit_eisaid("PNP0511"); + devicelen += acpigen_write_name("_UID"); + + /* One */ + devicelen += acpigen_write_byte(0x1); + devicelen += acpigen_write_name("_CRS"); + + reslen = acpigen_write_resourcetemplate_header(); + reslen += acpigen_write_io16(0x2f8, 0x2f8, 1, 8, 1); + reslen += acpigen_write_irq(0x08); + + devicelen += reslen; + devicelen += acpigen_write_resourcetemplate_footer(reslen); + + /* method op */ + devicelen += acpigen_emit_byte(0x14); + methodlen = acpigen_write_len_f(); + methodlen += acpigen_emit_namestring("_STA"); + /* no fnarg */ + methodlen += acpigen_emit_byte(0x00); + /* return */ + methodlen += acpigen_emit_byte(0xa4); + methodlen += acpigen_write_byte(0xf); + acpigen_patch_len(methodlen); + + devicelen += methodlen; + + acpigen_patch_len(devicelen - 1); + scopelen += devicelen; + } + if (have_dock_serial) { /* Device op. */ scopelen += acpigen_emit_byte(0x5b); diff --git a/src/mainboard/lenovo/x201/acpi_tables.c b/src/mainboard/lenovo/x201/acpi_tables.c index b6e99dd..710e369 100644 --- a/src/mainboard/lenovo/x201/acpi_tables.c +++ b/src/mainboard/lenovo/x201/acpi_tables.c @@ -94,7 +94,7 @@ unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { generate_cpu_entries(); - drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 0); + drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 0, 0); return (unsigned long)(acpigen_get_current()); } diff --git a/src/mainboard/lenovo/x60/acpi_tables.c b/src/mainboard/lenovo/x60/acpi_tables.c index cf07067..c8fce7f 100644 --- a/src/mainboard/lenovo/x60/acpi_tables.c +++ b/src/mainboard/lenovo/x60/acpi_tables.c @@ -87,7 +87,7 @@ unsigned long acpi_fill_madt(unsigned long current) unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { generate_cpu_entries(); - drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 1); + drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 1, 1); return (unsigned long) (acpigen_get_current()); } diff --git a/src/mainboard/lenovo/x60/devicetree.cb b/src/mainboard/lenovo/x60/devicetree.cb index 81648bd..b3dd514 100644 --- a/src/mainboard/lenovo/x60/devicetree.cb +++ b/src/mainboard/lenovo/x60/devicetree.cb @@ -125,6 +125,10 @@ chip northbridge/intel/i945 chip superio/nsc/pc87382 device pnp 164e.2 on # IR io 0x60 = 0x2f8 + irq 0x29 = 0xb0 + irq 0x70 = 0x3 + drq 0x74 = 0x1 + irq 0xf0 = 0x82 end device pnp 164e.3 on # Digitizer diff --git a/src/mainboard/lenovo/x60/romstage.c b/src/mainboard/lenovo/x60/romstage.c index 1198fb2..8eca464 100644 --- a/src/mainboard/lenovo/x60/romstage.c +++ b/src/mainboard/lenovo/x60/romstage.c @@ -86,7 +86,7 @@ static void ich7_enable_lpc(void) // decode range pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x80, 0x0210); // decode range - pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1f0d); + pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1f0f); /* range 0x1600 - 0x167f */ pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x84, 0x1601);
1
0
0
0
Patch set updated for coreboot: 36525b4 lenovo/x60: Support digitizer on X60t and X201t.
by Vladimir Serbinenko
31 May '14
31 May '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5239
-gerrit commit 36525b40e6951f09a4b4772c804da153390b21a6 Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sat Feb 15 17:00:46 2014 +0100 lenovo/x60: Support digitizer on X60t and X201t. Change-Id: I5b0399a8edca3b73aa7d515d2c446c31b3239fa5 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- src/drivers/Kconfig | 1 + src/drivers/Makefile.inc | 1 + src/drivers/lenovo/Kconfig | 29 ++++++ src/drivers/lenovo/Makefile.inc | 1 + src/drivers/lenovo/lenovo.h | 3 + src/drivers/lenovo/wacom.c | 177 ++++++++++++++++++++++++++++++++ src/mainboard/lenovo/Kconfig | 4 +- src/mainboard/lenovo/x201/Kconfig | 4 +- src/mainboard/lenovo/x201/acpi_tables.c | 2 + src/mainboard/lenovo/x201/devicetree.cb | 14 +++ src/mainboard/lenovo/x201/romstage.c | 2 +- src/mainboard/lenovo/x60/Kconfig | 3 +- src/mainboard/lenovo/x60/acpi_tables.c | 2 + src/mainboard/lenovo/x60/devicetree.cb | 7 +- 14 files changed, 243 insertions(+), 7 deletions(-) diff --git a/src/drivers/Kconfig b/src/drivers/Kconfig index 874ec75..42d1583 100644 --- a/src/drivers/Kconfig +++ b/src/drivers/Kconfig @@ -26,6 +26,7 @@ source src/drivers/i2c/Kconfig source src/drivers/ics/Kconfig source src/drivers/intel/Kconfig source src/drivers/ipmi/Kconfig +source src/drivers/lenovo/Kconfig source src/drivers/maxim/Kconfig source src/drivers/parade/Kconfig if PC80_SYSTEM diff --git a/src/drivers/Makefile.inc b/src/drivers/Makefile.inc index 66fe7b8..cb26643 100644 --- a/src/drivers/Makefile.inc +++ b/src/drivers/Makefile.inc @@ -23,6 +23,7 @@ subdirs-y += emulation subdirs-y += generic subdirs-y += i2c subdirs-y += intel +subdirs-y += lenovo subdirs-y += maxim subdirs-y += net subdirs-y += parade diff --git a/src/drivers/lenovo/Kconfig b/src/drivers/lenovo/Kconfig new file mode 100644 index 0000000..30bacb9 --- /dev/null +++ b/src/drivers/lenovo/Kconfig @@ -0,0 +1,29 @@ +config DRIVERS_LENOVO_WACOM + bool + default n + +if DRIVERS_LENOVO_WACOM + +choice + prompt "Digitizer" + default DIGITIZER_AUTODETECT + +config DIGITIZER_AUTODETECT + bool "Autodetect" + help + The presence of digitizer is inferred from model number stored in + AT24RF chip. + +config DIGITIZER_PRESENT + bool "Present" + help + The digitizer is assumed to be present. + +config DIGITIZER_ABSENT + bool "Absent" + help + The digitizer is assumed to be absent. + +endchoice + +endif diff --git a/src/drivers/lenovo/Makefile.inc b/src/drivers/lenovo/Makefile.inc new file mode 100644 index 0000000..c50db5b --- /dev/null +++ b/src/drivers/lenovo/Makefile.inc @@ -0,0 +1 @@ +ramstage-$(CONFIG_DRIVERS_LENOVO_WACOM) += wacom.c diff --git a/src/drivers/lenovo/lenovo.h b/src/drivers/lenovo/lenovo.h new file mode 100644 index 0000000..4c44119 --- /dev/null +++ b/src/drivers/lenovo/lenovo.h @@ -0,0 +1,3 @@ +int drivers_lenovo_is_wacom_present(void); +void drivers_lenovo_serial_ports_ssdt_generate(const char *scope, + int have_dock_serial); diff --git a/src/drivers/lenovo/wacom.c b/src/drivers/lenovo/wacom.c new file mode 100644 index 0000000..96ade66 --- /dev/null +++ b/src/drivers/lenovo/wacom.c @@ -0,0 +1,177 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 coresystems GmbH + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2, or (at your + * option) any later version, of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <types.h> +#include <console/console.h> +#include <arch/acpi.h> +#include <arch/acpigen.h> +#include <device/device.h> +#include <device/pnp.h> +#include <string.h> +#include "lenovo.h" +#include "drivers/i2c/at24rf08c/lenovo.h" + +static const char tablet_numbers[][5] = { + /* X60t. */ + "6363", "6364", "6365", "6366", + "6367", "6368", "7762", "7763", + "7764", "7767", "7768", "7769", + /* X201t. */ + "0053", "0831", "2985", "3093", + "3113", "3144", "3239", "4184", + "7448", "7449", "7450", "7453", + "2263", "2266", +}; + +int +drivers_lenovo_is_wacom_present(void) +{ + const char *pn; + int i; + static int result = -1; + device_t superio; + u8 sioid; + + if (result != -1) + return result; + + if (IS_ENABLED(CONFIG_DIGITIZER_PRESENT)) { + printk (BIOS_INFO, "Digitizer state forced as present\n"); + return (result = 1); + } + + if (IS_ENABLED(CONFIG_DIGITIZER_ABSENT)) { + printk (BIOS_INFO, "Digitizer state forced as absent\n"); + return (result = 0); + } + + superio = dev_find_slot_pnp (0x164e, 3); + if (!superio) { + printk (BIOS_INFO, "No Super I/O, skipping wacom\n"); + return (result = 0); + } + + /* Probe ID. */ + sioid = pnp_read_config(superio, 0x20); + if (sioid == 0xff) { + printk (BIOS_INFO, "Super I/O probe failed, skipping wacom\n"); + return (result = 0); + } + + pn = lenovo_mainboard_partnumber(); + if (!pn) + return 0; + printk (BIOS_DEBUG, "Lenovo P/N is %s\n", pn); + for (i = 0; i < ARRAY_SIZE (tablet_numbers); i++) + if (memcmp (tablet_numbers[i], pn, 4) == 0) { + printk (BIOS_DEBUG, "Lenovo P/N %s is a tablet\n", pn); + return (result = 1); + } + printk (BIOS_DEBUG, "Lenovo P/N %s is not a tablet\n", pn); + return (result = 0); +} + +void +drivers_lenovo_serial_ports_ssdt_generate(const char *scope, + int have_dock_serial) +{ + int scopelen, devicelen, reslen, methodlen; + + scopelen = acpigen_write_scope(scope); + + if (drivers_lenovo_is_wacom_present()) { + /* Device op. */ + scopelen += acpigen_emit_byte(0x5b); + scopelen += acpigen_emit_byte(0x82); + devicelen = acpigen_write_len_f(); + devicelen += acpigen_emit_namestring("DTR"); + + devicelen += acpigen_write_name("_HID"); + devicelen += acpigen_emit_eisaid("WACF004"); + + devicelen += acpigen_write_name("_CRS"); + + reslen = acpigen_write_resourcetemplate_header(); + reslen += acpigen_write_io16(0x200, 0x200, 1, 8, 1); + reslen += acpigen_write_irq((1 << 5)); + + devicelen += reslen; + devicelen += acpigen_write_resourcetemplate_footer(reslen); + + /* method op */ + devicelen += acpigen_emit_byte(0x14); + methodlen = acpigen_write_len_f(); + methodlen += acpigen_emit_namestring("_STA"); + /* no fnarg */ + methodlen += acpigen_emit_byte(0x00); + /* return */ + methodlen += acpigen_emit_byte(0xa4); + methodlen += acpigen_write_byte(0xf); + + acpigen_patch_len(methodlen); + devicelen += methodlen; + + acpigen_patch_len(devicelen - 1); + scopelen += devicelen; + } + + if (have_dock_serial) { + /* Device op. */ + scopelen += acpigen_emit_byte(0x5b); + scopelen += acpigen_emit_byte(0x82); + devicelen = acpigen_write_len_f(); + devicelen += acpigen_emit_namestring("COMA"); + + devicelen += acpigen_write_name("_HID"); + devicelen += acpigen_emit_eisaid("PNP0501"); + devicelen += acpigen_write_name("_UID"); + /* Byte */ + devicelen += acpigen_write_byte(0x2); + + devicelen += acpigen_write_name("_CRS"); + + reslen = acpigen_write_resourcetemplate_header(); + reslen += acpigen_write_io16(0x3f8, 0x3f8, 1, 8, 1); + reslen += acpigen_write_irq(1 << 4); + + devicelen += reslen; + devicelen += acpigen_write_resourcetemplate_footer(reslen); + + /* method op */ + devicelen += acpigen_emit_byte(0x14); + methodlen = acpigen_write_len_f(); + methodlen += acpigen_emit_namestring("_STA"); + /* no fnarg */ + methodlen += acpigen_emit_byte(0x00); + /* return */ + methodlen += acpigen_emit_byte(0xa4); + methodlen += acpigen_write_byte(0xf); + acpigen_patch_len(methodlen); + + devicelen += methodlen; + + acpigen_patch_len(devicelen - 1); + scopelen += devicelen; + } + + acpigen_patch_len(scopelen - 1); +} diff --git a/src/mainboard/lenovo/Kconfig b/src/mainboard/lenovo/Kconfig index c1dec85..583efc8 100644 --- a/src/mainboard/lenovo/Kconfig +++ b/src/mainboard/lenovo/Kconfig @@ -4,7 +4,7 @@ choice prompt "Mainboard model" config BOARD_LENOVO_X60 - bool "ThinkPad X60 / X60s" + bool "ThinkPad X60 / X60s / X60t" help The following X60 series ThinkPad machines have been verified to work correctly: @@ -13,7 +13,7 @@ config BOARD_LENOVO_X60 ThinkPad X60 (Model 1709) config BOARD_LENOVO_X201 - bool "ThinkPad X201" + bool "ThinkPad X201 / X201s / X201t" help Lenovo X201 laptop. Consult wiki for details. diff --git a/src/mainboard/lenovo/x201/Kconfig b/src/mainboard/lenovo/x201/Kconfig index 50df47b..61038c4 100644 --- a/src/mainboard/lenovo/x201/Kconfig +++ b/src/mainboard/lenovo/x201/Kconfig @@ -17,6 +17,8 @@ config BOARD_SPECIFIC_OPTIONS # dummy select EARLY_CBMEM_INIT select MAINBOARD_HAS_NATIVE_VGA_INIT select MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG + select SUPERIO_NSC_PC87382 + select DRIVERS_LENOVO_WACOM config MAINBOARD_DIR string @@ -28,7 +30,7 @@ config MAINBOARD_PART_NUMBER config MAINBOARD_VERSION string - default "ThinkPad X201" + default "ThinkPad X201 / X201s / X201t" config MAINBOARD_VENDOR string diff --git a/src/mainboard/lenovo/x201/acpi_tables.c b/src/mainboard/lenovo/x201/acpi_tables.c index 165de0d..b6e99dd 100644 --- a/src/mainboard/lenovo/x201/acpi_tables.c +++ b/src/mainboard/lenovo/x201/acpi_tables.c @@ -31,6 +31,7 @@ #include <device/pci.h> #include <device/pci_ids.h> #include "southbridge/intel/ibexpeak/nvs.h" +#include "drivers/lenovo/lenovo.h" extern const unsigned char AmlCode[]; #if CONFIG_HAVE_ACPI_SLIC @@ -93,6 +94,7 @@ unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { generate_cpu_entries(); + drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 0); return (unsigned long)(acpigen_get_current()); } diff --git a/src/mainboard/lenovo/x201/devicetree.cb b/src/mainboard/lenovo/x201/devicetree.cb index 9053f89..1db5bf0 100644 --- a/src/mainboard/lenovo/x201/devicetree.cb +++ b/src/mainboard/lenovo/x201/devicetree.cb @@ -143,6 +143,20 @@ chip northbridge/intel/nehalem end device pci 1f.0 on # PCI-LPC bridge subsystemid 0x17aa 0x2166 + chip superio/nsc/pc87382 + device pnp 164e.3 on # Digitizer + io 0x60 = 0x200 + irq 0x29 = 0xb0 + irq 0x70 = 0x5 + irq 0xf0 = 0x82 + end + # IR, not connected + device pnp 164e.2 off end + # GPIO, not connected + device pnp 164e.7 off end + # DLPC, not connected + device pnp 164e.19 off end + end end device pci 1f.2 on # IDE/SATA subsystemid 0x17aa 0x2168 diff --git a/src/mainboard/lenovo/x201/romstage.c b/src/mainboard/lenovo/x201/romstage.c index 1237a5c..f74b441 100644 --- a/src/mainboard/lenovo/x201/romstage.c +++ b/src/mainboard/lenovo/x201/romstage.c @@ -53,7 +53,7 @@ static void pch_enable_lpc(void) /* Enable EC, PS/2 Keyboard/Mouse */ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN | - COMA_LPC_EN); + COMA_LPC_EN | GAMEL_LPC_EN); pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); diff --git a/src/mainboard/lenovo/x60/Kconfig b/src/mainboard/lenovo/x60/Kconfig index 5abb14c..d64692c 100644 --- a/src/mainboard/lenovo/x60/Kconfig +++ b/src/mainboard/lenovo/x60/Kconfig @@ -24,6 +24,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select MAINBOARD_HAS_NATIVE_VGA_INIT select EARLY_CBMEM_INIT select H8_DOCK_EARLY_INIT + select DRIVERS_LENOVO_WACOM config MAINBOARD_DIR string @@ -39,7 +40,7 @@ config DCACHE_RAM_SIZE config MAINBOARD_PART_NUMBER string - default "ThinkPad X60 / X60s" + default "ThinkPad X60 / X60s / X60t" config MMCONF_BASE_ADDRESS hex diff --git a/src/mainboard/lenovo/x60/acpi_tables.c b/src/mainboard/lenovo/x60/acpi_tables.c index f6ed4ae..cf07067 100644 --- a/src/mainboard/lenovo/x60/acpi_tables.c +++ b/src/mainboard/lenovo/x60/acpi_tables.c @@ -29,6 +29,7 @@ #include <device/device.h> #include <device/pci.h> #include <device/pci_ids.h> +#include "drivers/lenovo/lenovo.h" extern const unsigned char AmlCode[]; #if CONFIG_HAVE_ACPI_SLIC @@ -86,6 +87,7 @@ unsigned long acpi_fill_madt(unsigned long current) unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { generate_cpu_entries(); + drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 1); return (unsigned long) (acpigen_get_current()); } diff --git a/src/mainboard/lenovo/x60/devicetree.cb b/src/mainboard/lenovo/x60/devicetree.cb index fbef3bf..81648bd 100644 --- a/src/mainboard/lenovo/x60/devicetree.cb +++ b/src/mainboard/lenovo/x60/devicetree.cb @@ -127,8 +127,11 @@ chip northbridge/intel/i945 io 0x60 = 0x2f8 end - device pnp 164e.3 off # Serial Port - io 0x60 = 0x3f8 + device pnp 164e.3 on # Digitizer + io 0x60 = 0x200 + irq 0x29 = 0xb0 + irq 0x70 = 0x5 + irq 0xf0 = 0x82 end device pnp 164e.7 on # GPIO
1
0
0
0
Patch set updated for coreboot: 79d5477 acpigen: Add acpigen_emit_eisaid.
by Vladimir Serbinenko
31 May '14
31 May '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5240
-gerrit commit 79d547747ee918cd0ff82b12896dc99143a050ca Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sat Feb 15 18:59:40 2014 +0100 acpigen: Add acpigen_emit_eisaid. Change-Id: Ib92142a133445018cd152dabe299792ba5f36548 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- 3rdparty | 2 +- src/arch/x86/boot/acpigen.c | 34 ++++++++++++++++++++++++++++++++++ src/arch/x86/include/arch/acpigen.h | 1 + 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/3rdparty b/3rdparty index 324ec3c..45f0c04 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit 324ec3cb642a278d6d97ae809bc6098045bc6e65 +Subproject commit 45f0c04fd788fb29d9e303b2b2d1657ddb03448a diff --git a/src/arch/x86/boot/acpigen.c b/src/arch/x86/boot/acpigen.c index fdb7e02..ba3d2df 100644 --- a/src/arch/x86/boot/acpigen.c +++ b/src/arch/x86/boot/acpigen.c @@ -754,3 +754,37 @@ int acpigen_write_mainboard_resources(const char *scope, const char *name) acpigen_patch_len(len - 1); return len; } + +static int hex2bin(const char c) +{ + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return c - '0'; +} + +int acpigen_emit_eisaid(const char *eisaid) +{ + u32 compact = 0; + + /* Clamping individual values would be better but + there is a disagreement over what is a valid + EISA id, so accept anything and don't clamp, + parent code should create a valid EISAid. + */ + compact |= (eisaid[0] - 'A' + 1) << 26; + compact |= (eisaid[1] - 'A' + 1) << 21; + compact |= (eisaid[2] - 'A' + 1) << 16; + compact |= hex2bin(eisaid[3]) << 12; + compact |= hex2bin(eisaid[4]) << 8; + compact |= hex2bin(eisaid[5]) << 4; + compact |= hex2bin(eisaid[6]); + + acpigen_emit_byte(0xc); + acpigen_emit_byte((compact >> 24) & 0xff); + acpigen_emit_byte((compact >> 16) & 0xff); + acpigen_emit_byte((compact >> 8) & 0xff); + acpigen_emit_byte(compact & 0xff); + return 5; +} diff --git a/src/arch/x86/include/arch/acpigen.h b/src/arch/x86/include/arch/acpigen.h index 2ff9967..3217dbe 100644 --- a/src/arch/x86/include/arch/acpigen.h +++ b/src/arch/x86/include/arch/acpigen.h @@ -34,6 +34,7 @@ int acpigen_write_byte(unsigned int data); int acpigen_emit_byte(unsigned char data); int acpigen_emit_stream(const char *data, int size); int acpigen_emit_namestring(const char *namepath); +int acpigen_emit_eisaid(const char *eisaid); int acpigen_write_dword(unsigned int data); int acpigen_write_qword(uint64_t data); int acpigen_write_name(const char *name);
1
0
0
0
Patch set updated for coreboot: 6e1f884 lenovo/t60: Enable Infrared port.
by Vladimir Serbinenko
31 May '14
31 May '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5243
-gerrit commit 6e1f8847c5902ed0dfb4c0ff0d477150ebba89a4 Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sat Feb 15 19:17:10 2014 +0100 lenovo/t60: Enable Infrared port. Change-Id: I10f05334328c9929a99352185d286a7a17898801 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- src/mainboard/lenovo/t60/acpi/superio.asl | 16 ++++++++++++++++ src/mainboard/lenovo/t60/devicetree.cb | 4 ++++ src/mainboard/lenovo/t60/romstage.c | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/mainboard/lenovo/t60/acpi/superio.asl b/src/mainboard/lenovo/t60/acpi/superio.asl index e69de29..a0d8e0a 100644 --- a/src/mainboard/lenovo/t60/acpi/superio.asl +++ b/src/mainboard/lenovo/t60/acpi/superio.asl @@ -0,0 +1,16 @@ + Device (FIR) // Infrared + { + Name(_HID, EISAID("IBM0071")) + Name(_CID, EISAID("PNP0511")) + + Name(_CRS, ResourceTemplate() + { + IO (Decode16, 0x2f8, 0x2f8, 0x01, 0x08) + IRQNoFlags () {3} + }) + + Method (_STA, 0) + { + Return (0xf) + } + } diff --git a/src/mainboard/lenovo/t60/devicetree.cb b/src/mainboard/lenovo/t60/devicetree.cb index f092380..5e80cb7 100644 --- a/src/mainboard/lenovo/t60/devicetree.cb +++ b/src/mainboard/lenovo/t60/devicetree.cb @@ -148,6 +148,10 @@ chip northbridge/intel/i945 chip superio/nsc/pc87382 device pnp 164e.2 on # IR io 0x60 = 0x2f8 + irq 0x29 = 0xb0 + irq 0x70 = 0x3 + drq 0x74 = 0x1 + irq 0xf0 = 0x82 end device pnp 164e.3 off # Serial Port diff --git a/src/mainboard/lenovo/t60/romstage.c b/src/mainboard/lenovo/t60/romstage.c index dae917c..237e967 100644 --- a/src/mainboard/lenovo/t60/romstage.c +++ b/src/mainboard/lenovo/t60/romstage.c @@ -79,7 +79,7 @@ static void ich7_enable_lpc(void) // decode range pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x80, 0x0210); // decode range - pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1f0d); + pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1f0f); /* range 0x1600 - 0x167f */ pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x84, 0x1601);
1
0
0
0
Patch set updated for coreboot: 12e7316 lenovo/x60: Enable Infrared port.
by Vladimir Serbinenko
31 May '14
31 May '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5242
-gerrit commit 12e7316f08789d69a12c2679ae945e7fac4189be Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sat Feb 15 19:13:00 2014 +0100 lenovo/x60: Enable Infrared port. Change-Id: I8ce0195bc85a983627826b31eb9879c3dbc80dd9 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- src/drivers/lenovo/lenovo.h | 3 ++- src/drivers/lenovo/wacom.c | 44 ++++++++++++++++++++++++++++++++- src/mainboard/lenovo/x201/acpi_tables.c | 2 +- src/mainboard/lenovo/x60/acpi_tables.c | 2 +- src/mainboard/lenovo/x60/devicetree.cb | 4 +++ src/mainboard/lenovo/x60/romstage.c | 2 +- 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/drivers/lenovo/lenovo.h b/src/drivers/lenovo/lenovo.h index 4c44119..06b52e5 100644 --- a/src/drivers/lenovo/lenovo.h +++ b/src/drivers/lenovo/lenovo.h @@ -1,3 +1,4 @@ int drivers_lenovo_is_wacom_present(void); void drivers_lenovo_serial_ports_ssdt_generate(const char *scope, - int have_dock_serial); + int have_dock_serial, + int have_infrared); diff --git a/src/drivers/lenovo/wacom.c b/src/drivers/lenovo/wacom.c index 96ade66..edf191b 100644 --- a/src/drivers/lenovo/wacom.c +++ b/src/drivers/lenovo/wacom.c @@ -92,7 +92,8 @@ drivers_lenovo_is_wacom_present(void) void drivers_lenovo_serial_ports_ssdt_generate(const char *scope, - int have_dock_serial) + int have_dock_serial, + int have_infrared) { int scopelen, devicelen, reslen, methodlen; @@ -134,6 +135,47 @@ drivers_lenovo_serial_ports_ssdt_generate(const char *scope, scopelen += devicelen; } + if (have_infrared) { + /* Device op. */ + scopelen += acpigen_emit_byte(0x5b); + scopelen += acpigen_emit_byte(0x82); + devicelen = acpigen_write_len_f(); + devicelen += acpigen_emit_namestring("FIR"); + + devicelen += acpigen_write_name("_HID"); + devicelen += acpigen_emit_eisaid("IBM0071"); + devicelen += acpigen_write_name("_CID"); + devicelen += acpigen_emit_eisaid("PNP0511"); + devicelen += acpigen_write_name("_UID"); + + /* One */ + devicelen += acpigen_write_byte(0x1); + devicelen += acpigen_write_name("_CRS"); + + reslen = acpigen_write_resourcetemplate_header(); + reslen += acpigen_write_io16(0x2f8, 0x2f8, 1, 8, 1); + reslen += acpigen_write_irq(0x08); + + devicelen += reslen; + devicelen += acpigen_write_resourcetemplate_footer(reslen); + + /* method op */ + devicelen += acpigen_emit_byte(0x14); + methodlen = acpigen_write_len_f(); + methodlen += acpigen_emit_namestring("_STA"); + /* no fnarg */ + methodlen += acpigen_emit_byte(0x00); + /* return */ + methodlen += acpigen_emit_byte(0xa4); + methodlen += acpigen_write_byte(0xf); + acpigen_patch_len(methodlen); + + devicelen += methodlen; + + acpigen_patch_len(devicelen - 1); + scopelen += devicelen; + } + if (have_dock_serial) { /* Device op. */ scopelen += acpigen_emit_byte(0x5b); diff --git a/src/mainboard/lenovo/x201/acpi_tables.c b/src/mainboard/lenovo/x201/acpi_tables.c index b6e99dd..710e369 100644 --- a/src/mainboard/lenovo/x201/acpi_tables.c +++ b/src/mainboard/lenovo/x201/acpi_tables.c @@ -94,7 +94,7 @@ unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { generate_cpu_entries(); - drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 0); + drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 0, 0); return (unsigned long)(acpigen_get_current()); } diff --git a/src/mainboard/lenovo/x60/acpi_tables.c b/src/mainboard/lenovo/x60/acpi_tables.c index cf07067..c8fce7f 100644 --- a/src/mainboard/lenovo/x60/acpi_tables.c +++ b/src/mainboard/lenovo/x60/acpi_tables.c @@ -87,7 +87,7 @@ unsigned long acpi_fill_madt(unsigned long current) unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { generate_cpu_entries(); - drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 1); + drivers_lenovo_serial_ports_ssdt_generate("\\_SB.PCI0.LPCB", 1, 1); return (unsigned long) (acpigen_get_current()); } diff --git a/src/mainboard/lenovo/x60/devicetree.cb b/src/mainboard/lenovo/x60/devicetree.cb index 81648bd..b3dd514 100644 --- a/src/mainboard/lenovo/x60/devicetree.cb +++ b/src/mainboard/lenovo/x60/devicetree.cb @@ -125,6 +125,10 @@ chip northbridge/intel/i945 chip superio/nsc/pc87382 device pnp 164e.2 on # IR io 0x60 = 0x2f8 + irq 0x29 = 0xb0 + irq 0x70 = 0x3 + drq 0x74 = 0x1 + irq 0xf0 = 0x82 end device pnp 164e.3 on # Digitizer diff --git a/src/mainboard/lenovo/x60/romstage.c b/src/mainboard/lenovo/x60/romstage.c index 1198fb2..8eca464 100644 --- a/src/mainboard/lenovo/x60/romstage.c +++ b/src/mainboard/lenovo/x60/romstage.c @@ -86,7 +86,7 @@ static void ich7_enable_lpc(void) // decode range pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x80, 0x0210); // decode range - pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1f0d); + pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1f0f); /* range 0x1600 - 0x167f */ pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x84, 0x1601);
1
0
0
0
New patch to review for coreboot: 1814168 nehalem: Remove fake_vbt copying.
by Vladimir Serbinenko
31 May '14
31 May '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5895
-gerrit commit 1814168cd069b0223d18b11be7e531da020523c1 Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sat May 31 22:26:42 2014 +0200 nehalem: Remove fake_vbt copying. Instead generate simple VBT in code. Tested on X201. Change-Id: I2244053edd24c22694161d9bf5f7f2f3eb4e2f57 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- src/mainboard/lenovo/x201/Makefile.inc | 1 - src/mainboard/lenovo/x201/gma.c | 514 -------------------------- src/mainboard/packardbell/ms2290/Makefile.inc | 1 - src/mainboard/packardbell/ms2290/gma.c | 272 -------------- src/northbridge/intel/nehalem/gma.c | 121 +++++- 5 files changed, 115 insertions(+), 794 deletions(-) diff --git a/src/mainboard/lenovo/x201/Makefile.inc b/src/mainboard/lenovo/x201/Makefile.inc index 285e0d0..db291f3 100644 --- a/src/mainboard/lenovo/x201/Makefile.inc +++ b/src/mainboard/lenovo/x201/Makefile.inc @@ -21,5 +21,4 @@ smm-$(CONFIG_HAVE_SMI_HANDLER) += dock.c smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c romstage-y += dock.c ramstage-y += dock.c -ramstage-y += gma.c diff --git a/src/mainboard/lenovo/x201/gma.c b/src/mainboard/lenovo/x201/gma.c deleted file mode 100644 index f417905..0000000 --- a/src/mainboard/lenovo/x201/gma.c +++ /dev/null @@ -1,514 +0,0 @@ -#include <arch/io.h> -#include <device/device.h> -#include <device/pci.h> -#include <device/pci_ids.h> -#include <device/pci_ops.h> - -#include "northbridge/intel/nehalem/nehalem.h" - -/* This array contains the information on flat panel. When using native - graphics init coreboot copies it to where VGA Option ROM would be so - that OS can find it and able to use internal display. This contains no - executable code and is just information on the panel. - */ - -unsigned char fake_vbt[] = { - 0x24, 0x56, 0x42, 0x54, 0x20, 0x49, 0x52, 0x4f, 0x4e, 0x4c, 0x41, 0x4b, - 0x45, 0x2d, 0x4d, 0x4f, - 0x42, 0x49, 0x4c, 0x45, 0x64, 0x00, 0x30, 0x00, 0x8e, 0x0f, 0x48, 0x00, - 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x42, 0x49, 0x4f, 0x53, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42, 0x4c, - 0x4f, 0x43, 0x4b, 0x20, - 0x9c, 0x00, 0x16, 0x00, 0x5e, 0x0f, 0xfe, 0xea, 0x00, 0x00, 0x64, 0x01, - 0x01, 0x0f, 0x0d, 0x32, - 0x30, 0x32, 0x36, 0x44, 0x43, 0x49, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x6c, - 0x28, 0x52, 0x29, 0x49, - 0x72, 0x6f, 0x6e, 0x6c, 0x61, 0x6b, 0x65, 0x20, 0x4d, 0x6f, 0x62, 0x69, - 0x6c, 0x65, 0x20, 0x50, - 0x43, 0x49, 0x20, 0x41, 0x63, 0x63, 0x65, 0x6c, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x64, 0x20, 0x53, - 0x56, 0x47, 0x41, 0x20, 0x42, 0x49, 0x4f, 0x53, 0x0d, 0x0a, 0x42, 0x75, - 0x69, 0x6c, 0x64, 0x20, - 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x3a, 0x20, 0x32, 0x30, 0x32, 0x36, - 0x20, 0x50, 0x43, 0x20, - 0x31, 0x34, 0x2e, 0x33, 0x34, 0x20, 0x20, 0x30, 0x39, 0x2f, 0x32, 0x38, - 0x20, 0x2f, 0x32, 0x30, - 0x31, 0x30, 0x20, 0x20, 0x32, 0x32, 0x3a, 0x32, 0x30, 0x3a, 0x35, 0x32, - 0x0d, 0x0a, 0x44, 0x45, - 0x43, 0x4f, 0x4d, 0x50, 0x49, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x20, - 0x4f, 0x52, 0x20, 0x44, - 0x49, 0x53, 0x41, 0x53, 0x53, 0x45, 0x4d, 0x42, 0x4c, 0x59, 0x20, 0x50, - 0x52, 0x4f, 0x48, 0x49, - 0x42, 0x49, 0x54, 0x45, 0x44, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x43, 0x6f, - 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, - 0x32, 0x30, 0x30, 0x30, - 0x2d, 0x32, 0x30, 0x30, 0x33, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, - 0x43, 0x6f, 0x72, 0x70, - 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x73, - 0x20, 0x52, 0x65, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0d, 0x0a, 0x0d, 0x0a, 0x00, 0x00, - 0xc0, 0x03, 0x08, 0x04, - 0x00, 0x00, 0x00, 0x01, 0x05, 0x00, 0x07, 0x03, 0x00, 0x01, 0x19, 0xfe, - 0x32, 0x00, 0x44, 0x04, - 0x40, 0x06, 0x04, 0x02, 0x09, 0x01, 0x08, 0x0a, 0x02, 0x08, 0x0c, 0x04, - 0x08, 0x03, 0x01, 0x02, - 0x05, 0x01, 0x04, 0x0d, 0x01, 0x04, 0x0b, 0x01, 0x02, 0x07, 0x01, 0x04, - 0x15, 0x01, 0x04, 0x45, - 0x01, 0x04, 0x0e, 0x04, 0x08, 0x46, 0x04, 0x40, 0x28, 0x20, 0x08, 0x48, - 0x40, 0x08, 0x10, 0x00, - 0x02, 0x0d, 0x01, 0x02, 0x04, 0x00, 0x00, 0x21, 0x08, 0x00, 0x22, 0x10, - 0x00, 0x20, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xcd, 0x04, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc6, - 0x68, 0x00, 0x20, 0x00, - 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xe3, 0x08, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, - 0x00, 0x07, 0x20, 0x01, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, - 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x03, 0x01, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x30, 0x32, 0x34, 0x36, 0x38, - 0x3a, 0x3c, 0x40, 0x42, - 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, - 0x80, 0x81, 0x82, 0x83, - 0x84, 0x1a, 0x00, 0xfe, 0xad, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x30, 0x00, 0xbf, - 0x06, 0x1e, 0x00, 0x59, - 0x03, 0x28, 0x00, 0x86, 0x03, 0x02, 0x00, 0x90, 0x03, 0x38, 0x00, 0xd1, - 0x03, 0xc8, 0x00, 0x1f, - 0x06, 0x30, 0x00, 0x52, 0x06, 0x18, 0x00, 0x6d, 0x06, 0x18, 0x00, 0x88, - 0x06, 0x18, 0x00, 0x8b, - 0x07, 0x08, 0x00, 0xcf, 0x07, 0x12, 0x00, 0xe1, 0x07, 0x12, 0x00, 0xf3, - 0x07, 0x12, 0x00, 0x05, - 0x08, 0x12, 0x00, 0x1a, 0x08, 0x0a, 0x00, 0x24, 0x08, 0x0a, 0x00, 0x2e, - 0x08, 0x0a, 0x00, 0x38, - 0x08, 0x0a, 0x00, 0x45, 0x08, 0x0a, 0x00, 0x4f, 0x08, 0x0a, 0x00, 0x59, - 0x08, 0x0a, 0x00, 0x63, - 0x08, 0x0a, 0x00, 0x75, 0x08, 0x0a, 0x00, 0x7f, 0x08, 0x0a, 0x00, 0x89, - 0x08, 0x0a, 0x00, 0x93, - 0x08, 0x0a, 0x00, 0x9d, 0x08, 0x0a, 0x00, 0xa7, 0x08, 0x0a, 0x00, 0xb1, - 0x08, 0x0a, 0x00, 0xbb, - 0x08, 0x0a, 0x00, 0xc5, 0x08, 0x0a, 0x00, 0xcf, 0x08, 0x0a, 0x00, 0xd9, - 0x08, 0x0a, 0x00, 0xe3, - 0x08, 0x0a, 0x00, 0xed, 0x08, 0x0a, 0x00, 0xf7, 0x08, 0x0a, 0x00, 0x01, - 0x09, 0x0a, 0x00, 0x0b, - 0x09, 0x0a, 0x00, 0x06, 0x5d, 0x00, 0xfc, 0xff, 0x02, 0x80, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x07, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x04, 0x00, 0x8e, 0x29, 0x00, 0x80, 0x9c, 0x01, 0x07, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x9c, 0x11, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x07, 0x07, 0x00, 0xfe, 0xff, 0xce, 0x18, 0x00, 0xff, - 0xff, 0x08, 0x3d, 0x00, - 0xfc, 0xff, 0x02, 0x40, 0xf0, 0x04, 0x00, 0x01, 0x00, 0x00, 0x01, 0x44, - 0xf0, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xf0, 0x04, 0x00, 0x00, - 0x00, 0x03, 0x03, 0x50, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, - 0xf0, 0x04, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x58, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x0a, 0xcb, 0x00, - 0x0a, 0x80, 0x04, 0x60, 0x03, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x00, - 0x05, 0x58, 0x02, 0xff, - 0xff, 0xff, 0xbf, 0xff, 0xff, 0x00, 0x05, 0xc0, 0x03, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0x80, - 0x07, 0xa0, 0x05, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x40, 0x07, 0x70, 0x05, 0xff, 0xff, 0xff, 0xbf, 0xff, - 0xff, 0x00, 0x07, 0x40, - 0x05, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x80, 0x02, 0xe0, 0x01, 0xff, - 0x1b, 0xfe, 0x07, 0xff, - 0xff, 0x20, 0x03, 0x58, 0x02, 0xff, 0x1b, 0xfe, 0x07, 0xff, 0xff, 0x00, - 0x04, 0x00, 0x03, 0xff, - 0x1b, 0xfe, 0x07, 0xff, 0xff, 0x40, 0x06, 0xb0, 0x04, 0xff, 0x1b, 0xff, - 0x07, 0xff, 0xff, 0x00, - 0x08, 0x00, 0x06, 0xff, 0xdb, 0xff, 0x07, 0xff, 0xff, 0x00, 0x05, 0x00, - 0x04, 0xff, 0x1b, 0xfe, - 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x0b, - 0xc7, 0x00, 0x21, 0x40, - 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0x05, 0x70, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x02, 0x05, 0x72, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x00, 0x4a, 0x00, 0x04, 0x00, - 0x03, 0x08, 0x3c, 0x84, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x0d, 0x03, 0x00, - 0xf7, 0x03, 0xc8, 0x0e, - 0x09, 0x00, 0x01, 0x90, 0x05, 0x5a, 0x00, 0xec, 0x05, 0x2d, 0x00, 0x0f, - 0x8b, 0x00, 0x09, 0x0a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84, 0x00, - 0x10, 0x00, 0x03, 0x08, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x08, 0x00, 0x40, 0x00, - 0x00, 0x40, 0x08, 0x00, 0x20, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, - 0x00, 0x03, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x08, - 0x00, 0x40, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, - 0x03, 0x01, 0x00, 0x00, - 0x01, 0x08, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x01, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x04, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x08, - 0x00, 0x02, 0x00, 0x00, 0x01, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x08, - 0x00, 0x00, 0x00, 0x00, - 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, - 0x0c, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x20, - 0x00, 0x0f, 0x02, 0x09, - 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x14, 0x9e, 0x00, - 0x06, 0x1a, 0x03, 0xff, 0x00, 0x03, 0xe0, 0x01, 0x07, 0x3c, 0x40, 0x0b, - 0x00, 0xc0, 0x30, 0xe0, - 0x14, 0x10, 0x18, 0x48, 0x36, 0x00, 0x05, 0xa3, 0x10, 0x00, 0x00, 0x18, - 0x03, 0xff, 0xc0, 0x03, - 0x58, 0x02, 0x07, 0x3c, 0xc8, 0x11, 0xc0, 0x00, 0x31, 0x58, 0x18, 0x20, - 0x20, 0x60, 0x36, 0x00, - 0x05, 0xa3, 0x10, 0x00, 0x00, 0x18, 0x03, 0xff, 0x00, 0x05, 0x20, 0x03, - 0x07, 0x3c, 0x9e, 0x20, - 0x00, 0x90, 0x51, 0x20, 0x1f, 0x30, 0x48, 0x80, 0x36, 0x00, 0x05, 0xa3, - 0x10, 0x00, 0x00, 0x18, - 0x03, 0xff, 0x00, 0x03, 0xe0, 0x01, 0x07, 0x32, 0x2c, 0x09, 0x00, 0xa0, - 0x30, 0xe0, 0x1a, 0x10, - 0x18, 0x10, 0x36, 0x00, 0x05, 0xa3, 0x10, 0x00, 0x00, 0x18, 0x03, 0xff, - 0xc0, 0x03, 0x58, 0x02, - 0x07, 0x32, 0xb2, 0x0d, 0xc0, 0xa0, 0x30, 0x58, 0x1a, 0x20, 0x18, 0x10, - 0x36, 0x00, 0x05, 0xa3, - 0x10, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3c, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x16, 0x4b, - 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x30, 0x84, 0x0e, 0x00, 0x00, 0x4c, 0x46, 0x50, 0x5f, - 0x50, 0x61, 0x6e, 0x65, - 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, - 0x65, 0x6c, 0x4e, 0x61, - 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, - 0x61, 0x6d, 0x65, 0x4c, - 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, - 0x17, 0x48, 0x00, 0x64, - 0x19, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 0x36, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x2a, 0x00, 0x98, 0x51, 0x00, 0x30, 0x40, 0x30, 0x70, 0x13, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0xa8, 0x2f, 0x78, 0xe0, 0x51, 0x1a, 0x26, 0x40, 0x58, - 0x98, 0x13, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1e, 0x48, 0x3f, 0x40, 0x30, 0x62, 0xb0, 0x32, - 0x40, 0x40, 0xc0, 0x13, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x18, 0x28, 0x00, 0x36, 0x7f, - 0x03, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x36, 0x7f, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x36, 0x7f, - 0x01, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x36, 0x7f, 0x06, 0x00, - 0x04, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x19, 0x28, 0x00, 0x19, 0x00, 0xfa, 0x00, 0xfa, 0x00, 0x19, - 0x00, 0x90, 0x01, 0x20, - 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xc8, 0x00, 0x40, 0x00, 0x40, - 0x00, 0x40, 0x00, 0x40, - 0x00, 0x2c, 0x01, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x2c, - 0x01, 0x1a, 0x02, 0x00, - 0x00, 0x40, 0x1b, 0xc8, 0x00, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, - 0x01, 0x88, 0x13, 0xd0, - 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, - 0x00, 0xd0, 0x07, 0xf4, - 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, - 0x13, 0xd0, 0x07, 0x0a, - 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, - 0x07, 0xf4, 0x01, 0x88, - 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, - 0x07, 0x0a, 0x00, 0xd0, - 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, - 0x01, 0x88, 0x13, 0xd0, - 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, - 0x00, 0xd0, 0x07, 0xf4, - 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, - 0x13, 0xd0, 0x07, 0x0a, - 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, - 0x07, 0xf4, 0x01, 0x88, - 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, - 0x07, 0x0a, 0x00, 0xd0, - 0x07, 0xf4, 0x01, 0x88, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x18, 0x00, - 0x01, 0x00, 0x73, 0x00, 0x54, 0x05, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0a, 0x00, 0x00, 0x29, 0x94, 0x00, 0x03, - 0xf2, 0x09, 0x20, 0x18, - 0x0a, 0x12, 0x2a, 0x0a, 0x0a, 0x34, 0x0a, 0x20, 0x5a, 0x0a, 0x12, 0x6c, - 0x0a, 0x0a, 0x76, 0x0a, - 0x20, 0x9c, 0x0a, 0x12, 0xae, 0x0a, 0x0a, 0xb8, 0x0a, 0x20, 0xde, 0x0a, - 0x12, 0xf0, 0x0a, 0x0a, - 0xfa, 0x0a, 0x20, 0x20, 0x0b, 0x12, 0x32, 0x0b, 0x0a, 0x3c, 0x0b, 0x20, - 0x62, 0x0b, 0x12, 0x74, - 0x0b, 0x0a, 0x7e, 0x0b, 0x20, 0xa4, 0x0b, 0x12, 0xb6, 0x0b, 0x0a, 0xc0, - 0x0b, 0x20, 0xe6, 0x0b, - 0x12, 0xf8, 0x0b, 0x0a, 0x02, 0x0c, 0x20, 0x28, 0x0c, 0x12, 0x3a, 0x0c, - 0x0a, 0x44, 0x0c, 0x20, - 0x6a, 0x0c, 0x12, 0x7c, 0x0c, 0x0a, 0x86, 0x0c, 0x20, 0xac, 0x0c, 0x12, - 0xbe, 0x0c, 0x0a, 0xc8, - 0x0c, 0x20, 0xee, 0x0c, 0x12, 0x00, 0x0d, 0x0a, 0x0a, 0x0d, 0x20, 0x30, - 0x0d, 0x12, 0x42, 0x0d, - 0x0a, 0x4c, 0x0d, 0x20, 0x72, 0x0d, 0x12, 0x84, 0x0d, 0x0a, 0x8e, 0x0d, - 0x20, 0xb4, 0x0d, 0x12, - 0xc6, 0x0d, 0x0a, 0xd0, 0x0d, 0x20, 0xf6, 0x0d, 0x12, 0x08, 0x0e, 0x0a, - 0x12, 0x0e, 0x0d, 0x2a, - 0xf0, 0x04, 0x80, 0x02, 0xe0, 0x01, 0x80, 0x11, 0x0e, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x08, 0x72, - 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x0c, 0x72, 0x0c, 0x00, 0xc4, 0x09, - 0xfa, 0x00, 0x10, 0x72, - 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0xd6, 0x09, 0x80, 0x90, - 0x20, 0xe0, 0x1d, 0x10, - 0x08, 0x60, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, - 0x01, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x05, 0x20, 0x03, 0x80, 0x11, 0x0e, 0x00, - 0x00, 0x03, 0x00, 0x00, - 0x08, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x0c, 0x72, 0x0c, 0x00, - 0xc4, 0x09, 0xfa, 0x00, - 0x10, 0x72, 0x0c, 0x00, 0x03, 0x0f, 0x27, 0x00, 0xff, 0xff, 0x12, 0x1b, - 0x00, 0x80, 0x50, 0x20, - 0x14, 0x30, 0x18, 0x20, 0x44, 0x00, 0x05, 0xa3, 0x10, 0x00, 0x00, 0x1f, - 0x30, 0xae, 0x11, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa0, 0x05, 0x84, 0x03, 0x80, 0x11, - 0x0e, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x0c, 0x72, - 0x0c, 0x00, 0xc4, 0x09, - 0xfa, 0x00, 0x10, 0x72, 0x0c, 0x00, 0x03, 0x0f, 0x27, 0x00, 0xff, 0xff, - 0xf0, 0x1c, 0xa0, 0xa0, - 0x50, 0x84, 0x1a, 0x30, 0x18, 0x10, 0x36, 0x00, 0x05, 0xa3, 0x10, 0x00, - 0x00, 0x18, 0x30, 0xae, - 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x05, 0x20, 0x03, - 0x80, 0x11, 0x0e, 0x00, - 0x3c, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, - 0x0c, 0x72, 0x0c, 0x00, - 0xc4, 0x09, 0xfa, 0x00, 0x10, 0x72, 0x0c, 0x00, 0x03, 0x0f, 0x27, 0x00, - 0xff, 0xff, 0x64, 0x19, - 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 0x36, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, - 0x30, 0xae, 0x31, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x05, - 0x20, 0x03, 0x80, 0x11, - 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xc4, 0x09, - 0xfa, 0x00, 0x0c, 0x72, - 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x10, 0x72, 0x0c, 0x00, 0x03, 0x0f, - 0x27, 0x00, 0xff, 0xff, - 0xc7, 0x1b, 0x00, 0xa0, 0x50, 0x20, 0x17, 0x30, 0x30, 0x20, 0x36, 0x00, - 0x05, 0xa3, 0x10, 0x00, - 0x00, 0x18, 0x30, 0xae, 0x11, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, - 0x00, 0x05, 0x20, 0x03, - 0x80, 0x11, 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, - 0xc4, 0x09, 0xfa, 0x00, - 0x0c, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x10, 0x72, 0x0c, 0x00, - 0x03, 0x0f, 0x27, 0x00, - 0xff, 0xff, 0xc0, 0x1b, 0x00, 0xab, 0x50, 0x20, 0x10, 0x30, 0x34, 0x40, - 0x33, 0x00, 0x05, 0xa3, - 0x10, 0x00, 0x00, 0x19, 0x30, 0xae, 0x11, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x13, 0x00, 0x05, - 0x20, 0x03, 0x80, 0x11, 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x08, 0x72, - 0x0c, 0x00, 0xc4, 0x09, - 0xfa, 0x00, 0x0c, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x10, 0x72, - 0x0c, 0x00, 0x03, 0x0f, - 0x27, 0x00, 0xff, 0xff, 0xcc, 0x1b, 0x00, 0xa1, 0x50, 0x20, 0x17, 0x30, - 0x31, 0x20, 0x36, 0x00, - 0x05, 0xa3, 0x10, 0x00, 0x00, 0x19, 0x30, 0xae, 0x10, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x12, - 0x00, 0x05, 0x00, 0x03, 0x80, 0x11, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x08, 0x72, 0x0c, 0x00, - 0xc4, 0x09, 0xfa, 0x00, 0x0c, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, - 0x10, 0x72, 0x0c, 0x00, - 0x03, 0x0f, 0x27, 0x00, 0xff, 0xff, 0xa9, 0x1a, 0x00, 0xa0, 0x50, 0x00, - 0x0a, 0x30, 0x30, 0x20, - 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x90, - 0x08, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x90, 0x06, 0x1a, 0x04, 0x80, 0x11, 0x0e, 0x00, 0x3c, 0x03, - 0x00, 0x00, 0x08, 0x72, - 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x0c, 0x72, 0x0c, 0x00, 0xc4, 0x09, - 0xfa, 0x00, 0x10, 0x72, - 0x0c, 0x00, 0x03, 0x0f, 0x27, 0x00, 0xff, 0xff, 0x7c, 0x2e, 0x90, 0xa0, - 0x60, 0x1a, 0x1e, 0x40, - 0x30, 0x20, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, - 0x04, 0x90, 0x09, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x80, 0x07, 0xb0, 0x04, 0x80, 0x11, 0x0e, 0x00, - 0x3c, 0x03, 0x00, 0x00, - 0x08, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x0c, 0x72, 0x0c, 0x00, - 0xc4, 0x09, 0xfa, 0x00, - 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0x28, 0x3c, - 0x80, 0xa0, 0x70, 0xb0, - 0x23, 0x40, 0x30, 0x20, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, - 0x36, 0x7f, 0x05, 0x90, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x03, 0x80, 0x11, - 0x0e, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x0c, 0x72, - 0x0c, 0x00, 0xc4, 0x09, - 0xfa, 0x00, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, - 0x64, 0x19, 0x00, 0x40, - 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1e, 0x36, 0x7f, - 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x03, - 0x80, 0x11, 0x0e, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, - 0x0c, 0x72, 0x0c, 0x00, - 0xc4, 0x09, 0xfa, 0x00, 0x10, 0x72, 0x0c, 0x00, 0x03, 0x0f, 0x27, 0x00, - 0xff, 0xff, 0x64, 0x19, - 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 0x36, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1e, - 0x36, 0x7f, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, - 0x00, 0x03, 0x80, 0x11, - 0x0e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xc4, 0x09, - 0xfa, 0x00, 0x0c, 0x72, - 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x10, 0x72, 0x0c, 0x00, 0x03, 0x0f, - 0x27, 0x00, 0xff, 0xff, - 0x64, 0x19, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 0x36, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0x00, 0x05, 0x20, 0x03, - 0x80, 0x11, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, - 0xc4, 0x09, 0xfa, 0x00, - 0x0c, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x10, 0x72, 0x0c, 0x00, - 0x03, 0x0f, 0x27, 0x00, - 0xff, 0xff, 0xea, 0x1a, 0x00, 0xa0, 0x50, 0x20, 0x17, 0x30, 0x0c, 0x30, - 0x43, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x00, 0x05, - 0x58, 0x02, 0x80, 0x11, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x72, - 0x0c, 0x00, 0xc4, 0x09, - 0xfa, 0x00, 0x0c, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, 0x10, 0x72, - 0x0c, 0x00, 0x03, 0x0f, - 0x27, 0x00, 0xff, 0xff, 0x06, 0x18, 0x00, 0x70, 0x51, 0x58, 0x15, 0x20, - 0x38, 0x80, 0x13, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x00, 0x0f, 0x00, - 0x00, 0x00, 0x00, 0x0c, - 0x00, 0x08, 0x00, 0x06, 0x80, 0x11, 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, - 0x08, 0x72, 0x0c, 0x00, - 0xc4, 0x09, 0xfa, 0x00, 0x0c, 0x72, 0x0c, 0x00, 0xc4, 0x09, 0xfa, 0x00, - 0x10, 0x72, 0x0c, 0x00, - 0x03, 0x0f, 0x27, 0x00, 0xff, 0xff, 0x29, 0x40, 0x00, 0x60, 0x80, 0x00, - 0x13, 0x60, 0x10, 0x10, - 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x00, - 0x10, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x70, 0x61, 0x6e, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4d, - 0x50, 0x57, 0x58, 0x47, 0x41, 0x32, 0x32, 0x30, 0x4e, 0x49, 0x54, 0x00, - 0x4d, 0x50, 0x57, 0x58, - 0x47, 0x41, 0x2b, 0x32, 0x35, 0x30, 0x4e, 0x49, 0x54, 0x43, 0x5f, 0x44, - 0x42, 0x34, 0x30, 0x30, - 0x4e, 0x49, 0x54, 0x00, 0x00, 0x00, 0x43, 0x5f, 0x4d, 0x54, 0x50, 0x33, - 0x30, 0x30, 0x4e, 0x49, - 0x54, 0x00, 0x00, 0x43, 0x5f, 0x50, 0x50, 0x32, 0x32, 0x30, 0x4e, 0x49, - 0x54, 0x00, 0x00, 0x00, - 0x4d, 0x50, 0x43, 0x5f, 0x43, 0x43, 0x46, 0x4c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x70, 0x61, 0x6e, - 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, - 0x6e, 0x65, 0x6c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x6e, 0x65, 0x6c, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x6e, 0x65, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x70, 0x61, 0x6e, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x70, 0x61, - 0x6e, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0x61, 0x6e, 0x65, 0x6c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x6e, 0x65, - 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x6e, 0x65, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x2b, 0x61, 0x00, 0x06, 0x4e, 0xdc, 0x00, 0x00, 0x58, 0xaa, - 0x4a, 0x71, 0x02, 0x04, - 0x58, 0xaa, 0x4a, 0xa5, 0x00, 0x04, 0x58, 0xaa, 0x4a, 0x96, 0x00, 0x02, - 0x58, 0xaa, 0x4a, 0x5a, - 0x00, 0x04, 0x58, 0xaa, 0x4a, 0xff, 0x00, 0x05, 0x58, 0xaa, 0x4a, 0xa5, - 0x00, 0x16, 0x58, 0xaa, - 0x4e, 0xdc, 0x00, 0x00, 0x58, 0xaa, 0x4e, 0xdc, 0x00, 0x00, 0x58, 0xaa, - 0x4e, 0xdc, 0x00, 0x00, - 0x58, 0xaa, 0x4e, 0xdc, 0x00, 0x00, 0x58, 0xaa, 0x4e, 0xdc, 0x00, 0x00, - 0x58, 0xaa, 0x4e, 0xdc, - 0x00, 0x00, 0x58, 0xaa, 0x4e, 0xdc, 0x00, 0x00, 0x58, 0xaa, 0x4e, 0xdc, - 0x00, 0x00, 0x58, 0xaa, - 0x4e, 0xdc, 0x00, 0x00, 0x58, 0xaa, 0x2c, 0x15, 0x00, 0x09, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, -}; diff --git a/src/mainboard/packardbell/ms2290/Makefile.inc b/src/mainboard/packardbell/ms2290/Makefile.inc index a9db8d8..b47ace2 100644 --- a/src/mainboard/packardbell/ms2290/Makefile.inc +++ b/src/mainboard/packardbell/ms2290/Makefile.inc @@ -18,4 +18,3 @@ ## smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c -ramstage-y += gma.c diff --git a/src/mainboard/packardbell/ms2290/gma.c b/src/mainboard/packardbell/ms2290/gma.c deleted file mode 100644 index 540d858..0000000 --- a/src/mainboard/packardbell/ms2290/gma.c +++ /dev/null @@ -1,272 +0,0 @@ -#include <arch/io.h> -#include <device/device.h> -#include <device/pci.h> -#include <device/pci_ids.h> -#include <device/pci_ops.h> - -#include "northbridge/intel/nehalem/nehalem.h" - -/* This array contains the information on flat panel. When using native - graphics init coreboot copies it to where VGA Option ROM would be so - that OS can find it and able to use internal display. This contains no - executable code and is just information on the panel. - */ - -unsigned char fake_vbt[] = { -0x24, 0x56, 0x42, 0x54, 0x20, 0x49, 0x52, 0x4f, 0x4e, 0x4c, 0x41, 0x4b, 0x45, 0x2d, 0x4d, 0x4f, -0x42, 0x49, 0x4c, 0x45, 0x64, 0x00, 0x30, 0x00, 0xc3, 0x10, 0xa4, 0x00, 0x30, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x42, 0x49, 0x4f, 0x53, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x20, -0x9b, 0x00, 0x16, 0x00, 0x93, 0x10, 0xfe, 0xea, 0x00, 0x00, 0x64, 0x01, 0x01, 0x0f, 0x0d, 0x31, -0x39, 0x39, 0x34, 0x49, 0x6e, 0x74, 0x65, 0x6c, 0x28, 0x52, 0x29, 0x49, 0x72, 0x6f, 0x6e, 0x6c, -0x61, 0x6b, 0x65, 0x20, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x20, 0x50, 0x43, 0x49, 0x20, 0x41, -0x63, 0x63, 0x65, 0x6c, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x53, 0x56, 0x47, 0x41, 0x20, -0x42, 0x49, 0x4f, 0x53, 0x0d, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x20, 0x4e, 0x75, 0x6d, 0x62, -0x65, 0x72, 0x3a, 0x20, 0x69, 0x6c, 0x6d, 0x31, 0x39, 0x39, 0x34, 0x31, 0x2e, 0x6a, 0x76, 0x37, -0x20, 0x50, 0x43, 0x20, 0x31, 0x34, 0x2e, 0x33, 0x34, 0x20, 0x20, 0x30, 0x35, 0x2f, 0x32, 0x36, -0x2f, 0x32, 0x30, 0x31, 0x30, 0x20, 0x20, 0x31, 0x39, 0x3a, 0x32, 0x32, 0x3a, 0x30, 0x33, 0x0d, -0x0a, 0x44, 0x45, 0x43, 0x4f, 0x4d, 0x50, 0x49, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x4f, -0x52, 0x20, 0x44, 0x49, 0x53, 0x41, 0x53, 0x53, 0x45, 0x4d, 0x42, 0x4c, 0x59, 0x20, 0x50, 0x52, -0x4f, 0x48, 0x49, 0x42, 0x49, 0x54, 0x45, 0x44, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, -0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x30, 0x30, -0x2d, 0x32, 0x30, 0x30, 0x33, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x70, -0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x52, 0x65, 0x73, -0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0d, 0x0a, 0x0d, 0x0a, 0x00, 0x00, 0xc0, 0x03, 0x08, 0x04, -0x01, 0x00, 0x00, 0x01, 0x05, 0x00, 0x07, 0x01, 0x00, 0x01, 0x01, 0xfe, 0x20, 0x00, 0x01, 0x01, -0x08, 0x08, 0x04, 0x04, 0x09, 0x08, 0x0c, 0x08, 0x05, 0x04, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0d, -0x01, 0x02, 0x04, 0x00, 0x00, 0x21, 0x08, 0x00, 0x22, 0x10, 0x00, 0x4c, 0x46, 0x50, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0xc0, 0xd1, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xd2, 0x60, 0x00, 0x20, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe4, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05, -0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, -0x00, 0x00, 0x04, 0x1c, 0x00, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x40, 0x42, 0x44, 0x46, -0x48, 0x4a, 0x4c, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x80, 0x81, 0x82, 0x83, 0x84, 0x1a, -0x00, 0xfe, 0xac, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, -0x01, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x20, 0x00, 0xf4, 0x07, 0x1e, 0x00, 0x8e, 0x04, 0x28, 0x00, -0xbb, 0x04, 0x02, 0x00, 0xc5, 0x04, 0x38, 0x00, 0x06, 0x05, 0xc8, 0x00, 0x54, 0x07, 0x30, 0x00, -0x87, 0x07, 0x18, 0x00, 0xa2, 0x07, 0x18, 0x00, 0xbd, 0x07, 0x18, 0x00, 0xc0, 0x08, 0x08, 0x00, -0x04, 0x09, 0x12, 0x00, 0x16, 0x09, 0x12, 0x00, 0x28, 0x09, 0x12, 0x00, 0x3a, 0x09, 0x12, 0x00, -0x4f, 0x09, 0x0a, 0x00, 0x59, 0x09, 0x0a, 0x00, 0x63, 0x09, 0x0a, 0x00, 0x6d, 0x09, 0x0a, 0x00, -0x7a, 0x09, 0x0a, 0x00, 0x84, 0x09, 0x0a, 0x00, 0x8e, 0x09, 0x0a, 0x00, 0x98, 0x09, 0x0a, 0x00, -0xaa, 0x09, 0x0a, 0x00, 0xb4, 0x09, 0x0a, 0x00, 0xbe, 0x09, 0x0a, 0x00, 0xc8, 0x09, 0x0a, 0x00, -0xd2, 0x09, 0x0a, 0x00, 0xdc, 0x09, 0x0a, 0x00, 0xe6, 0x09, 0x0a, 0x00, 0xf0, 0x09, 0x0a, 0x00, -0xfa, 0x09, 0x0a, 0x00, 0x04, 0x0a, 0x0a, 0x00, 0x0e, 0x0a, 0x0a, 0x00, 0x18, 0x0a, 0x0a, 0x00, -0x22, 0x0a, 0x0a, 0x00, 0x2c, 0x0a, 0x0a, 0x00, 0x36, 0x0a, 0x0a, 0x00, 0x40, 0x0a, 0x0a, 0x00, -0x06, 0xa5, 0x01, 0xfc, 0xff, 0x02, 0x14, 0x60, 0x0c, 0x00, 0x80, 0x00, 0x80, 0x04, 0x40, 0x60, -0x0c, 0x00, 0x07, 0x0d, 0x03, 0x00, 0x44, 0x60, 0x0c, 0x00, 0x07, 0x0d, 0x03, 0x00, 0x18, 0x60, -0x0c, 0x00, 0x80, 0x00, 0x80, 0x04, 0x48, 0x60, 0x0c, 0x00, 0x07, 0x0d, 0x03, 0x00, 0x4c, 0x60, -0x0c, 0x00, 0x07, 0x0d, 0x03, 0x00, 0x80, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, -0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9c, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x11, -0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x7f, 0x02, 0x1f, 0x03, 0x04, 0x00, -0x06, 0x00, 0x87, 0x02, 0x17, 0x03, 0x08, 0x00, 0x06, 0x00, 0x8f, 0x02, 0xef, 0x02, 0x0c, 0x00, -0x06, 0x00, 0xdf, 0x01, 0x0c, 0x02, 0x10, 0x00, 0x06, 0x00, 0xe7, 0x01, 0x04, 0x02, 0x14, 0x00, -0x06, 0x00, 0xe9, 0x01, 0xeb, 0x01, 0x1c, 0x00, 0x06, 0x00, 0xdf, 0x01, 0x7f, 0x02, 0x00, 0x10, -0x06, 0x00, 0x7f, 0x02, 0x1f, 0x03, 0x04, 0x10, 0x06, 0x00, 0x87, 0x02, 0x17, 0x03, 0x08, 0x10, -0x06, 0x00, 0x8f, 0x02, 0xef, 0x02, 0x0c, 0x10, 0x06, 0x00, 0xdf, 0x01, 0x0c, 0x02, 0x10, 0x10, -0x06, 0x00, 0xe7, 0x01, 0x04, 0x02, 0x14, 0x10, 0x06, 0x00, 0xe9, 0x01, 0xeb, 0x01, 0x1c, 0x10, -0x06, 0x00, 0xdf, 0x01, 0x7f, 0x02, 0x00, 0x00, 0x0e, 0x00, 0x7f, 0x02, 0x1f, 0x03, 0x04, 0x00, -0x0e, 0x00, 0x87, 0x02, 0x17, 0x03, 0x08, 0x00, 0x0e, 0x00, 0x8f, 0x02, 0xef, 0x02, 0x0c, 0x00, -0x0e, 0x00, 0xdf, 0x01, 0x0c, 0x02, 0x10, 0x00, 0x0e, 0x00, 0xe7, 0x01, 0x04, 0x02, 0x14, 0x00, -0x0e, 0x00, 0xe9, 0x01, 0xeb, 0x01, 0x00, 0x10, 0x0e, 0x00, 0x7f, 0x02, 0x1f, 0x03, 0x04, 0x10, -0x0e, 0x00, 0x87, 0x02, 0x17, 0x03, 0x08, 0x10, 0x0e, 0x00, 0x8f, 0x02, 0xef, 0x02, 0x0c, 0x10, -0x0e, 0x00, 0xdf, 0x01, 0x0c, 0x02, 0x10, 0x10, 0x0e, 0x00, 0xe7, 0x01, 0x04, 0x02, 0x14, 0x10, -0x0e, 0x00, 0xe9, 0x01, 0xeb, 0x01, 0x00, 0x50, 0x04, 0x00, 0x22, 0x06, 0x24, 0xc2, 0x08, 0x00, -0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -0x04, 0x00, 0x8e, 0x29, 0x00, 0x80, 0x00, 0x11, 0x0e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x40, -0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x40, 0x11, 0x0e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x50, 0x11, -0x0e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x60, 0x11, 0x0e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x07, 0x00, 0xfe, 0xff, 0xce, 0x18, 0x00, -0xff, 0xff, 0x08, 0x3d, 0x00, 0xfc, 0xff, 0x02, 0x40, 0xf0, 0x04, 0x00, 0x01, 0x00, 0x00, 0x01, -0x44, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, -0x4c, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x03, 0x03, 0x50, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, -0x54, 0xf0, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, -0xff, 0xff, 0x0a, 0xcb, 0x00, 0x0a, 0x80, 0x02, 0xe0, 0x01, 0xff, 0xff, 0xff, 0xda, 0xff, 0xff, -0x20, 0x03, 0x58, 0x02, 0xff, 0x03, 0xfe, 0x07, 0xff, 0xff, 0x00, 0x04, 0x00, 0x03, 0xff, 0x1b, -0xfe, 0x07, 0xff, 0xff, 0x80, 0x04, 0x60, 0x03, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0x00, 0x05, -0x58, 0x02, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x00, 0x05, 0xd0, 0x02, 0xff, 0x1b, 0xff, 0xbf, -0xff, 0xff, 0x00, 0x05, 0x00, 0x03, 0xff, 0x9b, 0xff, 0xbf, 0xff, 0xff, 0x00, 0x05, 0xc0, 0x03, -0xff, 0x9b, 0xff, 0x07, 0xff, 0xff, 0x00, 0x05, 0x00, 0x04, 0xff, 0x1b, 0xfe, 0x07, 0xff, 0xff, -0x56, 0x05, 0x00, 0x03, 0xff, 0x9b, 0xff, 0x07, 0xff, 0xff, 0x40, 0x06, 0x84, 0x03, 0xff, 0x1b, -0xfe, 0x07, 0xff, 0xff, 0x40, 0x06, 0xb0, 0x04, 0xff, 0x1b, 0xfe, 0x07, 0xff, 0xff, 0x00, 0x07, -0x40, 0x05, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0x40, 0x07, 0x70, 0x05, 0xff, 0xff, 0xff, 0x07, -0xff, 0xff, 0x80, 0x07, 0x38, 0x04, 0xff, 0x1b, 0xff, 0x07, 0xff, 0xff, 0x80, 0x07, 0xb0, 0x04, -0xff, 0xdb, 0xff, 0x07, 0xff, 0xff, 0x80, 0x07, 0xa0, 0x05, 0xff, 0x9b, 0xff, 0x07, 0xff, 0xff, -0x00, 0x08, 0x00, 0x06, 0xff, 0xdb, 0xff, 0x07, 0xff, 0xff, 0x78, 0x05, 0x1a, 0x04, 0xff, 0x9b, -0xff, 0x07, 0xff, 0xff, 0x90, 0x06, 0xb1, 0x03, 0xff, 0x1b, 0xff, 0x07, 0xff, 0xff, 0x00, 0x00, -0x0b, 0xc7, 0x00, 0x21, 0x40, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x09, 0x06, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x72, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x00, 0x4e, 0x56, 0x05, -0x00, 0x03, 0x10, 0x3c, 0x84, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x01, 0x0d, 0x03, -0x00, 0x78, 0x01, 0x0a, 0x0e, 0x09, 0x00, 0x01, 0xc5, 0x06, 0x5a, 0x00, 0x21, 0x07, 0x2d, 0x00, -0x0f, 0x8b, 0x00, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, -0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84, -0x00, 0x10, 0x00, 0x03, 0x01, 0x08, 0x00, 0x04, 0x08, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x08, 0x00, -0x02, 0x00, 0x00, 0x01, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, -0x00, 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x01, 0x04, -0x00, 0x04, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x01, 0x00, 0x00, -0x01, 0x08, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x01, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, -0x08, 0x00, 0x00, 0x00, 0x00, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x12, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, -0x20, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x14, 0x9e, 0x00, 0x06, 0x1a, 0x03, 0x99, 0x00, 0x05, 0x20, 0x03, 0x07, 0x3c, 0xa9, -0x20, 0x00, 0x90, 0x51, 0x20, 0x1c, 0x30, 0x08, 0x88, 0x93, 0x00, 0x00, 0x20, 0x53, 0x00, 0x00, -0x00, 0x01, 0x99, 0xa0, 0x05, 0x84, 0x03, 0x07, 0x3c, 0xab, 0x22, 0xa0, 0xa0, 0x50, 0x84, 0x1a, -0x30, 0x30, 0x20, 0x36, 0x00, 0x2f, 0xbe, 0x10, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x07, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3c, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, -0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x16, 0x4b, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x84, 0x0e, 0x00, 0x00, 0x4c, 0x46, 0x50, -0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, -0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, -0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, -0x65, 0x17, 0x48, 0x00, 0x64, 0x19, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 0x36, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x2a, 0x00, 0x98, 0x51, 0x00, 0x30, 0x40, 0x30, 0x70, -0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xa8, 0x2f, 0x78, 0xe0, 0x51, 0x1a, 0x26, 0x40, -0x58, 0x98, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x48, 0x3f, 0x40, 0x30, 0x62, 0xb0, -0x32, 0x40, 0x40, 0xc0, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x18, 0x28, 0x00, 0x36, -0x7f, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x36, 0x7f, 0x05, 0x00, 0x02, 0x00, 0x00, -0x00, 0x00, 0x0c, 0x36, 0x7f, 0x01, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x36, 0x7f, 0x06, -0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x19, 0x28, 0x00, 0x19, 0x00, 0xfa, 0x00, 0xfa, 0x00, -0x19, 0x00, 0x90, 0x01, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xc8, 0x00, 0x40, 0x00, -0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x2c, 0x01, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, -0x2c, 0x01, 0x1a, 0x02, 0x00, 0x00, 0x00, 0x1b, 0xc8, 0x00, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, -0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, -0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, -0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, -0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, -0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, -0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, -0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, -0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, -0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, -0xd0, 0x07, 0x0a, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x88, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x28, 0x18, 0x00, 0x02, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x94, 0x00, -0x03, 0x27, 0x0b, 0x20, 0x4d, 0x0b, 0x12, 0x5f, 0x0b, 0x0a, 0x69, 0x0b, 0x20, 0x8f, 0x0b, 0x12, -0xa1, 0x0b, 0x0a, 0xab, 0x0b, 0x20, 0xd1, 0x0b, 0x12, 0xe3, 0x0b, 0x0a, 0xed, 0x0b, 0x20, 0x13, -0x0c, 0x12, 0x25, 0x0c, 0x0a, 0x2f, 0x0c, 0x20, 0x55, 0x0c, 0x12, 0x67, 0x0c, 0x0a, 0x71, 0x0c, -0x20, 0x97, 0x0c, 0x12, 0xa9, 0x0c, 0x0a, 0xb3, 0x0c, 0x20, 0xd9, 0x0c, 0x12, 0xeb, 0x0c, 0x0a, -0xf5, 0x0c, 0x20, 0x1b, 0x0d, 0x12, 0x2d, 0x0d, 0x0a, 0x37, 0x0d, 0x20, 0x5d, 0x0d, 0x12, 0x6f, -0x0d, 0x0a, 0x79, 0x0d, 0x20, 0x9f, 0x0d, 0x12, 0xb1, 0x0d, 0x0a, 0xbb, 0x0d, 0x20, 0xe1, 0x0d, -0x12, 0xf3, 0x0d, 0x0a, 0xfd, 0x0d, 0x20, 0x23, 0x0e, 0x12, 0x35, 0x0e, 0x0a, 0x3f, 0x0e, 0x20, -0x65, 0x0e, 0x12, 0x77, 0x0e, 0x0a, 0x81, 0x0e, 0x20, 0xa7, 0x0e, 0x12, 0xb9, 0x0e, 0x0a, 0xc3, -0x0e, 0x20, 0xe9, 0x0e, 0x12, 0xfb, 0x0e, 0x0a, 0x05, 0x0f, 0x20, 0x2b, 0x0f, 0x12, 0x3d, 0x0f, -0x0a, 0x47, 0x0f, 0x0d, 0x2a, 0xf0, 0x04, 0x80, 0x02, 0xe0, 0x01, 0x80, 0x11, 0x0e, 0x00, 0x00, -0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, -0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0xd6, 0x09, 0x80, -0x90, 0x20, 0xe0, 0x1d, 0x10, 0x08, 0x60, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, -0x7f, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x20, 0x03, 0x58, 0x02, 0x80, 0x11, 0x0e, -0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, -0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0xa0, -0x0f, 0x20, 0x00, 0x31, 0x58, 0x1c, 0x20, 0x28, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x1e, 0x36, 0x7f, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x06, 0x84, 0x03, 0x80, -0x11, 0x0e, 0x00, 0x3c, 0x03, 0x30, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xb8, 0x0b, 0x2c, 0x01, 0x0c, -0x72, 0x0c, 0x00, 0xb8, 0x0b, 0x2c, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x06, 0x0f, 0x27, 0x00, 0xff, -0xff, 0x2f, 0x26, 0x40, 0xb8, 0x60, 0x84, 0x0c, 0x30, 0x30, 0x30, 0x23, 0x00, 0x7e, 0xd7, 0x10, -0x00, 0x00, 0x19, 0x30, 0xe4, 0x89, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x05, 0x00, -0x04, 0x80, 0x11, 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, -0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, -0x00, 0xff, 0xff, 0x30, 0x2a, 0x00, 0x98, 0x51, 0x00, 0x30, 0x40, 0x30, 0x70, 0x13, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x78, -0x05, 0x1a, 0x04, 0x80, 0x11, 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, -0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, -0x0f, 0x27, 0x00, 0xff, 0xff, 0x30, 0x2a, 0x78, 0x20, 0x51, 0x1a, 0x10, 0x40, 0x10, 0x70, 0x13, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x01, 0x90, 0x05, 0x00, 0x00, 0x00, 0x00, -0x0c, 0x78, 0x05, 0x1a, 0x04, 0x80, 0x11, 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, -0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, -0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0xa8, 0x2f, 0x78, 0xe0, 0x51, 0x1a, 0x26, 0x40, 0x58, -0x98, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x01, 0x90, 0x06, 0x00, 0x00, -0x00, 0x00, 0x0c, 0x40, 0x06, 0xb0, 0x04, 0x80, 0x11, 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x08, -0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, -0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0x48, 0x3f, 0x40, 0x30, 0x62, 0xb0, 0x32, -0x40, 0x40, 0xc0, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x06, 0x00, 0x07, -0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x05, 0x00, 0x03, 0x80, 0x11, 0x0e, 0x00, 0x00, 0x03, 0x00, -0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, -0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0xa9, 0x1a, 0x00, 0xa0, 0x50, -0x00, 0x0a, 0x30, 0x30, 0x20, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, -0x90, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x90, 0x06, 0x1a, 0x04, 0x80, 0x11, 0x0e, 0x00, 0x3c, -0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, -0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0x7c, 0x2e, 0x90, -0xa0, 0x60, 0x1a, 0x1e, 0x40, 0x30, 0x20, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, -0x7f, 0x04, 0x90, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x80, 0x07, 0xb0, 0x04, 0x80, 0x11, 0x0e, -0x00, 0x3c, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, -0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0x28, -0x3c, 0x80, 0xa0, 0x70, 0xb0, 0x23, 0x40, 0x30, 0x20, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x1e, 0x36, 0x7f, 0x05, 0x90, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x03, 0x80, -0x11, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, -0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, -0xff, 0x64, 0x19, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 0x36, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, -0x03, 0x80, 0x11, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, -0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, -0x00, 0xff, 0xff, 0x64, 0x19, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 0x36, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, -0x04, 0x00, 0x03, 0x80, 0x11, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, -0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, -0x0f, 0x27, 0x00, 0xff, 0xff, 0x64, 0x19, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 0x36, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, -0x0c, 0x00, 0x05, 0x20, 0x03, 0x80, 0x11, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x72, 0x0c, -0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, 0x72, 0x0c, -0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0xea, 0x1a, 0x00, 0xa0, 0x50, 0x20, 0x17, 0x30, 0x0c, -0x30, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x90, 0x0e, 0x00, 0x00, -0x00, 0x00, 0x0c, 0x00, 0x05, 0x58, 0x02, 0x80, 0x11, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, -0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, 0x01, 0x10, -0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0x06, 0x18, 0x00, 0x70, 0x51, 0x58, 0x15, -0x20, 0x38, 0x80, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, 0x00, 0x0f, -0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x06, 0x80, 0x11, 0x0e, 0x00, 0x3c, 0x03, 0x00, -0x00, 0x08, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0x58, 0x02, 0x0c, 0x72, 0x0c, 0x00, 0xd0, 0x07, 0xf4, -0x01, 0x10, 0x72, 0x0c, 0x00, 0x05, 0x0f, 0x27, 0x00, 0xff, 0xff, 0x29, 0x40, 0x00, 0x60, 0x80, -0x00, 0x13, 0x60, 0x10, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x36, 0x7f, 0x03, -0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, -0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, -0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, -0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, -0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, -0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, -0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, -0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, -0x50, 0x61, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x46, 0x50, 0x5f, 0x50, 0x61, 0x6e -}; diff --git a/src/northbridge/intel/nehalem/gma.c b/src/northbridge/intel/nehalem/gma.c index 3a9dcf5..c76bfe4 100644 --- a/src/northbridge/intel/nehalem/gma.c +++ b/src/northbridge/intel/nehalem/gma.c @@ -1046,6 +1046,114 @@ static void intel_gma_init(const struct northbridge_intel_nehalem_config *info, #endif +/* VBT definitions copied from Linux. */ +struct vbt_header { + u8 signature[20]; + u16 version; + u16 header_size; + u16 vbt_size; + u8 vbt_checksum; + u8 reserved0; + u32 bdb_offset; + u32 aim_offset[4]; +} __attribute__((packed)); + +struct bdb_header { + u8 signature[16]; + u16 version; + u16 header_size; + u16 bdb_size; +} __attribute__((packed)); + +#define BDB_GENERAL_FEATURES 1 + +struct bdb_general_features { + /* bits 1 */ + u8 panel_fitting:2; + u8 flexaim:1; + u8 msg_enable:1; + u8 clear_screen:3; + u8 color_flip:1; + + /* bits 2 */ + u8 download_ext_vbt:1; + u8 enable_ssc:1; + u8 ssc_freq:1; + u8 enable_lfp_on_override:1; + u8 disable_ssc_ddt:1; + u8 rsvd7:1; + u8 display_clock_mode:1; + u8 rsvd8:1; /* finish byte */ + + /* bits 3 */ + u8 disable_smooth_vision:1; + u8 single_dvi:1; + u8 rsvd9:1; + u8 fdi_rx_polarity_inverted:1; + u8 rsvd10:4; /* finish byte */ + + /* bits 4 */ + u8 legacy_monitor_detect; + + /* bits 5 */ + u8 int_crt_support:1; + u8 int_tv_support:1; + u8 int_efp_support:1; + u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */ + u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */ + u8 rsvd11:3; /* finish byte */ +} __attribute__((packed)); + + +#if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT +static size_t generate_vbt(const struct northbridge_intel_nehalem_config *conf, + void *vbt) +{ + struct vbt_header *head = vbt; + struct bdb_header *bdb_head; + struct bdb_general_features *genfeat; + u8 *ptr; + + memset (head, 0, sizeof (*head)); + + memcpy (head->signature, "$VBT IRONLAKE-MOBILE", 20); + head->version = 100; + head->header_size = sizeof (*head); + head->bdb_offset = sizeof (*head); + + bdb_head = (struct bdb_header *) (head + 1); + memset (bdb_head, 0, sizeof (*bdb_head)); + memcpy (bdb_head->signature, "BIOS_DATA_BLOCK ", 16); + bdb_head->version = 0xa8; + bdb_head->header_size = sizeof (*bdb_head); + + ptr = (u8 *) (bdb_head + 1); + + ptr[0] = BDB_GENERAL_FEATURES; + ptr[1] = sizeof (*genfeat); + ptr[2] = sizeof (*genfeat) >> 8; + ptr += 3; + + genfeat = (struct bdb_general_features *) ptr; + memset (genfeat, 0, sizeof (*genfeat)); + genfeat->panel_fitting = 3; + genfeat->flexaim = 1; + genfeat->download_ext_vbt = 1; + genfeat->enable_ssc = conf->gpu_use_spread_spectrum_clock; + genfeat->ssc_freq = !conf->gpu_link_frequency_270_mhz; + genfeat->rsvd10 = 0x4; + genfeat->legacy_monitor_detect = 1; + genfeat->int_crt_support = 1; + genfeat->dp_ssc_enb = 1; + + ptr += sizeof (*genfeat); + + bdb_head->bdb_size = ptr - (u8 *)bdb_head; + head->vbt_size = ptr - (u8 *)head; + head->vbt_checksum = 0; + return ptr - (u8 *)head; +} +#endif static void gma_func0_init(struct device *dev) { @@ -1080,19 +1188,17 @@ static void gma_func0_init(struct device *dev) intel_gma_init(conf, gtt_res->base, physbase, pio_res->base, lfb_res->base); } -#endif /* Linux relies on VBT for panel info. */ if (read16(0xc0000) != 0xaa55) { optionrom_header_t *oh = (void *)0xc0000; optionrom_pcir_t *pcir; - int sz; + size_t vbt_size; + size_t fake_oprom_size; memset(oh->reserved, 0, 8192); - sz = (0x80 + sizeof(fake_vbt) + 511) / 512; oh->signature = 0xaa55; - oh->size = sz; oh->pcir_offset = 0x40; oh->vbt_offset = 0x80; @@ -1105,11 +1211,14 @@ static void gma_func0_init(struct device *dev) pcir->classcode[0] = dev->class >> 8; pcir->classcode[1] = dev->class >> 16; pcir->classcode[2] = dev->class >> 24; - pcir->imagelength = sz; pcir->indicator = 0x80; - memcpy((void *)0xc0080, fake_vbt, sizeof(fake_vbt)); + vbt_size = generate_vbt (conf, (void *)0xc0080); + fake_oprom_size = (0x80 + vbt_size + 511) / 512; + oh->size = fake_oprom_size; + pcir->imagelength = fake_oprom_size; } +#endif /* Post VBIOS init */
1
0
0
0
Patch set updated for coreboot: f5949a0 sandy/ivybridge: Native raminit.
by Vladimir Serbinenko
31 May '14
31 May '14
Vladimir Serbinenko (phcoder(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/5786
-gerrit commit f5949a0ff46359e39edceeaa89e8f239869622a1 Author: Vladimir Serbinenko <phcoder(a)gmail.com> Date: Sun May 18 11:05:56 2014 +0200 sandy/ivybridge: Native raminit. Based on damo22 work and my X230 tracing. Works for my X230 in a variety of RAM configs. Also-By: Damien Zammit <damien(a)zamaudio.com> Change-Id: I1aa024c55a8416fc53b25e7123037df0e55a2769 Signed-off-by: Vladimir Serbinenko <phcoder(a)gmail.com> --- src/cpu/intel/Makefile.inc | 1 + src/cpu/x86/smm/smmhandler_tseg.S | 2 +- src/cpu/x86/smm/smmrelocate.S | 4 +- src/device/dram/ddr3.c | 8 +- src/include/device/dram/ddr3.h | 3 + src/mainboard/lenovo/x230/Kconfig | 6 +- src/mainboard/lenovo/x230/romstage.c | 120 +- src/northbridge/intel/Makefile.inc | 1 + src/northbridge/intel/sandybridge/Kconfig | 12 +- src/northbridge/intel/sandybridge/Makefile.inc | 5 +- src/northbridge/intel/sandybridge/gma.c | 4 +- src/northbridge/intel/sandybridge/raminit_native.c | 3766 ++++++++++++++++++++ src/northbridge/intel/sandybridge/raminit_native.h | 29 + src/southbridge/intel/bd82x6x/Makefile.inc | 6 +- src/southbridge/intel/bd82x6x/early_me_native.c | 272 ++ src/southbridge/intel/bd82x6x/early_pch_native.c | 375 ++ src/southbridge/intel/bd82x6x/early_thermal.c | 70 + src/southbridge/intel/bd82x6x/pch.h | 2 + src/southbridge/intel/bd82x6x/smi.c | 3 - src/southbridge/intel/bd82x6x/usb_ehci.c | 33 + src/southbridge/intel/ibexpeak/me.c | 125 - src/southbridge/intel/ibexpeak/smi.c | 6 - src/southbridge/intel/ibexpeak/usb_ehci.c | 17 + 23 files changed, 4647 insertions(+), 223 deletions(-) diff --git a/src/cpu/intel/Makefile.inc b/src/cpu/intel/Makefile.inc index 0392f69..68ea05d 100644 --- a/src/cpu/intel/Makefile.inc +++ b/src/cpu/intel/Makefile.inc @@ -19,6 +19,7 @@ subdirs-$(CONFIG_CPU_INTEL_SOCKET_RPGA989) += socket_rPGA989 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_NEHALEM) += model_2065x subdirs-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += model_206ax subdirs-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += model_206ax +subdirs-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE) += model_206ax subdirs-$(CONFIG_NORTHBRIDGE_INTEL_HASWELL) += haswell subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_SANDYBRIDGE) += fsp_model_206ax subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_IVYBRIDGE) += fsp_model_206ax diff --git a/src/cpu/x86/smm/smmhandler_tseg.S b/src/cpu/x86/smm/smmhandler_tseg.S index b33fcdf..380935a 100644 --- a/src/cpu/x86/smm/smmhandler_tseg.S +++ b/src/cpu/x86/smm/smmhandler_tseg.S @@ -57,7 +57,7 @@ #define SMI_UNLOCKED 1 #define __PRE_RAM__ -#if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE +#if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE #include <northbridge/intel/sandybridge/sandybridge.h> #define TSEG_BAR (DEFAULT_PCIEXBAR | TSEG) #elif CONFIG_NORTHBRIDGE_INTEL_NEHALEM diff --git a/src/cpu/x86/smm/smmrelocate.S b/src/cpu/x86/smm/smmrelocate.S index bdc9771..bc90fab 100644 --- a/src/cpu/x86/smm/smmrelocate.S +++ b/src/cpu/x86/smm/smmrelocate.S @@ -48,7 +48,7 @@ #if CONFIG_SMM_TSEG -#if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE +#if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE #include <northbridge/intel/sandybridge/sandybridge.h> #define TSEG_BAR (DEFAULT_PCIEXBAR | TSEG) #elif CONFIG_NORTHBRIDGE_INTEL_NEHALEM @@ -195,7 +195,7 @@ smm_relocate: xorl %edx, %edx wrmsr -#if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE +#if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE /* * IED base is top 4M of TSEG */ diff --git a/src/device/dram/ddr3.c b/src/device/dram/ddr3.c index 9b4f490..69782ab 100644 --- a/src/device/dram/ddr3.c +++ b/src/device/dram/ddr3.c @@ -110,7 +110,7 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd) { int ret; u16 crc, spd_crc; - u8 ftb_divisor, ftb_dividend, capacity_shift, bus_width, sdram_width; + u8 ftb_divisor, ftb_dividend, capacity_shift, bus_width; u8 reg8; u32 mtb; /* medium time base */ unsigned int val, param; @@ -209,8 +209,8 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd) printram(" Invalid SDRAM width\n"); ret = SPD_STATUS_INVALID_FIELD; } - sdram_width = (4 << val); - printram(" SDRAM width : %u\n", sdram_width); + dimm->width = (4 << val); + printram(" SDRAM width : %u\n", dimm->width); /* Memory bus width */ reg8 = spd[8]; @@ -236,7 +236,7 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd) * capacity_shift * The rest is the JEDEC formula */ dimm->size_mb = ((1 << (capacity_shift + (25 - 20))) * bus_width - * dimm->ranks) / sdram_width; + * dimm->ranks) / dimm->width; /* Fine Timebase (FTB) Dividend/Divisor */ /* Dividend */ diff --git a/src/include/device/dram/ddr3.h b/src/include/device/dram/ddr3.h index b19c51c..4bf5058 100644 --- a/src/include/device/dram/ddr3.h +++ b/src/include/device/dram/ddr3.h @@ -37,6 +37,7 @@ * @{ */ #define TCK_1066MHZ 240 +#define TCK_933MHZ 275 #define TCK_800MHZ 320 #define TCK_666MHZ 384 #define TCK_533MHZ 480 @@ -137,6 +138,8 @@ typedef struct dimm_attr_st { u16 cas_supported; /* Flags extracted from SPD */ dimm_flags_t flags; + /* SDRAM width */ + u8 width; /* Number of ranks */ u8 ranks; /* Number or row address bits */ diff --git a/src/mainboard/lenovo/x230/Kconfig b/src/mainboard/lenovo/x230/Kconfig index d3aa6e9..6fd309e 100644 --- a/src/mainboard/lenovo/x230/Kconfig +++ b/src/mainboard/lenovo/x230/Kconfig @@ -3,7 +3,7 @@ if BOARD_LENOVO_X230 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y select CPU_INTEL_SOCKET_RPGA989 - select NORTHBRIDGE_INTEL_IVYBRIDGE + select NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE select SOUTHBRIDGE_INTEL_C216 select EC_LENOVO_PMH7 select EC_LENOVO_H8 @@ -47,10 +47,6 @@ config MMCONF_BASE_ADDRESS hex default 0xf0000000 -config CACHE_ROM_SIZE_OVERRIDE - hex - default 0x800000 - config IRQ_SLOT_COUNT int default 18 diff --git a/src/mainboard/lenovo/x230/romstage.c b/src/mainboard/lenovo/x230/romstage.c index 6e4e685..ff319b5 100644 --- a/src/mainboard/lenovo/x230/romstage.c +++ b/src/mainboard/lenovo/x230/romstage.c @@ -32,7 +32,7 @@ #include <cbmem.h> #include <console/console.h> #include "northbridge/intel/sandybridge/sandybridge.h" -#include "northbridge/intel/sandybridge/raminit.h" +#include "northbridge/intel/sandybridge/raminit_native.h" #include "southbridge/intel/bd82x6x/pch.h" #include "southbridge/intel/bd82x6x/gpio.h" #include <arch/cpu.h> @@ -108,66 +108,59 @@ static void rcba_config(void) RCBA32(BUC) = 0; } +static void +init_usb (void) +{ + const u32 rcba_dump[64] = { + /* 3500 */ 0x20000153, 0x20000153, 0x20000f57, 0x20000f57, + /* 3510 */ 0x20000f57, 0x20000f57, 0x20000153, 0x2000055b, + /* 3520 */ 0x20000153, 0x2000055b, 0x20000f57, 0x20000f57, + /* 3530 */ 0x20000f57, 0x20000f57, 0x00000000, 0x00000000, + /* 3540 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* 3550 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* 3560 */ 0x024c8001, 0x000024a3, 0x00040002, 0x01000050, + /* 3570 */ 0x02000772, 0x16000f9f, 0x1800ff4f, 0x0001d630, + /* 3580 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* 3590 */ 0x00000000, 0x00000000, 0x00000000, 0x00000040, + /* 35a0 */ 0x04000201, 0x00000200, 0x00000000, 0x00000000, + /* 35b0 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* 35c0 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* 35d0 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* 35e0 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* 35f0 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }; + int i; + /* Activate PMBAR. */ + pci_write_config32(PCI_DEV(0, 0x1f, 0), PMBASE, DEFAULT_PMBASE | 1); + pci_write_config32(PCI_DEV(0, 0x1f, 0), PMBASE + 4, 0); + pci_write_config8(PCI_DEV(0, 0x1f, 0), 0x44 /* ACPI_CNTL */ , 0x80); /* Enable ACPI BAR */ + + /* Unlock registers. */ + outw (inw (DEFAULT_PMBASE | 0x003c) | 2, DEFAULT_PMBASE | 0x003c); + + for (i = 0; i < 64; i++) + write32 (DEFAULT_RCBABASE | (0x3500 + 4 * i), rcba_dump[i]); + + pcie_write_config32 (PCI_DEV (0, 0x14, 0), 0xe4, 0x00000000); + + /* Relock registers. */ + outw (0x0000, DEFAULT_PMBASE | 0x003c); +} + + void main(unsigned long bist) { int boot_mode = 0; int cbmem_was_initted; u32 pm1_cnt; u16 pm1_sts; + spd_raw_data spd[4]; if (MCHBAR16(SSKPD) == 0xCAFE) { outb(0x6, 0xcf9); hlt (); } - struct pei_data pei_data = { - .pei_version = PEI_VERSION, - .mchbar = DEFAULT_MCHBAR, - .dmibar = DEFAULT_DMIBAR, - .epbar = DEFAULT_EPBAR, - .pciexbar = CONFIG_MMCONF_BASE_ADDRESS, - .smbusbar = SMBUS_IO_BASE, - .wdbbar = 0x4000000, - .wdbsize = 0x1000, - .hpet_address = CONFIG_HPET_ADDRESS, - .rcba = DEFAULT_RCBABASE, - .pmbase = DEFAULT_PMBASE, - .gpiobase = DEFAULT_GPIOBASE, - .thermalbase = 0xfed08000, - .system_type = 0, // 0 Mobile, 1 Desktop/Server - .tseg_size = CONFIG_SMM_TSEG_SIZE, - .spd_addresses = { 0xA0, 0x00,0xA2,0x00 }, - .ts_addresses = { 0x00, 0x00, 0x00, 0x00 }, - .ec_present = 1, - .gbe_enable = 1, - .ddr3lv_support = 0, - // 0 = leave channel enabled - // 1 = disable dimm 0 on channel - // 2 = disable dimm 1 on channel - // 3 = disable dimm 0+1 on channel - .dimm_channel0_disabled = 2, - .dimm_channel1_disabled = 2, - .max_ddr3_freq = 1600, - .usb_port_config = { - /* enabled usb oc pin length */ - { 1, 0, 0x0080 }, /* P0 (left, fan side), OC 0 */ - { 1, 1, 0x0080 }, /* P1 (left touchpad side), OC 1 */ - { 1, 3, 0x0080 }, /* P2: dock, OC 3 */ - { 1, 0, 0x0040 }, /* P3: wwan, no OC */ - { 1, 0, 0x0080 }, /* P4: Wacom tablet on X230t, otherwise empty */ - { 1, 0, 0x0080 }, /* P5: Expresscard, no OC */ - { 0, 0, 0x0000 }, /* P6: Empty */ - { 1, 0, 0x0080 }, /* P7: dock, no OC */ - { 0, 0, 0x0000 }, /* P8: Empty */ - { 1, 5, 0x0080 }, /* P9: Right (EHCI debug), OC 5 */ - { 1, 0, 0x0040 }, /* P10: fingerprint reader, no OC */ - { 1, 0, 0x0040 }, /* P11: bluetooth, no OC. */ - { 1, 0, 0x0040 }, /* P12: wlan, no OC */ - { 1, 0, 0x0080 }, /* P13: webcam, no OC */ - }, - .ddr_refresh_rate_config = 2, /* Force double refresh rate */ - }; - timestamp_init(get_initial_timestamp()); timestamp_add_now(TS_START_ROMSTAGE); @@ -182,6 +175,8 @@ void main(unsigned long bist) setup_pch_gpios(&x230_gpio_map); + init_usb(); + /* Initialize console device(s) */ console_init(); @@ -217,31 +212,16 @@ void main(unsigned long bist) /* Enable SPD ROMs and DDR-III DRAM */ enable_smbus(); - /* Prepare USB controller early in S3 resume */ - if (boot_mode == 2) - enable_usb_bar(); - post_code(0x39); post_code(0x3a); - pei_data.boot_mode = boot_mode; timestamp_add_now(TS_BEFORE_INITRAM); - /* MRC.bin has a bug and sometimes halts (instead of reboot?). - */ - if (boot_mode != 2) - { - RCBA32(GCS) = RCBA32(GCS) & ~(1 << 5); /* reset */ - outw((0 << 11), DEFAULT_PMBASE | 0x60 | 0x08); /* let timer go */ - } - - sdram_initialize(&pei_data); + memset (spd, 0, sizeof (spd)); + read_spd (&spd[0], 0x50); + read_spd (&spd[2], 0x51); - if (boot_mode != 2) - { - RCBA32(GCS) = RCBA32(GCS) | (1 << 5); /* No reset */ - outw((1 << 11), DEFAULT_PMBASE | 0x60 | 0x08); /* halt timer */ - } + init_dram_ddr3 (spd, 1, TCK_800MHZ); timestamp_add_now(TS_AFTER_INITRAM); post_code(0x3c); @@ -254,8 +234,8 @@ void main(unsigned long bist) MCHBAR16(SSKPD) = 0xCAFE; cbmem_was_initted = !cbmem_recovery(boot_mode==2); - if (boot_mode!=2) - save_mrc_data(&pei_data); +// if (boot_mode!=2) +// save_mrc_data(&pei_data); #if CONFIG_HAVE_ACPI_RESUME /* If there is no high memory area, we didn't boot before, so diff --git a/src/northbridge/intel/Makefile.inc b/src/northbridge/intel/Makefile.inc index 808a1b2..f1c2540 100644 --- a/src/northbridge/intel/Makefile.inc +++ b/src/northbridge/intel/Makefile.inc @@ -15,6 +15,7 @@ subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I5000) += i5000 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_NEHALEM) += nehalem subdirs-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += sandybridge subdirs-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += sandybridge +subdirs-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE) += sandybridge subdirs-$(CONFIG_NORTHBRIDGE_INTEL_HASWELL) += haswell subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_SANDYBRIDGE) += fsp_sandybridge subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_IVYBRIDGE) += fsp_sandybridge diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig index fb92e40..9bac706 100644 --- a/src/northbridge/intel/sandybridge/Kconfig +++ b/src/northbridge/intel/sandybridge/Kconfig @@ -31,7 +31,14 @@ config NORTHBRIDGE_INTEL_IVYBRIDGE select MMCONF_SUPPORT_DEFAULT select CPU_INTEL_MODEL_306AX -if NORTHBRIDGE_INTEL_SANDYBRIDGE || NORTHBRIDGE_INTEL_IVYBRIDGE +config NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE + bool + select CACHE_MRC_BIN + select MMCONF_SUPPORT + select MMCONF_SUPPORT_DEFAULT + select CPU_INTEL_MODEL_306AX + +if NORTHBRIDGE_INTEL_SANDYBRIDGE || NORTHBRIDGE_INTEL_IVYBRIDGE || NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE config VGA_BIOS_ID string @@ -52,7 +59,8 @@ config MRC_CACHE_SIZE config DCACHE_RAM_BASE hex - default 0xff7e0000 + default 0xff7e0000 if !NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE + default 0xfefe0000 if NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE config DCACHE_RAM_SIZE hex diff --git a/src/northbridge/intel/sandybridge/Makefile.inc b/src/northbridge/intel/sandybridge/Makefile.inc index 6655e2a..ae20de5 100644 --- a/src/northbridge/intel/sandybridge/Makefile.inc +++ b/src/northbridge/intel/sandybridge/Makefile.inc @@ -26,7 +26,10 @@ ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c ramstage-y += mrccache.c romstage-y += ram_calc.c -romstage-y += raminit.c +romstage-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += raminit.c +romstage-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += raminit.c +romstage-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE) += raminit_native.c +romstage-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE) += ../../../device/dram/ddr3.c romstage-y += mrccache.c romstage-y += early_init.c romstage-y += report_platform.c diff --git a/src/northbridge/intel/sandybridge/gma.c b/src/northbridge/intel/sandybridge/gma.c index a01fe9f..fcd704f 100644 --- a/src/northbridge/intel/sandybridge/gma.c +++ b/src/northbridge/intel/sandybridge/gma.c @@ -651,9 +651,7 @@ static void gma_func0_init(struct device *dev) physbase = pci_read_config32(dev, 0x5c) & ~0xf; graphics_base = dev->resource_list[1].base; - int lightup_ok = i915lightup(conf, physbase, iobase, mmiobase, graphics_base); - if (lightup_ok) - gfx_set_init_done(1); + i915lightup(conf, physbase, iobase, mmiobase, graphics_base); #endif } diff --git a/src/northbridge/intel/sandybridge/raminit_native.c b/src/northbridge/intel/sandybridge/raminit_native.c new file mode 100644 index 0000000..64854da --- /dev/null +++ b/src/northbridge/intel/sandybridge/raminit_native.c @@ -0,0 +1,3766 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Damien Zammit <damien(a)zamaudio.com> + * Copyright (C) 2014 Vladimir Serbinenko <phcoder(a)gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <console/usb.h> +#include <bootmode.h> +#include <string.h> +#include <arch/hlt.h> +#include <arch/io.h> +#include <cbmem.h> +#include <arch/cbfs.h> +#include <cbfs.h> +#include <ip_checksum.h> +#include <pc80/mc146818rtc.h> +#include <device/pci_def.h> +#include "raminit_native.h" +#include "sandybridge.h" +#include <delay.h> + +/* Management Engine is in the southbridge */ +#include "southbridge/intel/bd82x6x/me.h" +/* For SPD. */ +#include "southbridge/intel/bd82x6x/smbus.h" +#include "arch/cpu.h" +#include "cpu/x86/msr.h" + +/* FIXME: no ECC support. */ +/* FIXME: no support for 3-channel chipsets. */ +/* FIXME: no S3. */ +/* FIXME: no timing caching. */ + +#define BASEFREQ 133 +#define tDLLK 512 + +#define IS_SANDY_CPU(x) ((x & 0xffff0) == 0x206a0) +#define IS_SANDY_CPU_C(x) ((x & 0xf) == 4) +#define IS_SANDY_CPU_D0(x) ((x & 0xf) == 5) +#define IS_SANDY_CPU_D1(x) ((x & 0xf) == 6) +#define IS_SANDY_CPU_D2(x) ((x & 0xf) == 7) + +#define IS_IVY_CPU(x) ((x & 0xffff0) == 0x306a0) +#define IS_IVY_CPU_C(x) ((x & 0xf) == 4) +#define IS_IVY_CPU_K(x) ((x & 0xf) == 5) +#define IS_IVY_CPU_D(x) ((x & 0xf) == 6) +#define IS_IVY_CPU_E(x) ((x & 0xf) >= 8) + +#define NUM_CHANNELS 2 +#define NUM_SLOTRANKS 4 +#define NUM_SLOTS 2 +#define NUM_LANES 8 + +typedef struct odtmap_st { + u16 rttwr; + u16 rttnom; +} odtmap; + +typedef struct dimm_info_st { + dimm_attr dimm[NUM_CHANNELS][NUM_SLOTS]; +} dimm_info; + +struct ram_rank_timings { + /* Register 4024. One byte per slotrank. */ + u8 val_4024; + /* Register 4028. One nibble per slotrank. */ + u8 val_4028; + + int val_320c; + + struct ram_lane_timings { + /* lane register offset 0x10. */ + u16 timA; /* bits 0 - 5, bits 16 - 18 */ + u8 rising; /* bits 8 - 14 */ + u8 falling; /* bits 20 - 26. */ + + /* lane register offset 0x20. */ + int timC; /* bit 0 - 5, 19. */ + u16 timB; /* bits 8 - 13, 15 - 17. */ + } lanes[NUM_LANES]; +}; + +typedef struct ramctr_timing_st { + int mobile; + + enum spd_memory_type dram_type; + u16 cas_supported; + /* tLatencies are in units of ns, scaled by x256 */ + u32 tCK; + u32 tAA; + u32 tWR; + u32 tRCD; + u32 tRRD; + u32 tRP; + u32 tRAS; + u32 tRC; + u32 tRFC; + u32 tWTR; + u32 tRTP; + u32 tFAW; + /* Latencies in terms of clock cycles + * They are saved separately as they are needed for DRAM MRS commands*/ + u8 CAS; /* CAS read latency */ + u8 CWL; /* CAS write latency */ + /* Number of dimms currently connected */ + u8 n_dimms; + + u32 tREFI; + u32 tMOD; + u32 tXSOffset; + u32 tWLO; + u32 tCKE; + u32 tXPDLL; + u32 tXP; + u32 tAONPD; + + u32 delay1; + u32 delay2; + u16 reg_5064b0; /* bits 0-11. */ + + u8 eccsupport; + u8 dualchannel; + + u8 rankmap[NUM_CHANNELS]; + int ref_card_offset[NUM_CHANNELS]; + + int reg_c14_offset; + + int edge_offset[3]; + int timC_offset[3]; + + int extended_temperature_range; + int auto_self_refresh; + + int rank_mirror[NUM_CHANNELS][NUM_SLOTRANKS]; + + struct ram_rank_timings timings[NUM_CHANNELS][NUM_SLOTRANKS]; +} ramctr_timing; + +#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0) +#define NORTHBRIDGE PCI_DEV(0, 0x0, 0) +#define FOR_ALL_LANES for (lane = 0; lane < NUM_LANES; lane++) +#define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) +#define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank)) +#define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel]) +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define MAX_EDGE_TIMING 71 +#define MAX_TIMC 127 +#define MAX_TIMB 511 +#define MAX_TIMA 127 + +static void program_timings(ramctr_timing * ctrl, int channel); + +static const char *ecc_decoder[] = { + "inactive", + "active on IO", + "disabled on IO", + "active" +}; + +static void wait_txt_clear(void) +{ + struct cpuid_result cp; + + cp = cpuid_ext(0x1, 0x0); + /* Check if TXT is supported? */ + if (!(cp.ecx & 0x40)) + return; + /* Some TXT public bit. */ + if (!(read32(0xfed30010) & 1)) + return; + /* Wait for TXT clear. */ + while (!(read8(0xfed40000) & (1 << 7))) ; +} + +static void sfence(void) +{ + asm volatile ("sfence"); +} + +/* + * Dump in the log memory controller configuration as read from the memory + * controller registers. + */ +static void report_memory_config(void) +{ + u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS]; + int i; + + addr_decoder_common = MCHBAR32(0x5000); + addr_decode_ch[0] = MCHBAR32(0x5004); + addr_decode_ch[1] = MCHBAR32(0x5008); + + printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n", + (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100); + printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n", + addr_decoder_common & 3, (addr_decoder_common >> 2) & 3, + (addr_decoder_common >> 4) & 3); + + for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) { + u32 ch_conf = addr_decode_ch[i]; + printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i, + ch_conf); + printk(BIOS_DEBUG, " ECC %s\n", + ecc_decoder[(ch_conf >> 24) & 3]); + printk(BIOS_DEBUG, " enhanced interleave mode %s\n", + ((ch_conf >> 22) & 1) ? "on" : "off"); + printk(BIOS_DEBUG, " rank interleave %s\n", + ((ch_conf >> 21) & 1) ? "on" : "off"); + printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n", + ((ch_conf >> 0) & 0xff) * 256, + ((ch_conf >> 19) & 1) ? 16 : 8, + ((ch_conf >> 17) & 1) ? "dual" : "single", + ((ch_conf >> 16) & 1) ? "" : ", selected"); + printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n", + ((ch_conf >> 8) & 0xff) * 256, + ((ch_conf >> 20) & 1) ? 16 : 8, + ((ch_conf >> 18) & 1) ? "dual" : "single", + ((ch_conf >> 16) & 1) ? ", selected" : ""); + } +} + +static void post_system_agent_init(void) +{ + /* If PCIe init is skipped, set the PEG clock gating */ + MCHBAR32(0x7010) = MCHBAR32(0x7010) | 0x01; +} + +void read_spd(spd_raw_data * spd, u8 addr) +{ + int j; + for (j = 0; j < 256; j++) + (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j); +} + +static void dram_find_spds_ddr3(spd_raw_data * spd, dimm_info * dimm, + ramctr_timing * ctrl) +{ + int dimms = 0; + int channel, slot, spd_slot; + + memset (ctrl->rankmap, 0, sizeof (ctrl->rankmap)); + + ctrl->extended_temperature_range = 1; + ctrl->auto_self_refresh = 1; + + FOR_ALL_CHANNELS { + int ref_card[NUM_SLOTS]; + for (slot = 0; slot < NUM_SLOTS; slot++) { + spd_slot = 2 * channel + slot; + spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]); + if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) { + // set dimm invalid + dimm->dimm[channel][slot].ranks = 0; + dimm->dimm[channel][slot].size_mb = 0; + continue; + } + + dram_print_spd_ddr3(&dimm->dimm[channel][slot]); + dimms++; + ctrl->rank_mirror[channel][slot * 2] = 0; + ctrl->rank_mirror[channel][slot * 2 + 1] = spd[spd_slot][0x3f] & 1; + + ctrl->auto_self_refresh &= (spd[spd_slot][31] >> 2) & 1; + ctrl->extended_temperature_range &= spd[spd_slot][31] & 1; + + ctrl->rankmap[channel] = ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot); + ref_card[channel] = spd[spd_slot][62] & 0x1f;; + printk(BIOS_DEBUG, "rankmap[%d] = 0x%x\n", channel, ctrl->rankmap[channel]); + } + if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc) + && ref_card[0] <= 5 && ref_card[1] <= 5) { + const int ref_card_offset_table[6][6] = { + { 0, 0, 0, 0, 2, 2, }, + { 0, 0, 0, 0, 2, 2, }, + { 0, 0, 0, 0, 2, 2, }, + { 0, 0, 0, 0, 1, 1, }, + { 2, 2, 2, 1, 0, 0, }, + { 2, 2, 2, 1, 0, 0, }, + }; + ctrl->ref_card_offset[channel] = ref_card_offset_table[ref_card[0]][ref_card[1]]; + } else + ctrl->ref_card_offset[channel] = 0; + } + + if (!dimms) + die("No DIMMs were found"); +} + +static void dram_find_common_params(const dimm_info * dimms, + ramctr_timing * ctrl) +{ + size_t valid_dimms; + int channel, slot; + ctrl->cas_supported = 0xff; + valid_dimms = 0; + FOR_ALL_CHANNELS + for (slot = 0; slot < 2; slot++) { + const dimm_attr *dimm = &dimms->dimm[channel][slot]; + if (dimm->dram_type == SPD_MEMORY_TYPE_UNDEFINED) + continue; + valid_dimms++; + + if (valid_dimms == 1) { + /* First DIMM defines the type of DIMM */ + ctrl->dram_type = dimm->dram_type; + } else { + /* Check if we have mismatched DIMMs */ + if (ctrl->dram_type != dimm->dram_type) + die("Mismatched DIMM Types"); + } + /* Find all possible CAS combinations */ + ctrl->cas_supported &= dimm->cas_supported; + + /* Find the smallest common latencies supported by all DIMMs */ + ctrl->tCK = MAX(ctrl->tCK, dimm->tCK); + ctrl->tAA = MAX(ctrl->tAA, dimm->tAA); + ctrl->tWR = MAX(ctrl->tWR, dimm->tWR); + ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD); + ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD); + ctrl->tRP = MAX(ctrl->tRP, dimm->tRP); + ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS); + ctrl->tRC = MAX(ctrl->tRC, dimm->tRC); + ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC); + ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR); + ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP); + ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW); + } + + ctrl->n_dimms = valid_dimms; + if (!ctrl->cas_supported) + die("Unsupported DIMM combination. " + "DIMMS do not support common CAS latency"); + if (!valid_dimms) + die("No valid DIMMs found"); + + ctrl->dualchannel = + (pcie_read_config32(PCI_DEV(0, 0, 0), 0xE4) & 0x4000) >> 14; + if (ctrl->dualchannel) { + printk(BIOS_DEBUG, "Dual channel supported\n"); + } else { + printk(BIOS_DEBUG, "Dual channel not supported\n"); + } +} + +static u8 get_CWL(u8 CAS) +{ + /* Get CWL based on CAS using the following rule: + * _________________________________________ + * CAS: | 4T | 5T | 6T | 7T | 8T | 9T | 10T | 11T | + * CWL: | 5T | 5T | 5T | 6T | 6T | 7T | 7T | 8T | + */ + static const u8 cas_cwl_map[] = { 5, 5, 5, 6, 6, 7, 7, 8 }; + if (CAS > 11) + return 8; + return cas_cwl_map[CAS - 4]; +} + +static u32 get_REFI(u32 tCK) +{ + /* Get REFI based on MCU frequency using the following rule: + * _________________________________________ + * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | + * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 | + */ + u32 FRQ = (u32) 256000 / (tCK * BASEFREQ); + static const u32 frq_refi_map[] = + { 3120, 4160, 5200, 6240, 7280, 8320 }; + if (FRQ > 8) + return 8320; + return frq_refi_map[FRQ - 3]; +} + +static u8 get_XSOffset(u32 tCK) +{ + /* Get XSOffset based on MCU frequency using the following rule: + * _________________________ + * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | + * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 | + */ + u32 FRQ = (u32) 256000 / (tCK * BASEFREQ); + static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 }; + if (FRQ > 8) + return 11; + return frq_xs_map[FRQ - 3]; +} + +static u8 get_MOD(u32 tCK) +{ + /* Get MOD based on MCU frequency using the following rule: + * _____________________________ + * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | + * MOD : | 12 | 12 | 12 | 12 | 15 | 16 | + */ + u32 FRQ = (u32) 256000 / (tCK * BASEFREQ); + static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 }; + if (FRQ > 8) + return 16; + return frq_mod_map[FRQ - 3]; +} + +static u8 get_WLO(u32 tCK) +{ + /* Get WLO based on MCU frequency using the following rule: + * _______________________ + * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | + * WLO : | 4 | 5 | 6 | 6 | 8 | 8 | + */ + u32 FRQ = (u32) 256000 / (tCK * BASEFREQ); + static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 }; + if (FRQ > 8) + return 8; + return frq_wlo_map[FRQ - 3]; +} + +static u8 get_CKE(u32 tCK) +{ + /* Get CKE based on MCU frequency using the following rule: + * _______________________ + * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | + * CKE : | 3 | 3 | 4 | 4 | 5 | 6 | + */ + u32 FRQ = (u32) 256000 / (tCK * BASEFREQ); + static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 }; + if (FRQ > 8) + return 6; + return frq_cke_map[FRQ - 3]; +} + +static u8 get_XPDLL(u32 tCK) +{ + /* Get XPDLL based on MCU frequency using the following rule: + * _____________________________ + * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | + * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 | + */ + u32 FRQ = (u32) 256000 / (tCK * BASEFREQ); + static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 }; + if (FRQ > 8) + return 26; + return frq_xpdll_map[FRQ - 3]; +} + +static u8 get_XP(u32 tCK) +{ + /* Get XP based on MCU frequency using the following rule: + * _______________________ + * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | + * XP : | 3 | 4 | 4 | 5 | 6 | 7 | + */ + u32 FRQ = (u32) 256000 / (tCK * BASEFREQ); + static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 }; + if (FRQ > 8) + return 7; + return frq_xp_map[FRQ - 3]; +} + +static u8 get_AONPD(u32 tCK) +{ + /* Get AONPD based on MCU frequency using the following rule: + * ________________________ + * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | + * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 | + */ + u32 FRQ = (u32) 256000 / (tCK * BASEFREQ); + static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 }; + if (FRQ > 8) + return 10; + return frq_aonpd_map[FRQ - 3]; +} + +static u32 get_COMP2(u32 tCK) +{ + /* Get COMP2 based on MCU frequency using the following rule: + * ___________________________________________________________ + * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | + * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C | + */ + u32 FRQ = (u32) 256000 / (tCK * BASEFREQ); + static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C, + 0xC6369CC, 0xC42514C, 0xC21410C + }; + if (FRQ > 8) + return 0xD6BEDCC; + return frq_comp2_map[FRQ - 3]; +} + +static void dram_timing(ramctr_timing * ctrl) +{ + u8 val; + u32 val32; + + /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure + * we cap it if we have faster DIMMs. + * Then, align it to the closest JEDEC standard frequency */ + if (ctrl->tCK <= TCK_1066MHZ) { + ctrl->tCK = TCK_1066MHZ; + ctrl->delay1 = 16; + ctrl->delay2 = 8; + ctrl->edge_offset[0] = 16; + ctrl->edge_offset[1] = 7; + ctrl->edge_offset[2] = 7; + ctrl->timC_offset[0] = 18; + ctrl->timC_offset[1] = 7; + ctrl->timC_offset[2] = 7; + ctrl->reg_c14_offset = 16; + ctrl->reg_5064b0 = 0x218; + } else if (ctrl->tCK <= TCK_933MHZ) { + ctrl->tCK = TCK_933MHZ; + ctrl->delay1 = 15; + ctrl->delay2 = 8; + ctrl->edge_offset[0] = 14; + ctrl->edge_offset[1] = 6; + ctrl->edge_offset[2] = 6; + ctrl->timC_offset[0] = 15; + ctrl->timC_offset[1] = 6; + ctrl->timC_offset[2] = 6; + ctrl->reg_c14_offset = 14; + ctrl->reg_5064b0 = 0x1d5; + } else if (ctrl->tCK <= TCK_800MHZ) { + ctrl->tCK = TCK_800MHZ; + ctrl->delay1 = 12; + ctrl->delay2 = 6; + ctrl->edge_offset[0] = 13; + ctrl->edge_offset[1] = 5; + ctrl->edge_offset[2] = 5; + ctrl->timC_offset[0] = 14; + ctrl->timC_offset[1] = 5; + ctrl->timC_offset[2] = 5; + ctrl->reg_c14_offset = 12; + ctrl->reg_5064b0 = 0x193; + } else if (ctrl->tCK <= TCK_666MHZ) { + ctrl->tCK = TCK_666MHZ; + ctrl->delay1 = 12; + ctrl->delay2 = 6; + ctrl->edge_offset[0] = 10; + ctrl->edge_offset[1] = 4; + ctrl->edge_offset[2] = 4; + ctrl->timC_offset[0] = 11; + ctrl->timC_offset[1] = 4; + ctrl->timC_offset[2] = 4; + ctrl->reg_c14_offset = 10; + ctrl->reg_5064b0 = 0x150; + } else { + ctrl->tCK = TCK_533MHZ; + ctrl->delay1 = 12; + ctrl->delay2 = 5; + ctrl->edge_offset[0] = 8; + ctrl->edge_offset[1] = 3; + ctrl->edge_offset[2] = 3; + ctrl->timC_offset[0] = 9; + ctrl->timC_offset[1] = 3; + ctrl->timC_offset[2] = 3; + ctrl->reg_c14_offset = 8; + ctrl->reg_5064b0 = 0x10d; + } + + val32 = (1000 << 8) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32); + + /* Find CAS and CWL latencies */ + val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val); + /* Find lowest supported CAS latency that satisfies the minimum value */ + while (!((ctrl->cas_supported >> (val - 4)) & 1) + && (ctrl->cas_supported >> (val - 4))) { + val++; + } + /* Is CAS supported */ + if (!(ctrl->cas_supported & (1 << (val - 4)))) + printk(BIOS_DEBUG, "CAS not supported\n"); + printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val); + ctrl->CAS = val; + ctrl->CWL = get_CWL(ctrl->CAS); + printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL); + + /* Find tRCD */ + ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD); + + ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP); + + /* Find tRAS */ + ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS); + + /* Find tWR */ + ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR); + + /* Find tFAW */ + ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW); + + /* Find tRRD */ + ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD); + + /* Find tRTP */ + ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP); + + /* Find tWTR */ + ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR); + + /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */ + ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC); + + ctrl->tRC = (ctrl->tRC + ctrl->tCK - 1) / ctrl->tCK; + printk(BIOS_DEBUG, "Required tRC : %uT\n", ctrl->tRC); + + ctrl->tREFI = get_REFI(ctrl->tCK); + ctrl->tMOD = get_MOD(ctrl->tCK); + ctrl->tXSOffset = get_XSOffset(ctrl->tCK); + ctrl->tWLO = get_WLO(ctrl->tCK); + ctrl->tCKE = get_CKE(ctrl->tCK); + ctrl->tXPDLL = get_XPDLL(ctrl->tCK); + ctrl->tXP = get_XP(ctrl->tCK); + ctrl->tAONPD = get_AONPD(ctrl->tCK); +} + +static void dram_freq(ramctr_timing * ctrl) +{ + u8 val1, val2; + u32 reg1 = 0; + + /* Step 1 - Set target PCU frequency */ + + if (ctrl->tCK <= TCK_1066MHZ) { + val1 = 0x08; + ctrl->tCK = TCK_1066MHZ; + } else if (ctrl->tCK <= TCK_933MHZ) { + val1 = 0x07; + ctrl->tCK = TCK_933MHZ; + } else if (ctrl->tCK <= TCK_800MHZ) { + val1 = 0x06; + ctrl->tCK = TCK_800MHZ; + } else if (ctrl->tCK <= TCK_666MHZ) { + val1 = 0x05; + ctrl->tCK = TCK_666MHZ; + } else { + val1 = 0x04; + ctrl->tCK = TCK_533MHZ; + } + + /* Step 2 - Select frequency in the MCU */ + reg1 = val1; + reg1 |= 0x80000000; // set running bit + MCHBAR32(0x5e00) = reg1; + while (reg1 & 0x80000000) { + printk(BIOS_DEBUG, " PLL busy..."); + reg1 = MCHBAR32(0x5e00); + } + printk(BIOS_DEBUG, "done\n"); + + /* Step 3 - Verify lock frequency */ + reg1 = MCHBAR32(0x5e04); + val2 = (u8) reg1; + if (val2 > val1) { + printk(BIOS_DEBUG, "Lock frequency is lower, recalculating\n"); + switch (val2) { + case 8: + ctrl->tCK = TCK_1066MHZ; + break; + case 7: + ctrl->tCK = TCK_933MHZ; + break; + case 6: + ctrl->tCK = TCK_800MHZ; + break; + case 5: + ctrl->tCK = TCK_666MHZ; + break; + case 4: + ctrl->tCK = TCK_533MHZ; + break; + default: + printk(BIOS_DEBUG, "ERROR: PLL is off or unknown\n"); + break; + } + dram_timing(ctrl); // recalculate timings + } + printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n", + (1000 << 8) / ctrl->tCK); +} + +static void dram_xover(ramctr_timing * ctrl) +{ + u32 reg; + int channel; + + FOR_ALL_CHANNELS { + // enable xover clk + printk(BIOS_DEBUG, "[%x] = %x\n", channel * 0x100 + 0xc14, + (ctrl->rankmap[channel] << 24)); + MCHBAR32(channel * 0x100 + 0xc14) = (ctrl->rankmap[channel] << 24); + + // enable xover ctl + reg = 0; + if (ctrl->rankmap[channel] & 0x5) { + reg |= 0x20000; + } + if (ctrl->rankmap[channel] & 0xa) { + reg |= 0x4000000; + } + // enable xover cmd + reg |= 0x4000; + printk(BIOS_DEBUG, "[%x] = %x\n", 0x100 * channel + 0x320c, + reg); + MCHBAR32(0x100 * channel + 0x320c) = reg; + } +} + +static void dram_timing_regs(ramctr_timing * ctrl) +{ + u32 reg, addr, val32, cpu, stretch; + struct cpuid_result cpures; + int channel; + + FOR_ALL_CHANNELS { + // DBP + reg = 0; + reg |= ctrl->tRCD; + reg |= (ctrl->tRP << 4); + reg |= (ctrl->CAS << 8); + reg |= (ctrl->CWL << 12); + reg |= (ctrl->tRAS << 16); + printk(BIOS_DEBUG, "[%x] = %x\n", 0x400 * channel + 0x4000, + reg); + MCHBAR32(0x400 * channel + 0x4000) = reg; + + // RAP + reg = 0; + reg |= ctrl->tRRD; + reg |= (ctrl->tRTP << 4); + reg |= (ctrl->tCKE << 8); + reg |= (ctrl->tWTR << 12); + reg |= (ctrl->tFAW << 16); + reg |= (ctrl->tWR << 24); + reg |= (3 << 30); + printk(BIOS_DEBUG, "[%x] = %x\n", 0x400 * channel + 0x4004, + reg); + MCHBAR32(0x400 * channel + 0x4004) = reg; + + // OTHP + addr = 0x400 * channel + 0x400c; + reg = 0; + reg |= ctrl->tXPDLL; + reg |= (ctrl->tXP << 5); + reg |= (ctrl->tAONPD << 8); + reg |= 0xa0000; + printk(BIOS_DEBUG, "[%x] = %x\n", addr, reg); + MCHBAR32(addr) = reg; + + MCHBAR32(0x400 * channel + 0x4014) = 0; + + MCHBAR32(addr) |= 0x00020000; + + // ODT stretch + reg = 0; + + cpures = cpuid(0); + cpu = cpures.eax; + if (IS_IVY_CPU(cpu) + || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) { + stretch = 2; + addr = 0x400 * channel + 0x400c; + printk(BIOS_DEBUG, "[%x] = %x\n", + 0x400 * channel + 0x400c, reg); + reg = MCHBAR32(addr); + + if (((ctrl->rankmap[channel] & 3) == 0) + || (ctrl->rankmap[channel] & 0xc) == 0) { + + // Rank 0 - operate on rank 2 + reg = (reg & ~0xc0000) | (stretch << 18); + + // Rank 2 - operate on rank 0 + reg = (reg & ~0x30000) | (stretch << 16); + + printk(BIOS_DEBUG, "[%x] = %x\n", addr, reg); + MCHBAR32(addr) = reg; + } + + } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) { + stretch = 3; + addr = 0x400 * channel + 0x401c; + reg = MCHBAR32(addr); + + if (((ctrl->rankmap[channel] & 3) == 0) + || (ctrl->rankmap[channel] & 0xc) == 0) { + + // Rank 0 - operate on rank 2 + reg = (reg & ~0x3000) | (stretch << 12); + + // Rank 2 - operate on rank 0 + reg = (reg & ~0xc00) | (stretch << 10); + + printk(BIOS_DEBUG, "[%x] = %x\n", addr, reg); + MCHBAR32(addr) = reg; + } + } else { + stretch = 0; + } + + // REFI + reg = 0; + val32 = ctrl->tREFI; + reg = (reg & ~0xffff) | val32; + val32 = ctrl->tRFC; + reg = (reg & ~0x1ff0000) | (val32 << 16); + val32 = (u32) (ctrl->tREFI * 9) / 1024; + reg = (reg & ~0xfe000000) | (val32 << 25); + printk(BIOS_DEBUG, "[%x] = %x\n", 0x400 * channel + 0x4298, + reg); + MCHBAR32(0x400 * channel + 0x4298) = reg; + + MCHBAR32(0x400 * channel + 0x4294) |= 0xff; + + // SRFTP + reg = 0; + val32 = tDLLK; + reg = (reg & ~0xfff) | val32; + val32 = ctrl->tXSOffset; + reg = (reg & ~0xf000) | (val32 << 12); + val32 = tDLLK - ctrl->tXSOffset; + reg = (reg & ~0x3ff0000) | (val32 << 16); + val32 = ctrl->tMOD - 8; + reg = (reg & ~0xf0000000) | (val32 << 28); + printk(BIOS_DEBUG, "[%x] = %x\n", 0x400 * channel + 0x42a4, + reg); + MCHBAR32(0x400 * channel + 0x42a4) = reg; + } +} + +static void dram_dimm_mapping(dimm_info * info, ramctr_timing * ctrl) +{ + int t; + u32 reg, val32; + int channel; + + FOR_ALL_CHANNELS { + dimm_attr *dimmA = 0; + dimm_attr *dimmB = 0; + reg = 0; + val32 = 0; + if (info->dimm[channel][0].size_mb >= + info->dimm[channel][1].size_mb) { + // dimm 0 is bigger, set it to dimmA + dimmA = &info->dimm[channel][0]; + dimmB = &info->dimm[channel][1]; + reg |= (0 << 16); + } else { + // dimm 1 is bigger, set it to dimmA + dimmA = &info->dimm[channel][1]; + dimmB = &info->dimm[channel][0]; + reg |= (1 << 16); + // swap dimm info + t = ctrl->rank_mirror[channel][1]; + ctrl->rank_mirror[channel][1] = + ctrl->rank_mirror[channel][3]; + ctrl->rank_mirror[channel][3] = t; + } + // dimmA + if (dimmA && (dimmA->ranks > 0)) { + val32 = dimmA->size_mb / 256; + reg = (reg & ~0xff) | val32; + val32 = dimmA->ranks - 1; + reg = (reg & ~0x20000) | (val32 << 17); + val32 = (dimmA->width / 8) - 1; + reg = (reg & ~0x80000) | (val32 << 19); + } + // dimmB + if (dimmB && (dimmB->ranks > 0)) { + val32 = dimmB->size_mb / 256; + reg = (reg & ~0xff00) | (val32 << 8); + val32 = dimmB->ranks - 1; + reg = (reg & ~0x40000) | (val32 << 18); + val32 = (dimmB->width / 8) - 1; + reg = (reg & ~0x100000) | (val32 << 20); + } + reg = (reg & ~0x200000) | (1 << 21); // rank interleave + reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave + + // Set MAD-DIMM register + if ((dimmA && (dimmA->ranks > 0)) + || (dimmB && (dimmB->ranks > 0))) { + MCHBAR32(0x5004 + channel * 4) = reg; + } + } +} + +static void dram_zones(dimm_info * info, ramctr_timing * ctrl, int training) +{ + u32 reg, ch0size, ch1size; + u8 val; + reg = 0; + val = 0; + if (training) { + ch0size = + info->dimm[0][0].size_mb + info->dimm[0][1].size_mb ? 256 : 0; + ch1size = + info->dimm[1][0].size_mb + info->dimm[1][1].size_mb ? 256 : 0; + } else { + ch0size = info->dimm[0][0].size_mb + info->dimm[0][1].size_mb; + ch1size = info->dimm[1][0].size_mb + info->dimm[1][1].size_mb; + } + + if (ch0size >= ch1size) { + reg = MCHBAR32(0x5014); + val = ch1size / 256; + reg = (reg & ~0xff000000) | val << 24; + reg = (reg & ~0xff0000) | (2 * val) << 16; + MCHBAR32(0x5014) = reg; + MCHBAR32(0x5000) = 0x24; + } else { + reg = MCHBAR32(0x5014); + val = ch0size / 256; + reg = (reg & ~0xff000000) | val << 24; + reg = (reg & ~0xff0000) | (2 * val) << 16; + MCHBAR32(0x5014) = reg; + MCHBAR32(0x5000) = 0x21; + } +} + +/* FIXME: this function bugs. */ +static void dram_memorymap(dimm_info * info, int me_uma_size) +{ + u32 reg, val, reclaim; + u32 tom, gfxstolen, gttsize; + size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase, + tsegbase, mestolenbase; + size_t tsegbasedelta, remapbase, remaplimit; + uint16_t ggc; + + mmiosize = 0x400; + + ggc = pci_read_config16(NORTHBRIDGE, GGC); + if (!(ggc & 2)) { + gfxstolen = ((ggc >> 3) & 0x1f) * 32; + gttsize = ((ggc >> 8) & 0x3); + } else { + gfxstolen = 0; + gttsize = 0; + } + + tsegsize = CONFIG_SMM_TSEG_SIZE >> 20; + + tom = + info->dimm[0][0].size_mb + info->dimm[0][1].size_mb + + info->dimm[0][1].size_mb + info->dimm[1][1].size_mb; + + mestolenbase = tom - me_uma_size; + + toludbase = MIN(4096 - mmiosize, tom - me_uma_size); + gfxstolenbase = toludbase - gfxstolen; + gttbase = gfxstolenbase - gttsize; + + tsegbase = gttbase - tsegsize; + + // Round tsegbase down to nearest address aligned to tsegsize + tsegbasedelta = tsegbase & (tsegsize - 1); + tsegbase &= ~(tsegsize - 1); + + gttbase -= tsegbasedelta; + gfxstolenbase -= tsegbasedelta; + toludbase -= tsegbasedelta; + + // Test if it is possible to reclaim a hole in the ram addressing + if (tom - me_uma_size > toludbase) { + // Reclaim is possible + reclaim = 1; + remapbase = MAX(4096, tom - me_uma_size); + remaplimit = + remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1; + touudbase = remaplimit + 1; + } else { + // Reclaim not possible + reclaim = 0; + touudbase = tom - me_uma_size; + } + + // Update memory map in pci-e configuration space + + // TOM (top of memory) + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0); + val = tom & 0xfff; + reg = (reg & ~0xfff00000) | (val << 20); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0xa0, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg); + + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4); + val = tom & 0xfffff000; + reg = (reg & ~0x000fffff) | (val >> 12); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0xa4, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg); + + // TOLUD (top of low used dram) + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc); + val = toludbase & 0xfff; + reg = (reg & ~0xfff00000) | (val << 20); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0xbc, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg); + + // TOUUD LSB (top of upper usable dram) + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8); + val = touudbase & 0xfff; + reg = (reg & ~0xfff00000) | (val << 20); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0xa8, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg); + + // TOUUD MSB + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac); + val = touudbase & 0xfffff000; + reg = (reg & ~0x000fffff) | (val >> 12); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0xac, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg); + + if (reclaim) { + // REMAP BASE + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x94); + val = remapbase & 0xfffff000; + reg = (reg & ~0x000fffff) | (val >> 12); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0x94, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, reg); + + // REMAP LIMIT + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x98); + val = remaplimit & 0xfff; + reg = (reg & ~0xfff00000) | (val << 20); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0x98, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, reg); + + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x9c); + val = remaplimit & 0xfffff000; + reg = (reg & ~0x000fffff) | (val >> 12); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0x9c, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, reg); + } + // TSEG + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8); + val = tsegbase & 0xfff; + reg = (reg & ~0xfff00000) | (val << 20); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0xb8, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg); + + // GFX stolen memory + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0); + val = gfxstolenbase & 0xfff; + reg = (reg & ~0xfff00000) | (val << 20); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0xb0, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg); + + // GTT stolen memory + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4); + val = gttbase & 0xfff; + reg = (reg & ~0xfff00000) | (val << 20); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0xb4, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg); + + if (me_uma_size) { + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c); + val = (0x80000 - me_uma_size) & 0xfffff000; + reg = (reg & ~0x000fffff) | (val >> 12); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0x7c, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg); + + // ME base + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70); + val = mestolenbase & 0xfff; + reg = (reg & ~0xfff00000) | (val << 20); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0x70, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg); + + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74); + val = mestolenbase & 0xfffff000; + reg = (reg & ~0x000fffff) | (val >> 12); + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0x74, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg); + + // ME mask + reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78); + val = (0x80000 - me_uma_size) & 0xfff; + reg = (reg & ~0xfff00000) | (val << 20); + reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem + + reg = (reg & ~0x800) | (1 << 11); // set ME memory enable + printk(BIOS_DEBUG, "PCI:[%x] = %x\n", 0x78, reg); + pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg); + } +} + +static void dram_ioregs(ramctr_timing * ctrl) +{ + u32 reg, comp2; + + int channel; + + // IO clock + FOR_ALL_CHANNELS { + MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel]; + } + + // IO command + FOR_ALL_CHANNELS { + MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel]; + } + + // IO control + FOR_ALL_POPULATED_CHANNELS { + program_timings(ctrl, channel); + } + + // Rcomp + printk(BIOS_DEBUG, "RCOMP..."); + reg = 0; + while (reg == 0) { + reg = MCHBAR32(0x5084) & 0x10000; + } + printk(BIOS_DEBUG, "done\n"); + + // Set comp2 + comp2 = get_COMP2(ctrl->tCK); + MCHBAR32(0x3714) = comp2; + printk(BIOS_DEBUG, "COMP2 done\n"); + + // Set comp1 + FOR_ALL_POPULATED_CHANNELS { + reg = MCHBAR32(0x1810 + channel * 0x100); //ch0 + reg = (reg & ~0xe00) | (1 << 9); //odt + reg = (reg & ~0xe00000) | (1 << 21); //clk drive up + reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up + MCHBAR32(0x1810 + channel * 0x100) = reg; + } + printk(BIOS_DEBUG, "COMP1 done\n"); + + printk(BIOS_DEBUG, "FORCE RCOMP and wait 20us..."); + MCHBAR32(0x5f08) |= 0x100; + udelay(20); + printk(BIOS_DEBUG, "done\n"); +} + +static void wait_428c(int channel) +{ + while (1) { + if (read32(DEFAULT_MCHBAR | 0x428c | (channel << 10)) & 0x50) + return; + } +} + +static void write_reset(ramctr_timing * ctrl) +{ + int channel, slotrank; + + /* choose a populated channel. */ + channel = (ctrl->rankmap[0]) ? 0 : 1; + + wait_428c(channel); + + /* choose a populated rank. */ + slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2; + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01); + + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60000); + + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001); + wait_428c(channel); +} + +static void dram_jedecreset(ramctr_timing * ctrl) +{ + u32 reg, addr; + int channel; + + while (!(MCHBAR32(0x5084) & 0x10000)) ; + do { + reg = MCHBAR32(0x428c); + } while ((reg & 0x14) == 0); + + // Set state of memory controller + reg = 0x112; + MCHBAR32(0x5030) = reg; + MCHBAR32(0x4ea0) = 0; + reg |= 2; //ddr reset + MCHBAR32(0x5030) = reg; + + // Assert dimm reset signal + reg = MCHBAR32(0x5030); + reg &= ~0x2; + MCHBAR32(0x5030) = reg; + + // Wait 200us + udelay(200); + + // Deassert dimm reset signal + MCHBAR32(0x5030) |= 2; + + // Wait 500us + udelay(500); + + // Enable DCLK + MCHBAR32(0x5030) |= 4; + + // XXX Wait 20ns + udelay(1); + + FOR_ALL_CHANNELS { + // Set valid rank CKE + reg = 0; + reg = (reg & ~0xf) | ctrl->rankmap[channel]; + addr = 0x400 * channel + 0x42a0; + MCHBAR32(addr) = reg; + + // Wait 10ns for ranks to settle + //udelay(0.01); + + reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4); + MCHBAR32(addr) = reg; + + // Write reset using a NOP + write_reset(ctrl); + } +} + +static odtmap get_ODT(ramctr_timing * ctrl, u8 rank) +{ + /* Get ODT based on rankmap: */ + int dimms_per_ch = 0; + int channel; + + FOR_ALL_CHANNELS { + dimms_per_ch = max ((ctrl->rankmap[channel] & 1) + + ((ctrl->rankmap[channel] >> 2) & 1), + dimms_per_ch); + } + + if (dimms_per_ch == 1) { + return (const odtmap){60, 60}; + } else if (dimms_per_ch == 2) { + return (const odtmap){120, 30}; + } else { + printk(BIOS_DEBUG, + "Huh, no dimms? m0 = %d m1 = %d dpc = %d\n", + ctrl->rankmap[0], + ctrl->rankmap[1], dimms_per_ch); + die(""); + } +} + +static void write_mrreg(ramctr_timing * ctrl, int channel, int slotrank, + int reg, u32 val) +{ + wait_428c(channel); + + printk(BIOS_SPEW, "MRd: %x <= %x\n", reg, val); + + if (ctrl->rank_mirror[channel][slotrank]) { + reg = ((reg >> 1) & 1) | ((reg << 1) & 2); + val = (val & ~0x1f8) | ((val >> 1) & 0xa8) + | ((val & 0xa8) << 1); + } + + printk(BIOS_SPEW, "MRd: %x <= %x\n", reg, val); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | (reg << 20) | val | 0x60000); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | (reg << 20) | val | 0x60000); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x1001 | (ctrl->delay1 << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24) | (reg << 20) | val | 0x60000); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0); + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001); +} + +static u32 make_mr0(ramctr_timing * ctrl, u8 rank) +{ + u16 mr0reg, mch_cas, mch_wr; + static const u8 mch_wr_t[12] = { 1, 2, 3, 4, 0, 5, 0, 6, 0, 7, 0, 0 }; + mr0reg = 0x100; + + // Convert CAS to MCH register friendly + if (ctrl->CAS < 12) { + mch_cas = (u16) ((ctrl->CAS - 4) << 1); + } else { + mch_cas = (u16) (ctrl->CAS - 12); + mch_cas = ((mch_cas << 1) | 0x1); + } + + // Convert tWR to MCH register friendly + mch_wr = mch_wr_t[ctrl->tWR - 5]; + + mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1); + mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3); + mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9); + // Fast (desktop) 0x1 or slow (mobile) 0x0 + mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12); + return mr0reg; +} + +static void dram_mr0(ramctr_timing * ctrl, u8 rank) +{ + int channel; + + FOR_ALL_POPULATED_CHANNELS write_mrreg(ctrl, channel, rank, 0, + make_mr0(ctrl, rank)); +} + +static u32 encode_odt(u32 odt) +{ + switch (odt) { + case 30: + return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4 + case 60: + return (1 << 2); // RZQ/4 + case 120: + return (1 << 6); // RZQ/2 + default: + case 0: + return 0; + } +} + +static u32 make_mr1(ramctr_timing * ctrl, u8 rank) +{ + odtmap odt; + u32 mr1reg; + + odt = get_ODT(ctrl, rank); + mr1reg = 0x2; + + mr1reg |= encode_odt(odt.rttnom); + + return mr1reg; +} + +static void dram_mr1(ramctr_timing * ctrl, u8 rank) +{ + u16 mr1reg; + int channel; + + mr1reg = make_mr1(ctrl, rank); + + FOR_ALL_CHANNELS { + write_mrreg(ctrl, channel, rank, 1, mr1reg); + } +} + +static void dram_mr2(ramctr_timing * ctrl, u8 rank) +{ + u16 pasr, cwl, mr2reg; + odtmap odt; + int channel; + int srt; + + pasr = 0; + cwl = ctrl->CWL - 5; + odt = get_ODT(ctrl, rank); + + srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh; + + mr2reg = 0; + mr2reg = (mr2reg & ~0x7) | pasr; + mr2reg = (mr2reg & ~0x38) | (cwl << 3); + mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6); + mr2reg = (mr2reg & ~0x80) | (srt << 7); + mr2reg |= (odt.rttwr / 60) << 9; + + FOR_ALL_CHANNELS { + write_mrreg(ctrl, channel, rank, 2, mr2reg); + } +} + +static void dram_mr3(ramctr_timing * ctrl, u8 rank) +{ + int channel; + + FOR_ALL_CHANNELS { + write_mrreg(ctrl, channel, rank, 3, 0); + } +} + +static void dram_mrscommands(ramctr_timing * ctrl) +{ + u8 rank; + u32 reg, addr; + int channel; + + for (rank = 0; rank < 4; rank++) { + // MR2 + printk(BIOS_SPEW, "MR2 rank %d...", rank); + dram_mr2(ctrl, rank); + printk(BIOS_SPEW, "done\n"); + + // MR3 + printk(BIOS_SPEW, "MR3 rank %d...", rank); + dram_mr3(ctrl, rank); + printk(BIOS_SPEW, "done\n"); + + // MR1 + printk(BIOS_SPEW, "MR1 rank %d...", rank); + dram_mr1(ctrl, rank); + printk(BIOS_SPEW, "done\n"); + + // MR0 + printk(BIOS_SPEW, "MR0 rank %d...", rank); + dram_mr0(ctrl, rank); + printk(BIOS_SPEW, "done\n"); + } + + write32(DEFAULT_MCHBAR + 0x4e20, 0x7); + write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001); + write32(DEFAULT_MCHBAR + 0x4e00, 0x60002); + write32(DEFAULT_MCHBAR + 0x4e10, 0); + write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003); + write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001); + write32(DEFAULT_MCHBAR + 0x4e04, 0x60400); + write32(DEFAULT_MCHBAR + 0x4e14, 0x288); + write32(DEFAULT_MCHBAR + 0x4e84, 0x40004); + + // Drain + FOR_ALL_CHANNELS { + // Wait for ref drained + wait_428c(channel); + } + + // Refresh enable + MCHBAR32(0x5030) |= 8; + + FOR_ALL_POPULATED_CHANNELS { + addr = 0x400 * channel + 0x4020; + reg = MCHBAR32(addr); + reg &= ~0x200000; + MCHBAR32(addr) = reg; + + wait_428c(channel); + + rank = (ctrl->rankmap[channel] & 1) ? 0 : 2; + + // Drain + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (rank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0); + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1); + + // Drain + wait_428c(channel); + } +} + +const u32 lane_registers[] = { + 0x0000, 0x0200, 0x0400, 0x0600, + 0x1000, 0x1200, 0x1400, 0x1600, + 0x0800 +}; + +static int clamp(int val, int low, int up) +{ + if (val < low) + return low; + if (val > up) + return up; + return val; +} + +static void program_timings(ramctr_timing * ctrl, int channel) +{ + u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028; + int lane; + int slotrank, slot; + int full_shift = 0; + u16 slot320c[NUM_SLOTS]; + + FOR_ALL_POPULATED_RANKS if (full_shift < + -ctrl->timings[channel][slotrank].val_320c) + full_shift = -ctrl->timings[channel][slotrank].val_320c; + + for (slot = 0; slot < NUM_SLOTS; slot++) + switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) { + case 0: + default: + slot320c[slot] = 0x7f; + break; + case 1: + slot320c[slot] = + ctrl->timings[channel][2 * slot + 0].val_320c + + full_shift; + break; + case 2: + slot320c[slot] = + ctrl->timings[channel][2 * slot + 1].val_320c + + full_shift; + break; + case 3: + slot320c[slot] = + (ctrl->timings[channel][2 * slot].val_320c + + ctrl->timings[channel][2 * slot + + 1].val_320c) / 2 + + full_shift; + break; + } + + reg32 = (1 << 17) | (1 << 14); + reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9); + reg32 |= (slot320c[1] & 0x7f) << 18; + reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6); + + MCHBAR32(0x320c + 0x100 * channel) = reg32; + + reg_c14 = ctrl->rankmap[channel] << 24; + reg_c18 = 0; + + FOR_ALL_POPULATED_RANKS { + int shift = + ctrl->timings[channel][slotrank].val_320c + full_shift; + int offset_val_c14; + if (shift < 0) + shift = 0; + offset_val_c14 = ctrl->reg_c14_offset + shift; + reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank); + reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank; + } + + MCHBAR32(0xc14 + channel * 0x100) = reg_c14; + MCHBAR32(0xc18 + channel * 0x100) = reg_c18; + + reg_4028 = MCHBAR32(0x4028 + 0x400 * channel); + reg_4028 &= 0xffff0000; + + reg_4024 = 0; + + FOR_ALL_POPULATED_RANKS { + int post_timA_min_high = 7, post_timA_max_high = 0; + int pre_timA_min_high = 7, pre_timA_max_high = 0; + int shift_402x = 0; + int shift = + ctrl->timings[channel][slotrank].val_320c + full_shift; + + if (shift < 0) + shift = 0; + + FOR_ALL_LANES { + if (post_timA_min_high > + ((ctrl->timings[channel][slotrank].lanes[lane]. + timA + shift) >> 6)) + post_timA_min_high = + ((ctrl->timings[channel][slotrank]. + lanes[lane].timA + shift) >> 6); + if (pre_timA_min_high > + (ctrl->timings[channel][slotrank].lanes[lane]. + timA >> 6)) + pre_timA_min_high = + (ctrl->timings[channel][slotrank]. + lanes[lane].timA >> 6); + if (post_timA_max_high < + ((ctrl->timings[channel][slotrank].lanes[lane]. + timA + shift) >> 6)) + post_timA_max_high = + ((ctrl->timings[channel][slotrank]. + lanes[lane].timA + shift) >> 6); + if (pre_timA_max_high < + (ctrl->timings[channel][slotrank].lanes[lane]. + timA >> 6)) + pre_timA_max_high = + (ctrl->timings[channel][slotrank]. + lanes[lane].timA >> 6); + } + + if (pre_timA_max_high - pre_timA_min_high < + post_timA_max_high - post_timA_min_high) + shift_402x = +1; + else if (pre_timA_max_high - pre_timA_min_high > + post_timA_max_high - post_timA_min_high) + shift_402x = -1; + + reg_4028 |= + (ctrl->timings[channel][slotrank].val_4028 + shift_402x - + post_timA_min_high) << (4 * slotrank); + reg_4024 |= + (ctrl->timings[channel][slotrank].val_4024 + + shift_402x) << (8 * slotrank); + + FOR_ALL_LANES { + MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel + + 4 * slotrank) + = + (((ctrl->timings[channel][slotrank].lanes[lane]. + timA + shift) & 0x3f) + | + ((ctrl->timings[channel][slotrank].lanes[lane]. + rising + shift) << 8) + | + (((ctrl->timings[channel][slotrank].lanes[lane]. + timA + shift - + (post_timA_min_high << 6)) & 0x1c0) << 10) + | (ctrl->timings[channel][slotrank].lanes[lane]. + falling << 20)); + + MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel + + 4 * slotrank) + = + ((clamp + (ctrl->timings[channel][slotrank].lanes[lane]. + timC + shift, 0, 127) & 0x3f) + | + (((ctrl->timings[channel][slotrank].lanes[lane]. + timB + shift) & 0x3f) << 8) + | + (((ctrl->timings[channel][slotrank].lanes[lane]. + timB + shift) & 0x1c0) << 9) + | + ((clamp + (ctrl->timings[channel][slotrank].lanes[lane]. + timC + shift, 0, 127) & 0x40) << 13)); + } + } + MCHBAR32(0x4024 + 0x400 * channel) = reg_4024; + MCHBAR32(0x4028 + 0x400 * channel) = reg_4028; +} + +static void test_timA(ramctr_timing * ctrl, int channel, int slotrank) +{ + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + (0xc01 | (ctrl->delay1 << 16))); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x360004); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x100f | ((ctrl->CAS + 36) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + (0xc01 | (ctrl->delay1 << 16))); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x360000); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001); + + wait_428c(channel); +} + +static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank, + int lane) +{ + u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA; + return ((read32 + (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 + + ((timA / 32) & 1) * 4) + >> (timA % 32)) & 1); +} + +struct run { + int middle; + int end; + int start; + int all; +}; + +static struct run get_longest_zero_run(int *seq, int sz) +{ + int i, ls; + int bl = 0, bs = 0; + struct run ret; + + ls = 0; + for (i = 0; i < 2 * sz; i++) + if (seq[i % sz]) { + if (i - ls > bl) { + bl = i - ls; + bs = ls; + } + ls = i + 1; + } + if (bl == 0) { + ret.middle = sz / 2; + ret.start = 0; + ret.end = sz; + ret.all = 1; + return ret; + } + + ret.start = bs % sz; + ret.end = (bs + bl - 1) % sz; + ret.middle = (bs + (bl - 1) / 2) % sz; + ret.all = 0; + + return ret; +} + +static void discover_timA_coarse(ramctr_timing * ctrl, int channel, + int slotrank, int *upperA) +{ + int timA; + int statistics[NUM_LANES][128]; + int lane; + + for (timA = 0; timA < 128; timA++) { + FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane]. + timA = timA; + program_timings(ctrl, channel); + + test_timA(ctrl, channel, slotrank); + + FOR_ALL_LANES { + statistics[lane][timA] = + !does_lane_work(ctrl, channel, slotrank, lane); + printk(BIOS_SPEW, "Astat: %d, %d, %d, %x, %x\n", + channel, slotrank, lane, timA, + statistics[lane][timA]); + } + } + FOR_ALL_LANES { + struct run rn = get_longest_zero_run(statistics[lane], 128); + ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle; + upperA[lane] = rn.end; + if (upperA[lane] < rn.middle) + upperA[lane] += 128; + printk(BIOS_SPEW, "Aval: %d, %d, %d, %x\n", channel, slotrank, + lane, ctrl->timings[channel][slotrank].lanes[lane].timA); + printk(BIOS_SPEW, "Aend: %d, %d, %d, %x\n", channel, slotrank, + lane, upperA[lane]); + } +} + +static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank, + int *upperA) +{ + int timA_delta; + int statistics[NUM_LANES][51]; + int lane, i; + + memset(statistics, 0, sizeof(statistics)); + + for (timA_delta = -25; timA_delta <= 25; timA_delta++) { + FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane]. + timA = upperA[lane] + timA_delta + 0x40; + program_timings(ctrl, channel); + + for (i = 0; i < 100; i++) { + test_timA(ctrl, channel, slotrank); + FOR_ALL_LANES { + statistics[lane][timA_delta + 25] += + does_lane_work(ctrl, channel, slotrank, + lane); + } + } + FOR_ALL_LANES { + printk(BIOS_SPEW, "A+stat: %d, %d, %d, %d (%x), %x\n", + channel, slotrank, lane, timA_delta, + upperA[lane] + timA_delta + 0x40, + statistics[lane][timA_delta + 25]); + } + } + FOR_ALL_LANES { + int last_zero, first_all; + + for (last_zero = -25; last_zero <= 25; last_zero++) + if (statistics[lane][last_zero + 25]) + break; + last_zero--; + for (first_all = -25; first_all <= 25; first_all++) + if (statistics[lane][first_all + 25] == 100) + break; + + printk(BIOS_SPEW, "lane %d: %d, %d\n", lane, last_zero, + first_all); + + ctrl->timings[channel][slotrank].lanes[lane].timA = + (last_zero + first_all) / 2 + upperA[lane]; + printk(BIOS_SPEW, "Aval: %d, %d, %d, %x\n", channel, slotrank, + lane, ctrl->timings[channel][slotrank].lanes[lane].timA); + } +} + +static void discover_402x(ramctr_timing * ctrl, int channel, int slotrank, + int *upperA) +{ + int works[NUM_LANES]; + int lane; + while (1) { + int all_works = 1, some_works = 0; + program_timings(ctrl, channel); + test_timA(ctrl, channel, slotrank); + FOR_ALL_LANES { + works[lane] = + !does_lane_work(ctrl, channel, slotrank, lane); + if (works[lane]) + some_works = 1; + else + all_works = 0; + } + if (all_works) + return; + if (!some_works) { + if (ctrl->timings[channel][slotrank].val_4024 < 2) + die("402x discovery failed"); + ctrl->timings[channel][slotrank].val_4024 -= 2; + printk(BIOS_SPEW, "4024 -= 2;\n"); + continue; + } + ctrl->timings[channel][slotrank].val_4028 += 2; + printk(BIOS_SPEW, "4028 += 2;\n"); + if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) + die("402x discovery failed"); + FOR_ALL_LANES if (works[lane]) { + ctrl->timings[channel][slotrank].lanes[lane].timA += + 128; + upperA[lane] += 128; + printk(BIOS_SPEW, "increment %d, %d, %d\n", channel, + slotrank, lane); + } + } +} + +struct timA_minmax { + int timA_min_high, timA_max_high; +}; + +static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank, + struct timA_minmax *mnmx) +{ + int lane; + mnmx->timA_min_high = 7; + mnmx->timA_max_high = 0; + + FOR_ALL_LANES { + if (mnmx->timA_min_high > + (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6)) + mnmx->timA_min_high = + (ctrl->timings[channel][slotrank].lanes[lane]. + timA >> 6); + if (mnmx->timA_max_high < + (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6)) + mnmx->timA_max_high = + (ctrl->timings[channel][slotrank].lanes[lane]. + timA >> 6); + } +} + +static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank, + struct timA_minmax *mnmx) +{ + struct timA_minmax post; + int shift_402x = 0; + + /* Get changed maxima. */ + pre_timA_change(ctrl, channel, slotrank, &post); + + if (mnmx->timA_max_high - mnmx->timA_min_high < + post.timA_max_high - post.timA_min_high) + shift_402x = +1; + else if (mnmx->timA_max_high - mnmx->timA_min_high > + post.timA_max_high - post.timA_min_high) + shift_402x = -1; + else + shift_402x = 0; + + ctrl->timings[channel][slotrank].val_4028 += shift_402x; + ctrl->timings[channel][slotrank].val_4024 += shift_402x; + printk(BIOS_SPEW, "4024 += %d;\n", shift_402x); + printk(BIOS_SPEW, "4028 += %d;\n", shift_402x); +} + +static void read_training(ramctr_timing * ctrl) +{ + int channel, slotrank, lane; + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { + u32 r32; + int all_high, some_high; + int upperA[NUM_LANES]; + struct timA_minmax mnmx; + + wait_428c(channel); + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0xc01 | (ctrl->tRP << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60400); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1); + + write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001); + + ctrl->timings[channel][slotrank].val_4028 = 4; + ctrl->timings[channel][slotrank].val_4024 = 55; + program_timings(ctrl, channel); + + discover_timA_coarse(ctrl, channel, slotrank, upperA); + + all_high = 1; + some_high = 0; + FOR_ALL_LANES if (ctrl->timings[channel][slotrank].lanes[lane]. + timA >= 0x40) + some_high = 1; + else + all_high = 0; + if (all_high) { + ctrl->timings[channel][slotrank].val_4028--; + printk(BIOS_SPEW, "4028--;\n"); + FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane]. + timA -= 0x40; + upperA[lane] -= 0x40; + + } + } else if (some_high) { + ctrl->timings[channel][slotrank].val_4024++; + ctrl->timings[channel][slotrank].val_4028++; + printk(BIOS_SPEW, "4024++;\n"); + printk(BIOS_SPEW, "4028++;\n"); + } + + program_timings(ctrl, channel); + + pre_timA_change(ctrl, channel, slotrank, &mnmx); + + discover_402x(ctrl, channel, slotrank, upperA); + + post_timA_change(ctrl, channel, slotrank, &mnmx); + pre_timA_change(ctrl, channel, slotrank, &mnmx); + + discover_timA_fine(ctrl, channel, slotrank, upperA); + + post_timA_change(ctrl, channel, slotrank, &mnmx); + pre_timA_change(ctrl, channel, slotrank, &mnmx); + + FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane]. + timA -= mnmx.timA_min_high * 0x40; + ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high; + printk(BIOS_SPEW, "4028 -= %d;\n", mnmx.timA_min_high); + + post_timA_change(ctrl, channel, slotrank, &mnmx); + + printk(BIOS_SPEW, "4/8: %d, %d, %x, %x\n", channel, slotrank, + ctrl->timings[channel][slotrank].val_4024, + ctrl->timings[channel][slotrank].val_4028); + + FOR_ALL_LANES + printk(BIOS_SPEW, "%d, %d, %d, %x\n", channel, slotrank, + lane, + ctrl->timings[channel][slotrank].lanes[lane].timA); + + write32(DEFAULT_MCHBAR + 0x3400, 0); + + r32 = read32(DEFAULT_MCHBAR + 0x5030); + write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20); + udelay(1); + + write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20); + + udelay(1); + } + + FOR_ALL_POPULATED_CHANNELS program_timings(ctrl, channel); + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS + FOR_ALL_LANES write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + + 4 * lane, 0); +} + +static void test_timC(ramctr_timing * ctrl, int channel, int slotrank) +{ + int lane; + + FOR_ALL_LANES { + write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0); + read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane); + } + + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10) + | 4 | (ctrl->tRCD << 16)); + + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | (6 << 16)); + + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | 8); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16)); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 8); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001); + + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0xc01 | (ctrl->tRP << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60400); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10) + | 8 | (ctrl->CAS << 16)); + + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | 0x60000); + + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x40011f4 | (max(ctrl->tRTP, 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + 0xc01 | (ctrl->tRP << 16)); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x60400); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240); + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001); + wait_428c(channel); +} + +static void discover_timC(ramctr_timing * ctrl, int channel, int slotrank) +{ + int timC; + int statistics[NUM_LANES][MAX_TIMC + 1]; + int lane; + + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0xc01 | (ctrl->tRP << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60400); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240); + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1); + + for (timC = 0; timC <= MAX_TIMC; timC++) { + FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane]. + timC = timC; + program_timings(ctrl, channel); + + test_timC(ctrl, channel, slotrank); + + FOR_ALL_LANES { + statistics[lane][timC] = + read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane + + 0x400 * channel); + printk(BIOS_SPEW, "Cstat: %d, %d, %d, %x, %x\n", + channel, slotrank, lane, timC, + statistics[lane][timC]); + } + } + FOR_ALL_LANES { + struct run rn = + get_longest_zero_run(statistics[lane], MAX_TIMC + 1); + ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle; + if (rn.all) + die("timC discovery failed"); + printk(BIOS_SPEW, "Cval: %d, %d, %d, %x\n", channel, slotrank, + lane, ctrl->timings[channel][slotrank].lanes[lane].timC); + } +} + +static int get_precedening_channels(ramctr_timing * ctrl, int target_channel) +{ + int channel, ret = 0; + FOR_ALL_POPULATED_CHANNELS if (channel < target_channel) + ret++; + return ret; +} + +static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b) +{ + unsigned j; + unsigned channel_offset = + get_precedening_channels(ctrl, channel) * 0x40; + printk(BIOS_SPEW, "channel_offset=%x\n", channel_offset); + for (j = 0; j < 16; j++) + write32(0x04000000 + channel_offset + 4 * j, j & 2 ? b : a); + sfence(); +} + +static int num_of_channels(const ramctr_timing * ctrl) +{ + int ret = 0; + int channel; + FOR_ALL_POPULATED_CHANNELS ret++; + return ret; +} + +static void fill_pattern1(ramctr_timing * ctrl, int channel) +{ + unsigned j; + unsigned channel_offset = + get_precedening_channels(ctrl, channel) * 0x40; + unsigned channel_step = 0x40 * num_of_channels(ctrl); + for (j = 0; j < 16; j++) + write32(0x04000000 + channel_offset + j * 4, 0xffffffff); + for (j = 0; j < 16; j++) + write32(0x04000000 + channel_offset + channel_step + j * 4, 0); + sfence(); +} + +static void precharge(ramctr_timing * ctrl) +{ + int channel, slotrank, lane; + + FOR_ALL_POPULATED_CHANNELS { + FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane].falling = + 16; + ctrl->timings[channel][slotrank].lanes[lane].rising = + 16; + } program_timings(ctrl, channel); + + FOR_ALL_POPULATED_RANKS { + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, + 0x1f000); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0xc01 | (ctrl->delay1 << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x360004); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, + 0x1f105); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + 0x4041003); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | 0); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, + 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x1001 | ((ctrl->CAS + 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, + 0x1f000); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + 0xc01 | (ctrl->delay1 << 16)); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x360000); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0); + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, + 0xc0001); + + wait_428c(channel); + } + + FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane].falling = + 48; + ctrl->timings[channel][slotrank].lanes[lane].rising = + 48; + } program_timings(ctrl, channel); + + FOR_ALL_POPULATED_RANKS { + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, + 0x1f000); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0xc01 | (ctrl->delay1 << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x360004); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, + 0x1f105); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + 0x4041003); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | 0); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, + 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x1001 | ((ctrl->CAS + 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, + 0x1f000); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + 0xc01 | (ctrl->delay1 << 16)); + + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x360000); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, + 0xc0001); + wait_428c(channel); + } + } +} + +static void test_timB(ramctr_timing * ctrl, int channel, int slotrank) +{ + write_mrreg(ctrl, channel, slotrank, 1, + 0x80 | make_mr1(ctrl, slotrank)); + + wait_428c(channel); + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0x8000c01 | ((ctrl->CWL + ctrl->delay2) << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + 8 | (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + 0x4000c01 | ((ctrl->CAS + 38) << 16)); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | 4); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001); + wait_428c(channel); + + write_mrreg(ctrl, channel, slotrank, 1, + 0x1080 | make_mr1(ctrl, slotrank)); +} + +static void discover_timB(ramctr_timing * ctrl, int channel, int slotrank) +{ + int timB; + int statistics[NUM_LANES][128]; + int lane; + + write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2)); + + for (timB = 0; timB < 128; timB++) { + FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane]. + timB = timB; + program_timings(ctrl, channel); + + test_timB(ctrl, channel, slotrank); + + FOR_ALL_LANES { + statistics[lane][timB] = + !((read32 + (DEFAULT_MCHBAR + lane_registers[lane] + + channel * 0x100 + 4 + ((timB / 32) & 1) * 4) + >> (timB % 32)) & 1); + printk(BIOS_SPEW, "Bstat: %d, %d, %d, %x, %x\n", + channel, slotrank, lane, timB, + statistics[lane][timB]); + } + } + FOR_ALL_LANES { + struct run rn = get_longest_zero_run(statistics[lane], 128); + ctrl->timings[channel][slotrank].lanes[lane].timB = rn.end; + if (rn.all) + die("timB discovery failed"); + printk(BIOS_SPEW, "Bval: %d, %d, %d, %x\n", channel, slotrank, + lane, ctrl->timings[channel][slotrank].lanes[lane].timB); + } +} + +static int get_timB_high_adjust(u64 val) +{ + int i; + if (val >= 0xfffffffffff00000LL) + return -1; + if (val >= 0xfffffff000000000LL) + return -2; + if (val >= 0xfff0000000000000LL) + return -3; + + for (i = 0; i < 8; i++) + if (val >> (8 * (7 - i) + 4)) + return i; + return 8; +} + +static void adjust_high_timB(ramctr_timing * ctrl) +{ + int channel, slotrank, lane; + write32(DEFAULT_MCHBAR + 0x3400, 0x200); + FOR_ALL_POPULATED_CHANNELS { + fill_pattern1(ctrl, channel); + write32(DEFAULT_MCHBAR | 0x4288 | (channel << 10), 1); + } + FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS { + + write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001); + + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0xc01 | (ctrl->tRCD << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | 0x8); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16)); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x8); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001); + + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0xc01 | ((ctrl->tRP) << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60400); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + 0xc01 | ((ctrl->tRCD) << 16)); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x4000c01 | + ((ctrl->tRP + + ctrl->timings[channel][slotrank].val_4024 + + ctrl->timings[channel][slotrank].val_4028) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24) | 0x60008); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001); + wait_428c(channel); + FOR_ALL_LANES { + u64 res = + read32(DEFAULT_MCHBAR + lane_registers[lane] + + 0x100 * channel + 4); + res |= + ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] + + 0x100 * channel + 8)) << 32; + ctrl->timings[channel][slotrank].lanes[lane].timB += + get_timB_high_adjust(res) * 64; + printk(BIOS_SPEW, "Bval+: %d, %d, %d, %x\n", channel, + slotrank, lane, + ctrl->timings[channel][slotrank].lanes[lane]. + timB); + } + } + write32(DEFAULT_MCHBAR + 0x3400, 0); +} + +static void write_op(ramctr_timing * ctrl, int channel) +{ + int slotrank; + + wait_428c(channel); + + /* choose an existing rank. */ + slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0; + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001); + + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60000); + + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1); + wait_428c(channel); +} + +static void write_training(ramctr_timing * ctrl) +{ + int channel, slotrank, lane; + u32 r32; + + FOR_ALL_POPULATED_CHANNELS + write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel, + read32(DEFAULT_MCHBAR + 0x4008 + + 0x400 * channel) | 0x8000000); + + FOR_ALL_POPULATED_CHANNELS { + write_op(ctrl, channel); + write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel, + read32(DEFAULT_MCHBAR + 0x4020 + + 0x400 * channel) | 0x200000); + } + write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8); + FOR_ALL_POPULATED_CHANNELS { + write_op(ctrl, channel); + } + + FOR_ALL_CHANNELS + FOR_ALL_POPULATED_RANKS + write_mrreg(ctrl, channel, slotrank, 1, + make_mr1(ctrl, slotrank) | 0x1080); + + write32(DEFAULT_MCHBAR + 0x3400, 0x108052); + + r32 = read32(DEFAULT_MCHBAR + 0x5030); + write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20); + udelay(1); + + write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20); + + udelay(1); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS + discover_timB(ctrl, channel, slotrank); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS + write_mrreg(ctrl, channel, + slotrank, 1, make_mr1(ctrl, slotrank)); + + write32(DEFAULT_MCHBAR + 0x3400, 0); + + FOR_ALL_POPULATED_CHANNELS + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8); + + FOR_ALL_POPULATED_CHANNELS { + write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel, + ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 + + 0x400 * channel)); + read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel); + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1); + wait_428c(channel); + } + + r32 = read32(DEFAULT_MCHBAR + 0x5030); + write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20); + udelay(1); + + write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20); + + udelay(1); + + printk(BIOS_SPEW, "CPE\n"); + precharge(ctrl); + printk(BIOS_SPEW, "CPF\n"); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane); + write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane, + 0); + } + + FOR_ALL_POPULATED_CHANNELS { + fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555); + write32(DEFAULT_MCHBAR | 0x4288 | (channel << 10), 0); + } + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS + discover_timC(ctrl, channel, slotrank); + + FOR_ALL_POPULATED_CHANNELS + program_timings(ctrl, channel); + + adjust_high_timB(ctrl); + + FOR_ALL_POPULATED_CHANNELS + program_timings(ctrl, channel); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane); + write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane, + 0); + } +} + +static int test_320c(ramctr_timing * ctrl, int channel, int slotrank) +{ + struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank]; + int timC_delta; + int lanes_ok = 0; + int ctr = 0; + int lane; + + for (timC_delta = -5; timC_delta <= 5; timC_delta++) { + FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane].timC = + saved_rt.lanes[lane].timC + timC_delta; + } + program_timings(ctrl, channel); + FOR_ALL_LANES write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0); + + write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f); + + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10) + | 8 | (ctrl->tRCD << 16)); + + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | ctr | 0x60000); + + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x4001020 | (max(ctrl->tRTP, 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x60400); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001); + wait_428c(channel); + FOR_ALL_LANES { + u32 r32 = + read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane + + 0x400 * channel); + + if (r32 == 0) + lanes_ok |= 1 << lane; + } + ctr++; + if (lanes_ok == ((1 << NUM_LANES) - 1)) + break; + } + + ctrl->timings[channel][slotrank] = saved_rt; + return lanes_ok != ((1 << NUM_LANES) - 1); +} + +const u32 pattern[][16] = { + {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff}, + {0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000}, + {0xe62d6424, 0x9277e09e, 0x8f43dc3f, 0x76eae589, + 0x0010fdc6, 0xdc55e01c, 0x5effb0ab, 0x6cba5d29, + 0xa43d1e64, 0xab5c2e0f, 0x7796ed16, 0x96023bf4, + 0xa74c831d, 0x90f138c0, 0x17830a8a, 0x5ac17c47}, + {0x359ebbeb, 0x2b9b4512, 0xef584d98, 0x106bf7cb, + 0x363525ad, 0xb3a4dfdc, 0xa6b9fcd8, 0xd21689ec, + 0x84a3695b, 0xbd9c2e27, 0xdb3d0f44, 0x988158f1, + 0xcca91d3f, 0xb62a6d12, 0xe905e4cf, 0x7f1fa626}, + {0xe58efeae, 0xcd006081, 0xa9119403, 0xbcfbd35f, + 0x213b3bf7, 0x7bfcb773, 0xc85143f9, 0x0bdbff50, + 0xa3053c90, 0x51d66cb7, 0x296f4387, 0xb715f99e, + 0xfaddc989, 0xbb1de8a7, 0x39206b4d, 0x80174a57}, + {0xa1622ac1, 0xb4f4a5f0, 0x16dc2bc3, 0x50fb0954, + 0x2e261721, 0x52b82c3c, 0x821902b8, 0x0d4b6c38, + 0x1f618631, 0x047956f3, 0xd4337f5a, 0x591f8002, + 0x27f28db2, 0xfae37369, 0xb3f27580, 0x3cdb6397}, + {0x3dee23be, 0x19f36408, 0x227f4a6a, 0x024603c5, + 0xd5e062db, 0x6d8d4c5c, 0x7ff693b0, 0x76641be9, + 0x9e74f41c, 0xe7bc7f33, 0x2636f2e9, 0x70279750, + 0xce2355aa, 0x32d230ef, 0x22f9b468, 0xadd4e7a2}, + {0x936c0fed, 0xba0612d5, 0xa97c1ea7, 0x10e29d67, + 0x1c4c5dc8, 0x83645621, 0xcd8b521c, 0xb8301817, + 0xac7d6571, 0xcc41d200, 0x4ebdefdd, 0xd2917bde, + 0x60f75acc, 0x7791534b, 0x26ea2a83, 0x6b74513a}, + {0xd1957b85, 0xc6f8f9ca, 0xf04fb4be, 0xfeb786fb, + 0xa1dea3aa, 0x67fe7db6, 0x25d49c87, 0xe3d54870, + 0x93dc1f86, 0x7d0c1a18, 0x9272e128, 0x68e1b876, + 0xce284c9e, 0x8fa18792, 0x5785a340, 0xb6fcf198}, + {0xff7d8e4a, 0x0c21ee43, 0xe820b388, 0xb4443c0e, + 0xa1e6e498, 0x5c426110, 0x1b434ef3, 0xbef05b91, + 0xa6907968, 0x53662ac3, 0x6defac32, 0x2c11c29c, + 0x6175cced, 0xb17dd3ad, 0x6e6a1076, 0x1372b1fa}, + {0x4408ed06, 0x49460ffd, 0xb49d26cb, 0x6a3662a5, + 0x5e857047, 0xa387cd4a, 0x04edc81e, 0xfd94d8d4, + 0x2fe48d91, 0x9d2356bc, 0x96131878, 0xaca3fce4, + 0xbb312c6c, 0x5023b090, 0x3614be70, 0xa14dfabb}, + {0xd4cc1e83, 0x757a1930, 0xc3d16a61, 0x9e0d6681, + 0x8a081fa9, 0xbd11c888, 0x1672f010, 0xa083f71c, + 0x1ec02eef, 0xc4586ca8, 0x6d322b35, 0x56054679, + 0x1552a0ff, 0x5cb7707e, 0xdfb55d4a, 0xcc76cc07}, + {0x507cf71f, 0x2166421a, 0x54be4af0, 0xfd42158c, + 0x417b1f7f, 0x9466860b, 0x3a0075bf, 0x2055575c, + 0xcedfe7ab, 0xbe85aa5f, 0x39d0c2e3, 0x851c19df, + 0x39a35a3f, 0x3fb10d7d, 0x20b14899, 0x703b7f08}, + {0x8a7d9dd1, 0x33235565, 0xbd3d2e57, 0xa48c2726, + 0x0d5e2e13, 0xae421ff9, 0x8784a224, 0xf66c1510, + 0x057627aa, 0x8fb0cb41, 0x4289975a, 0xb181adfa, + 0x59f2059a, 0xe86feb05, 0x84222fc1, 0x319b3ce9}, + {0xe1e243b8, 0x3b0bcc1a, 0x70396f00, 0x5caff44d, + 0xe96961b3, 0xad73f692, 0x8b841a2d, 0xf5838839, + 0xec9c9d04, 0xcc2b5562, 0xf8ca2549, 0xa9c52ff8, + 0x3b2fde68, 0x3d4dc7f0, 0xa57387d0, 0x051199ad}, + {0x5f0ce4fc, 0xd830fbb7, 0x90abeb8f, 0x96d9cdbb, + 0x58f80a80, 0x0baaca36, 0x81a23623, 0x77127614, + 0xaa8382cd, 0x0922fbca, 0xd84d37e1, 0x721297df, + 0x160f3b3a, 0x10a1ecdc, 0x151c92f4, 0xc1fdcdab}, + {0x261c45cc, 0xfeddd2da, 0xfc3cb1c1, 0x6639641f, + 0x2c011892, 0x7108bee2, 0x8545e0b9, 0x7dd36dab, + 0x07d91950, 0x1520adcb, 0xf84aa939, 0x07d9bb2d, + 0xdf1ed826, 0xaee3c814, 0x1dca1e81, 0xc8e9f486}, + {0x933d306a, 0xaab7103d, 0xa8be37be, 0x49612f3a, + 0xb0cf28e5, 0xf9648902, 0x106d7c11, 0xf32e1813, + 0x21af36ef, 0xe695e4c4, 0x7ee1831d, 0x2aeda467, + 0x99d0c655, 0x3f0691ab, 0xcd68f7c1, 0xb469a20e}, + {0x8557aef0, 0x3eb0e373, 0x0853ac31, 0xe5bded62, + 0x3eddb0dd, 0x6bbf1caf, 0x2119c3d9, 0xe1732350, + 0x55456c75, 0xf6119375, 0x498dd1ad, 0x13f80916, + 0xb97f9f5e, 0x921d9f4c, 0xabdee367, 0x1d6bb8bf}, + {0xd165a3be, 0xd8b41598, 0xa20e1809, 0xefd5c8ce, + 0x18935c80, 0xdf1911f9, 0xc9e449eb, 0xb887a4d7, + 0x4a324f6f, 0x533e8031, 0x1c21c074, 0xa95f1ea5, + 0x765b320a, 0x839d7dfb, 0xc7d3aa93, 0xe534ae3d}, + {0xbe8592c8, 0x068457e6, 0x89b94fa3, 0xd522ad02, + 0x7e7db0b7, 0x2c5b896f, 0x9f8ecb37, 0x05b983ff, + 0x3fe9b25f, 0x34a6215b, 0x0592ba34, 0xd564f85a, + 0x156c426d, 0x25ad5460, 0xe7b5e8b7, 0xa73285c6}, + {0x5ad8d838, 0x27b42d36, 0xcc806ad1, 0x157a058a, + 0x7297735a, 0xffd6df8d, 0xff96f7a2, 0x155b27ea, + 0x84708101, 0x979fd78b, 0x49797d0c, 0x0dc93e3c, + 0x20287332, 0xed759f88, 0xe5068529, 0xb83aa781}, + {0xc38b302c, 0x57b54075, 0xac810692, 0xb0d493e7, + 0x4adda486, 0x0665ce2e, 0xb2a9c003, 0xafacc4ce, + 0x4d5e906d, 0xb3d52fab, 0xe6962c6b, 0x850f4dd1, + 0x5021656c, 0x5df6c06b, 0x9255125b, 0x2363c478}, + {0x188b715c, 0xe8b884b0, 0x5e6d0b9a, 0x1f0051e1, + 0xd2d35d4c, 0xbfeaecbe, 0xc84bb0ad, 0x67a232d6, + 0x99001587, 0xbf4313e1, 0x74f64061, 0x2c1fc562, + 0xb6fe8ca6, 0x5226a239, 0xf5198574, 0x61b51dca}, + {0x51dcecd3, 0xbadbe596, 0xebe3e84a, 0x772bfdfc, + 0x03656ac5, 0xa7c36e91, 0x6cd32cf0, 0xc3f699dd, + 0x7d5aba01, 0x51e38e82, 0x23103a98, 0x20298b9d, + 0x19436510, 0x63ad7e6c, 0x8bc2b33f, 0x27079917}, + {0x8bd5be78, 0xf2403bfa, 0x780ebdb6, 0x94c53b64, + 0x6241c2e2, 0x5bfb081e, 0x6799e88f, 0xc997b7d1, + 0x466ac8b1, 0xbf5909da, 0x497ea39f, 0x402ffb48, + 0xd7470c2d, 0x8510aba9, 0x6c52a1c9, 0x812ca967}, + {0x031f7ab4, 0xd32fe890, 0x36ae6de5, 0x083dcde4, + 0x99a7f12f, 0xe44864a7, 0x02b75fff, 0xf25dda35, + 0x7679ff4f, 0xed421e01, 0xd9c2cfa1, 0xd36b4e82, + 0x5315d908, 0xc7ebcb2a, 0xb6f3e4c1, 0xf5bfbae9}, + {0x3f4a2a96, 0x64d8bd5a, 0x19acd70d, 0xf62fcdd9, + 0x5de99cdf, 0x32f3b7cb, 0x2c020578, 0x4e9bafb8, + 0x74919a08, 0xaba33e91, 0xa6bd2254, 0x2435a9b9, + 0x47e2a1b4, 0xe837a28e, 0xe113f1b0, 0x7654bd79}, + {0x05537a6c, 0x77be1a5c, 0x4c7492c9, 0x9086bfb0, + 0x257adc18, 0xf4787fc1, 0xe3fb6d53, 0x9525e589, + 0x445a65bc, 0x833f7d08, 0x69cf1f7e, 0x9a6372e1, + 0xceedb52e, 0x31032997, 0xd1c36828, 0x132772d6}, + {0x0a166972, 0x89beaf3b, 0x8d780fbc, 0x8aea5392, + 0x58347a41, 0x1e381ec2, 0xcc6280c8, 0xee0863e1, + 0x976e2dd2, 0x8c6ee6e2, 0xa0ca57cd, 0x95114a7d, + 0x3c096704, 0xa941769d, 0x2de20c05, 0x0bf8f812}, + {0x22779d6c, 0x94e12e8f, 0x5ce40299, 0xea1b55b0, + 0x9ebec05d, 0xe076cd2b, 0x8fef5648, 0x6a284c65, + 0xa790b705, 0xf0b19997, 0x0d8ca8af, 0x17440419, + 0xef4f702f, 0x33cbcbb1, 0x83d60f26, 0x48988397}, + {0x0fed7f53, 0xb5acbb67, 0xc031c73f, 0x5364d9ef, + 0xa6dbd12d, 0x82174a6c, 0xccf8e7ab, 0xc473c036, + 0xcff493d8, 0xad9afc3b, 0x316a24e8, 0x1842bea4, + 0x4cc0c82e, 0x28ccd91e, 0xd7311b5d, 0x50a89860}, +}; + +static void fill_pattern5(ramctr_timing * ctrl, int channel) +{ + unsigned i, j; + unsigned channel_offset = + get_precedening_channels(ctrl, channel) * 0x40; + unsigned channel_step = 0x40 * num_of_channels(ctrl); + for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) { + for (j = 0; j < 16; j++) + write32(0x04000000 + channel_offset + i * channel_step + + j * 4, pattern[i][j]); + } + sfence(); +} + +static void reprogram_320c(ramctr_timing * ctrl) +{ + int channel, slotrank; + u32 r32; + + FOR_ALL_POPULATED_CHANNELS { + wait_428c(channel); + + /* choose an existing rank. */ + slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0; + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001); + + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60000); + + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1); + wait_428c(channel); + write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel, + read32(DEFAULT_MCHBAR + 0x4020 + + 0x400 * channel) | 0x200000); + } + write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8); + FOR_ALL_POPULATED_CHANNELS { + wait_428c(channel); + + /* choose an existing rank. */ + slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0; + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001); + + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60000); + + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1); + wait_428c(channel); + } + + /* jedec reset */ + dram_jedecreset(ctrl); + /* mrs commands. */ + dram_mrscommands(ctrl); + + r32 = read32(DEFAULT_MCHBAR + 0x5030); + write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20); + udelay(1); + + write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20); + + udelay(1); +} + +static void command_training(ramctr_timing * ctrl) +{ + int channel; + int slotrank; + u32 reg_4004_b30; + int delta = 0; + int c320c; + int stat[NUM_SLOTRANKS][256]; + + /* FIXME: vendor BIOS discovers this by trying 0 and 2. Apparently 2 should work for + all systems but 0 is slightly more efficient for the systems that can tolerate it. + */ + reg_4004_b30 = 2; + + FOR_ALL_POPULATED_CHANNELS + MCHBAR32(0x4004 + 0x400 * channel) = + ctrl->tRRD + | (ctrl->tRTP << 4) + | (ctrl->tCKE << 8) + | (ctrl->tWTR << 12) + | (ctrl->tFAW << 16) + | (ctrl->tWR << 24) + | (reg_4004_b30 << 30); + + if (reg_4004_b30 == 2) + delta = 2; + else if (reg_4004_b30 == 0) + delta = 4; + + FOR_ALL_CHANNELS { + FOR_ALL_POPULATED_RANKS ctrl->timings[channel][slotrank]. + val_4024 -= delta; + } + + FOR_ALL_POPULATED_CHANNELS { + fill_pattern5(ctrl, channel); + write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f); + } + + FOR_ALL_POPULATED_CHANNELS { + for (c320c = -127; c320c <= 127; c320c++) { + FOR_ALL_POPULATED_RANKS ctrl-> + timings[channel][slotrank].val_320c = c320c; + program_timings(ctrl, channel); + reprogram_320c(ctrl); + FOR_ALL_POPULATED_RANKS { + stat[slotrank][c320c + 127] = + test_320c(ctrl, channel, slotrank); + printk(BIOS_SPEW, "3stat: %d, %d, %d: %d\n", + channel, slotrank, c320c, + stat[slotrank][c320c + 127]); + } + } + FOR_ALL_POPULATED_RANKS { + struct run rn = + get_longest_zero_run(stat[slotrank], 255); + ctrl->timings[channel][slotrank].val_320c = + rn.middle - 127; + printk(BIOS_SPEW, "3val: %d, %d: %d\n", channel, + slotrank, + ctrl->timings[channel][slotrank].val_320c); + if (rn.all) + die("c320c discovery failed"); + } + } + + FOR_ALL_POPULATED_CHANNELS program_timings(ctrl, channel); + + reprogram_320c(ctrl); +} + +static void discover_edges_real(ramctr_timing * ctrl, int channel, int slotrank, + int *edges) +{ + int edge; + int statistics[NUM_LANES][MAX_EDGE_TIMING + 1]; + int lane; + + for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) { + FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane].rising = + edge; + ctrl->timings[channel][slotrank].lanes[lane].falling = + edge; + } + printk(BIOS_SPEW, "edge %02x\n", edge); + program_timings(ctrl, channel); + + FOR_ALL_LANES { + write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + + 4 * lane, 0); + read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane + + 0x4140); + } + + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + (0xc01 | (ctrl->delay1 << 16))); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x360004); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x1001 | ((ctrl->CAS + 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + (0xc01 | (ctrl->delay1 << 16))); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x360000); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001); + + wait_428c(channel); + + FOR_ALL_LANES { + statistics[lane][edge] = + read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + + lane * 4); + printk(BIOS_SPEW, "estat %d, %d, %d, %d %02x\n", + channel, slotrank, lane, edge, + statistics[lane][edge]); + } + } + FOR_ALL_LANES { + struct run rn = + get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1); + edges[lane] = rn.middle; + if (rn.all) + die("edge discovery failed"); + printk(BIOS_SPEW, "eval %d, %d, %d, %02x\n", channel, slotrank, + lane, edges[lane]); + } +} + +static void discover_edges(ramctr_timing * ctrl) +{ + int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; + int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; + int channel, slotrank, lane; + u32 r32; + + write32(DEFAULT_MCHBAR + 0x3400, 0); + + r32 = read32(DEFAULT_MCHBAR + 0x5030); + write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20); + udelay(1); + + write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20); + + udelay(1); + + FOR_ALL_POPULATED_CHANNELS { + FOR_ALL_LANES write32(DEFAULT_MCHBAR + 4 * lane + + 0x400 * channel + 0x4080, 0); + } + + FOR_ALL_POPULATED_CHANNELS { + fill_pattern0(ctrl, channel, 0, 0); + write32(DEFAULT_MCHBAR | 0x4288 | (channel << 10), 0); + FOR_ALL_LANES read32(DEFAULT_MCHBAR + 0x400 * channel + + lane * 4 + 0x4140); + + FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane].falling = + 16; + ctrl->timings[channel][slotrank].lanes[lane].rising = + 16; + } program_timings(ctrl, channel); + + FOR_ALL_POPULATED_RANKS { + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, + 0x1f000); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0xc01 | (ctrl->delay1 << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x360004); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, + 0x1f105); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + 0x4041003); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | 0); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, + 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x1001 | ((ctrl->CAS + 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, + 0x1f000); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + 0xc01 | (ctrl->delay1 << 16)); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x360000); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0); + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, + 0xc0001); + + wait_428c(channel); + } + + FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane].falling = + 48; + ctrl->timings[channel][slotrank].lanes[lane].rising = + 48; + } + + program_timings(ctrl, channel); + + FOR_ALL_POPULATED_RANKS { + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, + 0x1f000); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0xc01 | (ctrl->delay1 << 16)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x360004); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, + 0x1f105); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + 0x4041003); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24) | 0); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, + 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x1001 | ((ctrl->CAS + 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, + 0x1f000); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + 0xc01 | (ctrl->delay1 << 16)); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x360000); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, + 0xc0001); + wait_428c(channel); + } + + FOR_ALL_LANES { + write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + + lane * 4, + ~read32(DEFAULT_MCHBAR + 0x4040 + + 0x400 * channel + lane * 4) & 0xff); + } + + fill_pattern0(ctrl, channel, 0, 0xffffffff); + write32(DEFAULT_MCHBAR | 0x4288 | (channel << 10), 0); + } + + /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */ + write32(DEFAULT_MCHBAR + 0x4eb0, 0x300); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { + discover_edges_real(ctrl, channel, slotrank, + falling_edges[channel][slotrank]); + } write32(DEFAULT_MCHBAR + 0x4eb0, 0x200); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { + discover_edges_real(ctrl, channel, slotrank, + rising_edges[channel][slotrank]); + } write32(DEFAULT_MCHBAR + 0x4eb0, 0); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane].falling = + falling_edges[channel][slotrank][lane]; + ctrl->timings[channel][slotrank].lanes[lane].rising = + rising_edges[channel][slotrank][lane]; + } FOR_ALL_POPULATED_CHANNELS program_timings(ctrl, channel); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane, + 0); + } +} + +static void discover_edges_write_real(ramctr_timing * ctrl, int channel, + int slotrank, int *edges) +{ + int edge; + u32 raw_statistics[MAX_EDGE_TIMING + 1]; + int statistics[MAX_EDGE_TIMING + 1]; + const int reg3000b24[] = { 0, 0xc, 0x2c }; + int lane, i; + int lower[NUM_LANES]; + int upper[NUM_LANES]; + + FOR_ALL_LANES { + lower[lane] = 0; + upper[lane] = MAX_EDGE_TIMING; + } + + for (i = 0; i < 3; i++) { + /* FIXME: trace shows that vendor BIOS also tests with other patterns. + I'm not sure whether it's really needed. + */ + write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel, + reg3000b24[i] << 24); + printk(BIOS_SPEW, "patterned\n"); + printk(BIOS_SPEW, "[%x] = 0x%08x\n(%d, %d)\n", + 0x3000 + 0x100 * channel, reg3000b24[i] << 24, channel, + slotrank); + for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) { + FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane]. + rising = edge; + ctrl->timings[channel][slotrank].lanes[lane]. + falling = edge; + } + program_timings(ctrl, channel); + + FOR_ALL_LANES { + write32(DEFAULT_MCHBAR + 0x4340 + + 0x400 * channel + 4 * lane, 0); + read32(DEFAULT_MCHBAR + 0x400 * channel + + 4 * lane + 0x4140); + } + wait_428c(channel); + + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, + 0x1f006); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + 0x4 | (ctrl->tRCD << 16) + | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << + 10)); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, + 0x240); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, + 0x1f201); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) << + 16)); + write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, + (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, + 0x242); + + write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, + 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, + 0x4005020 | (max(ctrl->tRTP, 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, + (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, + 0x242); + + write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, + 0x1f002); + write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, + 0xc01 | (ctrl->tRP << 16)); + write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel, + (slotrank << 24) | 0x60400); + write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, + 0xc0001); + wait_428c(channel); + FOR_ALL_LANES { + read32(DEFAULT_MCHBAR + 0x4340 + + 0x400 * channel + lane * 4); + } + + raw_statistics[edge] = + MCHBAR32(0x436c + 0x400 * channel); + } + FOR_ALL_LANES { + struct run rn; + for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) + statistics[edge] = + ! !(raw_statistics[edge] & (1 << lane)); + rn = get_longest_zero_run(statistics, + MAX_EDGE_TIMING + 1); + printk(BIOS_SPEW, + "edges: %d, %d, %d: 0x%x-0x%x-0x%x, 0x%x-0x%x\n", + channel, slotrank, i, rn.start, rn.middle, + rn.end, rn.start + ctrl->edge_offset[i], + rn.end - ctrl->edge_offset[i]); + lower[lane] = + max(rn.start + ctrl->edge_offset[i], lower[lane]); + upper[lane] = + min(rn.end - ctrl->edge_offset[i], upper[lane]); + edges[lane] = (lower[lane] + upper[lane]) / 2; + + } + } + + write32(DEFAULT_MCHBAR + 0x3000, 0); + printk(BIOS_SPEW, "CPA\n"); +} + +static void discover_edges_write(ramctr_timing * ctrl) +{ + int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; + int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; + int channel, slotrank, lane; + + FOR_ALL_POPULATED_CHANNELS { + fill_pattern5(ctrl, channel); + write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f); + } + + /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */ + write32(DEFAULT_MCHBAR + 0x4eb0, 0x300); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { + discover_edges_write_real(ctrl, channel, slotrank, + falling_edges[channel][slotrank]); + } + + write32(DEFAULT_MCHBAR + 0x4eb0, 0x200); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { + discover_edges_write_real(ctrl, channel, slotrank, + rising_edges[channel][slotrank]); + } + + write32(DEFAULT_MCHBAR + 0x4eb0, 0); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + ctrl->timings[channel][slotrank].lanes[lane].falling = + falling_edges[channel][slotrank][lane]; + ctrl->timings[channel][slotrank].lanes[lane].rising = + rising_edges[channel][slotrank][lane]; + } + + FOR_ALL_POPULATED_CHANNELS + program_timings(ctrl, channel); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane, + 0); + } +} + +static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank) +{ + wait_428c(channel); + write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006); + write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, + (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) + << 10) | (ctrl->tRCD << 16) | 4); + write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, + (slotrank << 24) | 0x60000); + write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244); + + write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201); + write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, + 0x80011e0 | + ((ctrl->tWTR + ctrl->CWL + 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4204 + + 0x400 * channel, (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4214 + + 0x400 * channel, 0x242); + + write32(DEFAULT_MCHBAR + 0x4228 + + 0x400 * channel, 0x1f105); + write32(DEFAULT_MCHBAR + 0x4238 + + 0x400 * channel, + 0x40011e0 | (max(ctrl->tRTP, 8) << 16)); + write32(DEFAULT_MCHBAR + 0x4208 + + 0x400 * channel, (slotrank << 24)); + write32(DEFAULT_MCHBAR + 0x4218 + + 0x400 * channel, 0x242); + + write32(DEFAULT_MCHBAR + 0x422c + + 0x400 * channel, 0x1f002); + write32(DEFAULT_MCHBAR + 0x423c + + 0x400 * channel, + 0x1001 | (ctrl->tRP << 16)); + write32(DEFAULT_MCHBAR + 0x420c + + 0x400 * channel, + (slotrank << 24) | 0x60400); + write32(DEFAULT_MCHBAR + 0x421c + + 0x400 * channel, 0); + + write32(DEFAULT_MCHBAR + 0x4284 + + 0x400 * channel, 0xc0001); + wait_428c(channel); +} + +static void discover_timC_write(ramctr_timing * ctrl) +{ + const u8 rege3c_b24[3] = { 0, 0xf, 0x2f }; + int i; + + int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; + int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; + int channel, slotrank, lane; + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + lower[channel][slotrank][lane] = 0; + upper[channel][slotrank][lane] = MAX_TIMC; + } + + write32(DEFAULT_MCHBAR + 0x4ea8, 1); + + for (i = 0; i < 3; i++) + FOR_ALL_POPULATED_CHANNELS { + write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100), + (rege3c_b24[i] << 24) + | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100)) + & ~0x3f000000)); + udelay(2); + FOR_ALL_POPULATED_RANKS { + int timC; + u32 raw_statistics[MAX_TIMC + 1]; + int statistics[MAX_TIMC + 1]; + + /* FIXME: trace shows that vendor BIOS also tests with other patterns. + I'm not sure whether it's really needed. + */ + fill_pattern5(ctrl, channel); + for (timC = 0; timC < MAX_TIMC + 1; timC++) { + FOR_ALL_LANES + ctrl->timings[channel][slotrank].lanes[lane].timC = timC; + program_timings(ctrl, channel); + + test_timC_write (ctrl, channel, slotrank); + + raw_statistics[timC] = + MCHBAR32(0x436c + 0x400 * channel); + printk(BIOS_SPEW, "Cstat %02x %02x\n", timC, + raw_statistics[timC]); + } + FOR_ALL_LANES { + struct run rn; + for (timC = 0; timC <= MAX_TIMC; timC++) + statistics[timC] = + !!(raw_statistics[timC] & + (1 << lane)); + rn = get_longest_zero_run(statistics, + MAX_TIMC + 1); + if (rn.all) + die("timC write discovery failed"); + printk(BIOS_SPEW, + "timC: %d, %d, %d: 0x%x-0x%x-0x%x, 0x%x-0x%x\n", + channel, slotrank, i, rn.start, + rn.middle, rn.end, + rn.start + ctrl->timC_offset[i], + rn.end - ctrl->timC_offset[i]); + lower[channel][slotrank][lane] = + max(rn.start + ctrl->timC_offset[i], + lower[channel][slotrank][lane]); + upper[channel][slotrank][lane] = + min(rn.end - ctrl->timC_offset[i], + upper[channel][slotrank][lane]); + + } + } + } + + write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c, + 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) & + ~0x3f000000)); + udelay(2); + + write32(DEFAULT_MCHBAR + 0x4ea8, 0); + + printk(BIOS_SPEW, "CPB\n"); + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES { + printk(BIOS_SPEW, "timC [%d, %d, %d] = 0x%x\n", channel, + slotrank, lane, + (lower[channel][slotrank][lane] + + upper[channel][slotrank][lane]) / 2); + ctrl->timings[channel][slotrank].lanes[lane].timC = + (lower[channel][slotrank][lane] + + upper[channel][slotrank][lane]) / 2; + } + FOR_ALL_POPULATED_CHANNELS program_timings(ctrl, channel); +} + +static void normalize_training(ramctr_timing * ctrl) +{ + int channel, slotrank, lane; + int mat = 0; + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { + int delta; + FOR_ALL_LANES mat = + max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat); + delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028; + ctrl->timings[channel][slotrank].val_4024 += delta; + ctrl->timings[channel][slotrank].val_4028 += delta; + } FOR_ALL_POPULATED_CHANNELS program_timings(ctrl, channel); +} + +static void write_controller_mr(ramctr_timing * ctrl) +{ + int channel, slotrank; + + FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS { + write32(DEFAULT_MCHBAR | 0x0004 | (channel << 8) | + lane_registers[slotrank], make_mr0(ctrl, slotrank)); + write32(DEFAULT_MCHBAR | 0x0008 | (channel << 8) | + lane_registers[slotrank], make_mr1(ctrl, slotrank)); + } +} + +static void channel_test(ramctr_timing * ctrl) +{ + int channel, slotrank, lane; + + FOR_ALL_POPULATED_CHANNELS + if (read32(DEFAULT_MCHBAR | 0x42a0 | (channel << 10)) & 0xa000) + die("Mini channel test failed (1)\n"); + FOR_ALL_POPULATED_CHANNELS { + fill_pattern0(ctrl, channel, 0x12345678, 0x98765432); + + write32(DEFAULT_MCHBAR | 0x4288 | (channel << 10), 0); + } + + for (slotrank = 0; slotrank < 4; slotrank++) + FOR_ALL_CHANNELS + if (ctrl->rankmap[channel] & (1 << slotrank)) { + FOR_ALL_LANES { + write32(DEFAULT_MCHBAR | (0x4f40 + 4 * lane), 0); + write32(DEFAULT_MCHBAR | (0x4d40 + 4 * lane), 0); + } + wait_428c(channel); + write32(DEFAULT_MCHBAR | 0x4220 | (channel << 10), 0x0001f006); + write32(DEFAULT_MCHBAR | 0x4230 | (channel << 10), 0x0028a004); + write32(DEFAULT_MCHBAR | 0x4200 | (channel << 10), + 0x00060000 | (slotrank << 24)); + write32(DEFAULT_MCHBAR | 0x4210 | (channel << 10), 0x00000244); + write32(DEFAULT_MCHBAR | 0x4224 | (channel << 10), 0x0001f201); + write32(DEFAULT_MCHBAR | 0x4234 | (channel << 10), 0x08281064); + write32(DEFAULT_MCHBAR | 0x4204 | (channel << 10), + 0x00000000 | (slotrank << 24)); + write32(DEFAULT_MCHBAR | 0x4214 | (channel << 10), 0x00000242); + write32(DEFAULT_MCHBAR | 0x4228 | (channel << 10), 0x0001f105); + write32(DEFAULT_MCHBAR | 0x4238 | (channel << 10), 0x04281064); + write32(DEFAULT_MCHBAR | 0x4208 | (channel << 10), + 0x00000000 | (slotrank << 24)); + write32(DEFAULT_MCHBAR | 0x4218 | (channel << 10), 0x00000242); + write32(DEFAULT_MCHBAR | 0x422c | (channel << 10), 0x0001f002); + write32(DEFAULT_MCHBAR | 0x423c | (channel << 10), 0x00280c01); + write32(DEFAULT_MCHBAR | 0x420c | (channel << 10), + 0x00060400 | (slotrank << 24)); + write32(DEFAULT_MCHBAR | 0x421c | (channel << 10), 0x00000240); + write32(DEFAULT_MCHBAR | 0x4284 | (channel << 10), 0x000c0001); + wait_428c(channel); + FOR_ALL_LANES + if (read32(DEFAULT_MCHBAR | 0x4340 | (channel << 10))) + die("Mini channel test failed (2)\n"); + } +} + +static void set_scrambling_seed(ramctr_timing * ctrl) +{ + int channel; + + /* FIXME: we hardcode seeds. Do we need to use some PRNG for them? + I don't think so. */ + static u32 seeds[NUM_CHANNELS][3] = { + {0x00009a36, 0xbafcfdcf, 0x46d1ab68}, + {0x00028bfa, 0x53fe4b49, 0x19ed5483} + }; + FOR_ALL_POPULATED_CHANNELS { + MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000; + write32(DEFAULT_MCHBAR | 0x4034, seeds[channel][0]); + write32(DEFAULT_MCHBAR | 0x403c, seeds[channel][1]); + write32(DEFAULT_MCHBAR | 0x4038, seeds[channel][2]); + } +} + +static void set_4f8c(void) +{ + struct cpuid_result cpures; + u32 cpu; + + cpures = cpuid(0); + cpu = (cpures.eax); + if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) { + MCHBAR32(0x4f8c) = 0x141D1519; + } else { + MCHBAR32(0x4f8c) = 0x551D1519; + } +} + +static void prepare_training(ramctr_timing * ctrl) +{ + int channel; + + FOR_ALL_POPULATED_CHANNELS { + // Always drive command bus + MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000; + } + + udelay(1); + + FOR_ALL_POPULATED_CHANNELS wait_428c(channel); +} + +static void hardcode1(ramctr_timing * ctrl) +{ + int channel; + u32 reg; + FOR_ALL_POPULATED_CHANNELS { + reg = read32(DEFAULT_MCHBAR | 0x400c | (channel << 10)); + write32(DEFAULT_MCHBAR | 0x400c | (channel << 10), + (reg & 0xFFF0FFFF) + | (ctrl->ref_card_offset[channel] << 16) + | (ctrl->ref_card_offset[channel] << 18)); + write32(DEFAULT_MCHBAR | 0x4008 | (channel << 10), 0x0a042220); // FIXME: hardcoded + } +} + +static void set_42a0(ramctr_timing * ctrl) +{ + int channel; + FOR_ALL_POPULATED_CHANNELS { + write32(DEFAULT_MCHBAR | (0x42a0 + 0x400 * channel), + 0x00001000 | ctrl->rankmap[channel]); + MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK + } +} + +void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck) +{ + int me_uma_size; + + MCHBAR32(0x5f00) |= 1; + + report_platform_info(); + + /* Wait for ME to be ready */ + intel_early_me_init(); + me_uma_size = intel_early_me_uma_size(); + + printk(BIOS_DEBUG, "Starting native Platform init\n"); + + u32 reg_5d10; + + wait_txt_clear(); + + wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 }); + + reg_5d10 = read32(DEFAULT_MCHBAR | 0x5d10); // !!! = 0x00000000 + if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */ + && reg_5d10) { + write32(DEFAULT_MCHBAR | 0x5d10, 0); + /* Need reset. */ + outb(0x6, 0xcf9); + + while (1) ; + } + + ramctr_timing ctrl; + + dimm_info info; + + early_pch_init_native(); + early_thermal_init(); + + ctrl.mobile = mobile; + ctrl.tCK = min_tck; + + /* Get DDR3 SPD data */ + dram_find_spds_ddr3(spds, &info, &ctrl); + + /* Find fastest common supported parameters */ + dram_find_common_params(&info, &ctrl); + + /* Calculate timings */ + dram_timing(&ctrl); + + /* Set MCU frequency */ + dram_freq(&ctrl); + + /* Set version register */ + MCHBAR32(0x5034) = 0xC04EB002; + + /* Enable crossover */ + dram_xover(&ctrl); + + /* Set timing and refresh registers */ + dram_timing_regs(&ctrl); + + /* Power mode preset */ + MCHBAR32(0x4e80) = 0x5500; + + /* Set scheduler parameters */ + MCHBAR32(0x4c20) = 0x10100005; + + /* Set cpu specific register */ + set_4f8c(); + + /* Clear IO reset bit */ + MCHBAR32(0x5030) &= ~0x20; + + /* Set MAD-DIMM registers */ + dram_dimm_mapping(&info, &ctrl); + printk(BIOS_DEBUG, "Done dimm mapping\n"); + + /* Zone config */ + dram_zones(&info, &ctrl, 1); + + /* Set memory map */ + dram_memorymap(&info, me_uma_size); + printk(BIOS_DEBUG, "Done memory map\n"); + + /* Set IO registers */ + dram_ioregs(&ctrl); + printk(BIOS_DEBUG, "Done io registers\n"); + + udelay(1); + + /* Do jedec ddr3 reset sequence */ + dram_jedecreset(&ctrl); + printk(BIOS_DEBUG, "Done jedec reset\n"); + + /* MRS commands */ + dram_mrscommands(&ctrl); + printk(BIOS_DEBUG, "Done MRS commands\n"); + dram_mrscommands(&ctrl); + + /* Prepare for memory training */ + prepare_training(&ctrl); + + read_training(&ctrl); + write_training(&ctrl); + + printk(BIOS_SPEW, "CP5a\n"); + + discover_edges(&ctrl); + + printk(BIOS_SPEW, "CP5b\n"); + + command_training(&ctrl); + + printk(BIOS_SPEW, "CP5c\n"); + + discover_edges_write(&ctrl); + + discover_timC_write(&ctrl); + + normalize_training(&ctrl); + + hardcode1(&ctrl); + + write_controller_mr(&ctrl); + + channel_test(&ctrl); + + write32(DEFAULT_MCHBAR | 0x5024, 0x00a030ce); // FIXME: hardcoded + + set_scrambling_seed(&ctrl); + + set_42a0(&ctrl); + + write32(DEFAULT_MCHBAR | 0x4cd4, 0x00000046); // FIXME: hardcoded + + write32(DEFAULT_MCHBAR | 0x400c, (read32(DEFAULT_MCHBAR | 0x400c) & 0xFFFFCFFF) | 0x1000); // OK + write32(DEFAULT_MCHBAR | 0x440c, (read32(DEFAULT_MCHBAR | 0x440c) & 0xFFFFCFFF) | 0x1000); // OK + write32(DEFAULT_MCHBAR | 0x4cb0, 0x00000740); // FIXME: hardcoded + write32(DEFAULT_MCHBAR | 0x4380, 0x00000aaa); // OK + write32(DEFAULT_MCHBAR | 0x4780, 0x00000aaa); // OK + write32(DEFAULT_MCHBAR | 0x4f88, 0x5f7003ff); // OK + write32(DEFAULT_MCHBAR | 0x5064, 0x00073000 | ctrl.reg_5064b0); // OK + write32(DEFAULT_MCHBAR | 0x4384, 0x009b6ea1); // FIXME: hardcoded + write32(DEFAULT_MCHBAR | 0x4784, 0x009b6ea1); // FIXME: hardcoded + write32(DEFAULT_MCHBAR | 0x5880, 0xca9171e5); // FIXME: hardcoded + read32(DEFAULT_MCHBAR | 0x5888); // !!! = 0x00e4d5d0 + write32(DEFAULT_MCHBAR | 0x5888, 0x00e4d5d0); // FIXME: hardcoded + read32(DEFAULT_MCHBAR | 0x58a8); // !!! = 0x00000000 + write32(DEFAULT_MCHBAR | 0x58a8, 0x00000000); // FIXME: hardcoded + read32(DEFAULT_MCHBAR | 0x4294); // !!! = 0x000098ff + write32(DEFAULT_MCHBAR | 0x4294, 0x000198ff); // FIXME: hardcoded + read32(DEFAULT_MCHBAR | 0x4694); // !!! = 0x000098ff + write32(DEFAULT_MCHBAR | 0x4694, 0x000198ff); // FIXME: hardcoded + + MCHBAR32(0x5030) |= 1; // OK + MCHBAR32(0x5030) |= 0x80; // OK + MCHBAR32(0x5f18) = 0xfa; // OK + read32(DEFAULT_MCHBAR | 0x5d10); // !!! = 0x00000000 + write32(DEFAULT_MCHBAR | 0x5d10, 0x2010040c); // FIXME: hardcoded + + /* Zone config */ + dram_zones(&info, &ctrl, 0); + + intel_early_me_status(); + intel_early_me_init_done(ME_INIT_STATUS_SUCCESS); + intel_early_me_status(); + + post_system_agent_init(); + report_memory_config(); +} diff --git a/src/northbridge/intel/sandybridge/raminit_native.h b/src/northbridge/intel/sandybridge/raminit_native.h new file mode 100644 index 0000000..ff7d7c1 --- /dev/null +++ b/src/northbridge/intel/sandybridge/raminit_native.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RAMINIT_H +#define RAMINIT_H + +#include <device/dram/ddr3.h> + +/* The order is ch0dimmA, ch0dimmB, ch1dimmA, ch1dimmB. */ +void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck); +void read_spd(spd_raw_data *spd, u8 addr); + +#endif /* RAMINIT_H */ diff --git a/src/southbridge/intel/bd82x6x/Makefile.inc b/src/southbridge/intel/bd82x6x/Makefile.inc index 64038e5..fa21277 100644 --- a/src/southbridge/intel/bd82x6x/Makefile.inc +++ b/src/southbridge/intel/bd82x6x/Makefile.inc @@ -45,10 +45,14 @@ smm-$(CONFIG_SPI_FLASH_SMM) += ../common/spi.c ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c me.c me_8.x.c finalize.c pch.c -romstage-y += early_usb.c early_smbus.c early_me.c me_status.c gpio.c +romstage-y += early_usb.c early_smbus.c me_status.c gpio.c romstage-y += reset.c romstage-y += early_spi.c early_pch.c +romstage-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += early_me.c +romstage-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += early_me.c +romstage-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE) += early_thermal.c early_pch_native.c early_me_native.c + ifeq ($(CONFIG_BUILD_WITH_FAKE_IFD),y) IFD_BIN_PATH := $(objgenerated)/ifdfake.bin IFD_SECTIONS := $(addprefix -b ,$(CONFIG_IFD_BIOS_SECTION:"%"=%)) \ diff --git a/src/southbridge/intel/bd82x6x/early_me_native.c b/src/southbridge/intel/bd82x6x/early_me_native.c new file mode 100644 index 0000000..ab54ffd --- /dev/null +++ b/src/southbridge/intel/bd82x6x/early_me_native.c @@ -0,0 +1,272 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <arch/hlt.h> +#include <arch/io.h> +#include <console/console.h> +#include <delay.h> +#include <device/pci_ids.h> +#include <string.h> +#include "me.h" +#include "pch.h" + +static const char *me_ack_values[] = { + [ME_HFS_ACK_NO_DID] = "No DID Ack received", + [ME_HFS_ACK_RESET] = "Non-power cycle reset", + [ME_HFS_ACK_PWR_CYCLE] = "Power cycle reset", + [ME_HFS_ACK_S3] = "Go to S3", + [ME_HFS_ACK_S4] = "Go to S4", + [ME_HFS_ACK_S5] = "Go to S5", + [ME_HFS_ACK_GBL_RESET] = "Global Reset", + [ME_HFS_ACK_CONTINUE] = "Continue to boot" +}; + +static inline void pci_read_dword_ptr(void *ptr, int offset) +{ + u32 dword = pci_read_config32(PCH_ME_DEV, offset); + memcpy(ptr, &dword, sizeof(dword)); +} + +static inline void pci_write_dword_ptr(void *ptr, int offset) +{ + u32 dword = 0; + memcpy(&dword, ptr, sizeof(dword)); + pci_write_config32(PCH_ME_DEV, offset, dword); +} + +void intel_early_me_status(void) +{ + struct me_hfs hfs; + struct me_gmes gmes; + + pci_read_dword_ptr(&hfs, PCI_ME_HFS); + pci_read_dword_ptr(&gmes, PCI_ME_GMES); + + intel_me_status(&hfs, &gmes); +} + +int intel_early_me_init(void) +{ + int count; + struct me_uma uma; + struct me_hfs hfs; + + printk(BIOS_INFO, "Intel ME early init\n"); + + /* Wait for ME UMA SIZE VALID bit to be set */ + for (count = ME_RETRY; count > 0; --count) { + pci_read_dword_ptr(&uma, PCI_ME_UMA); + if (uma.valid) + break; + udelay(ME_DELAY); + } + if (!count) { + printk(BIOS_ERR, "ERROR: ME is not ready!\n"); + return -1; + } + + /* Check for valid firmware */ + pci_read_dword_ptr(&hfs, PCI_ME_HFS); + if (hfs.fpt_bad) { + printk(BIOS_WARNING, "WARNING: ME has bad firmware\n"); + return -1; + } + + printk(BIOS_INFO, "Intel ME firmware is ready\n"); + return 0; +} + +int intel_early_me_uma_size(void) +{ + struct me_uma uma; + + pci_read_dword_ptr(&uma, PCI_ME_UMA); + if (uma.valid) { + printk(BIOS_DEBUG, "ME: Requested %uMB UMA\n", uma.size); + return uma.size; + } + + printk(BIOS_DEBUG, "ME: Invalid UMA size\n"); + return 0; +} + +static inline void set_global_reset(int enable) +{ + u32 etr3 = pci_read_config32(PCH_LPC_DEV, ETR3); + + /* Clear CF9 Without Resume Well Reset Enable */ + etr3 &= ~ETR3_CWORWRE; + + /* CF9GR indicates a Global Reset */ + if (enable) + etr3 |= ETR3_CF9GR; + else + etr3 &= ~ETR3_CF9GR; + + pci_write_config32(PCH_LPC_DEV, ETR3, etr3); +} + +int intel_early_me_init_done(u8 status) +{ + u8 reset, errorcode, opmode; + u16 reg16; + u32 mebase_l, mebase_h; + u32 millisec; + u32 hfs, me_fws2; + struct me_did did = { + .init_done = ME_INIT_DONE, + .status = status + }; + u32 meDID; + + hfs = (pci_read_config32(PCI_DEV(0, 0x16, 0), PCI_ME_HFS) & 0xff000) >> 12; + + opmode = (hfs & 0xf0) >> 4; + errorcode = hfs & 0xf; + + if (opmode != ME_HFS_MODE_NORMAL) { + printk(BIOS_NOTICE, "ME: Wrong mode : %d\n", opmode); + //return 0; + } + if (errorcode) { + printk(BIOS_NOTICE, "ME: HFS error : %d\n", errorcode); + //return 0; + } + + me_fws2 = pci_read_config32(PCI_DEV(0, 0x16, 0), 0x48); + printk(BIOS_NOTICE, "ME: FWS2: 0x%x\n", me_fws2); + printk(BIOS_NOTICE, "ME: Bist in progress: 0x%x\n", me_fws2 & 0x1); + printk(BIOS_NOTICE, "ME: ICC Status : 0x%x\n", (me_fws2 & 0x6) >> 1); + printk(BIOS_NOTICE, "ME: Invoke MEBx : 0x%x\n", (me_fws2 & 0x8) >> 3); + printk(BIOS_NOTICE, "ME: CPU replaced : 0x%x\n", (me_fws2 & 0x10) >> 4); + printk(BIOS_NOTICE, "ME: MBP ready : 0x%x\n", (me_fws2 & 0x20) >> 5); + printk(BIOS_NOTICE, "ME: MFS failure : 0x%x\n", (me_fws2 & 0x40) >> 6); + printk(BIOS_NOTICE, "ME: Warm reset req : 0x%x\n", (me_fws2 & 0x80) >> 7); + printk(BIOS_NOTICE, "ME: CPU repl valid : 0x%x\n", (me_fws2 & 0x100) >> 8); + printk(BIOS_NOTICE, "ME: (Reserved) : 0x%x\n", (me_fws2 & 0x600) >> 9); + printk(BIOS_NOTICE, "ME: FW update req : 0x%x\n", (me_fws2 & 0x800) >> 11); + printk(BIOS_NOTICE, "ME: (Reserved) : 0x%x\n", (me_fws2 & 0xf000) >> 12); + printk(BIOS_NOTICE, "ME: Current state : 0x%x\n", (me_fws2 & 0xff0000) >> 16); + printk(BIOS_NOTICE, "ME: Current PM event: 0x%x\n", (me_fws2 & 0xf000000) >> 24); + printk(BIOS_NOTICE, "ME: Progress code : 0x%x\n", (me_fws2 & 0xf0000000) >> 28); + + // Poll cpu replaced for 50ms + millisec = 0; + while ((((me_fws2 & 0x100) >> 8) == 0) && millisec < 50) { + udelay(1000); + me_fws2 = pci_read_config32(PCI_DEV(0, 0x16, 0), 0x48); + millisec++; + } + if (millisec >= 50 || ((me_fws2 & 0x100) >> 8) == 0x0) { + printk(BIOS_NOTICE, "Waited long enough, or CPU was not replaced, continue...\n"); + } else if ((me_fws2 & 0x100) == 0x100) { + if ((me_fws2 & 0x80) == 0x80) { + printk(BIOS_NOTICE, "CPU was replaced & warm reset required...\n"); + reg16 = pcie_read_config16(PCI_DEV(0, 31, 0), 0xa2) & ~0x80; + pcie_write_config16(PCI_DEV(0, 31, 0), 0xa2, reg16); + set_global_reset(0); + outb(0x6, 0xcf9); + hlt(); + } + + if (((me_fws2 & 0x10) == 0x10) && (me_fws2 & 0x80) == 0x00) { + printk(BIOS_NOTICE, "Full training required\n"); + } + } + + printk(BIOS_NOTICE, "PASSED! Tell ME that DRAM is ready\n"); + + /* MEBASE from MESEG_BASE[35:20] */ + mebase_l = pci_read_config32(PCI_CPU_DEVICE, PCI_CPU_MEBASE_L); + mebase_h = pci_read_config32(PCI_CPU_DEVICE, PCI_CPU_MEBASE_H) & 0xf; + did.uma_base = (mebase_l >> 20) | (mebase_h << 12); + + meDID = did.uma_base | (1 << 28);// | (1 << 23); + pci_write_config32(PCI_DEV(0, 0x16, 0), PCI_ME_H_GS, meDID); + + udelay(1100); + + /* Must wait for ME acknowledgement */ + millisec = 0; + hfs = (pci_read_config32(PCI_DEV(0, 0x16, 0), PCI_ME_HFS) & 0xfe000000) >> 24; + while ((((hfs & 0xf0) >> 4) != ME_HFS_BIOS_DRAM_ACK) && (millisec < 5000)) { + udelay(1000); + hfs = (pci_read_config32(PCI_DEV(0, 0x16, 0), PCI_ME_HFS) & 0xfe000000) >> 24; + millisec++; + } + + me_fws2 = pci_read_config32(PCI_DEV(0, 0x16, 0), 0x48); + printk(BIOS_NOTICE, "ME: FWS2: 0x%x\n", me_fws2); + printk(BIOS_NOTICE, "ME: Bist in progress: 0x%x\n", me_fws2 & 0x1); + printk(BIOS_NOTICE, "ME: ICC Status : 0x%x\n", (me_fws2 & 0x6) >> 1); + printk(BIOS_NOTICE, "ME: Invoke MEBx : 0x%x\n", (me_fws2 & 0x8) >> 3); + printk(BIOS_NOTICE, "ME: CPU replaced : 0x%x\n", (me_fws2 & 0x10) >> 4); + printk(BIOS_NOTICE, "ME: MBP ready : 0x%x\n", (me_fws2 & 0x20) >> 5); + printk(BIOS_NOTICE, "ME: MFS failure : 0x%x\n", (me_fws2 & 0x40) >> 6); + printk(BIOS_NOTICE, "ME: Warm reset req : 0x%x\n", (me_fws2 & 0x80) >> 7); + printk(BIOS_NOTICE, "ME: CPU repl valid : 0x%x\n", (me_fws2 & 0x100) >> 8); + printk(BIOS_NOTICE, "ME: (Reserved) : 0x%x\n", (me_fws2 & 0x600) >> 9); + printk(BIOS_NOTICE, "ME: FW update req : 0x%x\n", (me_fws2 & 0x800) >> 11); + printk(BIOS_NOTICE, "ME: (Reserved) : 0x%x\n", (me_fws2 & 0xf000) >> 12); + printk(BIOS_NOTICE, "ME: Current state : 0x%x\n", (me_fws2 & 0xff0000) >> 16); + printk(BIOS_NOTICE, "ME: Current PM event: 0x%x\n", (me_fws2 & 0xf000000) >> 24); + printk(BIOS_NOTICE, "ME: Progress code : 0x%x\n", (me_fws2 & 0xf0000000) >> 28); + + + /* Return the requested BIOS action */ + printk(BIOS_NOTICE, "ME: Requested BIOS Action: %s\n", + me_ack_values[(hfs & 0xe) >> 1]); + + reset = inb(0xcf9); + reset &= 0xf1; + switch ((hfs & 0xe) >> 1) { + case ME_HFS_ACK_NO_DID: + case ME_HFS_ACK_CONTINUE: + /* Continue to boot */ + return 0; + case ME_HFS_ACK_RESET: + /* Non-power cycle reset */ + set_global_reset(0); + reset |= 0x06; + break; + case ME_HFS_ACK_PWR_CYCLE: + /* Power cycle reset */ + set_global_reset(0); + reset |= 0x0e; + break; + case ME_HFS_ACK_GBL_RESET: + /* Global reset */ + set_global_reset(1); + reset |= 0x0e; + break; + case ME_HFS_ACK_S3: + case ME_HFS_ACK_S4: + case ME_HFS_ACK_S5: + break; + } + + /* Perform the requested reset */ + if (reset) { + outb(reset, 0xcf9); + hlt(); + } + return -1; +} diff --git a/src/southbridge/intel/bd82x6x/early_pch_native.c b/src/southbridge/intel/bd82x6x/early_pch_native.c new file mode 100644 index 0000000..5cd6315 --- /dev/null +++ b/src/southbridge/intel/bd82x6x/early_pch_native.c @@ -0,0 +1,375 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Vladimir Serbinenko <phcoder(a)gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <string.h> +#include <arch/hlt.h> +#include <arch/io.h> +#include <cbmem.h> +#include <arch/cbfs.h> +#include <cbfs.h> +#include <ip_checksum.h> +#include <pc80/mc146818rtc.h> +#include <device/pci_def.h> +#include <delay.h> + +#include "pch.h" +/* For DMI bar. */ +#include "northbridge/intel/sandybridge/sandybridge.h" + +#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0) + +static void +wait_2338 (void) +{ + while (read8 (DEFAULT_RCBA | 0x2338) & 1); +} + +static u32 +read_2338 (u32 edx) +{ + u32 ret; + + write32 (DEFAULT_RCBA | 0x2330, edx); + write16 (DEFAULT_RCBA | 0x2338, (read16 (DEFAULT_RCBA | 0x2338) + & 0x1ff) | 0x600); + wait_2338 (); + ret = read32 (DEFAULT_RCBA | 0x2334); + wait_2338 (); + read8 (DEFAULT_RCBA | 0x2338); + return ret; +} + +static void +write_2338 (u32 edx, u32 val) +{ + read_2338 (edx); + write16 (DEFAULT_RCBA | 0x2338, (read16 (DEFAULT_RCBA | 0x2338) + & 0x1ff) | 0x600); + wait_2338 (); + + write32 (DEFAULT_RCBA | 0x2334, val); + wait_2338 (); + write16 (DEFAULT_RCBA | 0x2338, + (read16 (DEFAULT_RCBA | 0x2338) & 0x1ff) | 0x600); + read8 (DEFAULT_RCBA | 0x2338); +} + + +static void +init_dmi (void) +{ + int i; + + write32 (DEFAULT_DMIBAR | 0x0914, + read32 (DEFAULT_DMIBAR | 0x0914) | 0x80000000); + write32 (DEFAULT_DMIBAR | 0x0934, + read32 (DEFAULT_DMIBAR | 0x0934) | 0x80000000); + for (i = 0; i < 4; i++) + { + write32 (DEFAULT_DMIBAR | 0x0a00 | (i << 4), + read32 (DEFAULT_DMIBAR | 0x0a00 | (i << 4)) & 0xf3ffffff); + write32 (DEFAULT_DMIBAR | 0x0a04 | (i << 4), + read32 (DEFAULT_DMIBAR | 0x0a04 | (i << 4)) | 0x800); + } + write32 (DEFAULT_DMIBAR | 0x0c30, (read32 (DEFAULT_DMIBAR | 0x0c30) + & 0xfffffff) | 0x40000000); + for (i = 0; i < 2; i++) + { + write32 (DEFAULT_DMIBAR | 0x0904 | (i << 5), + read32 (DEFAULT_DMIBAR | 0x0904 | (i << 5)) & 0xfe3fffff); + write32 (DEFAULT_DMIBAR | 0x090c | (i << 5), + read32 (DEFAULT_DMIBAR | 0x090c | (i << 5)) & 0xfff1ffff); + } + write32 (DEFAULT_DMIBAR | 0x090c, + read32 (DEFAULT_DMIBAR | 0x090c) & 0xfe1fffff); + write32 (DEFAULT_DMIBAR | 0x092c, + read32 (DEFAULT_DMIBAR | 0x092c) & 0xfe1fffff); + read32 (DEFAULT_DMIBAR | 0x0904); // !!! = 0x7a1842ec + write32 (DEFAULT_DMIBAR | 0x0904, 0x7a1842ec); + read32 (DEFAULT_DMIBAR | 0x090c); // !!! = 0x00000208 + write32 (DEFAULT_DMIBAR | 0x090c, 0x00000128); + read32 (DEFAULT_DMIBAR | 0x0924); // !!! = 0x7a1842ec + write32 (DEFAULT_DMIBAR | 0x0924, 0x7a1842ec); + read32 (DEFAULT_DMIBAR | 0x092c); // !!! = 0x00000208 + write32 (DEFAULT_DMIBAR | 0x092c, 0x00000128); + read32 (DEFAULT_DMIBAR | 0x0700); // !!! = 0x46139008 + write32 (DEFAULT_DMIBAR | 0x0700, 0x46139008); + read32 (DEFAULT_DMIBAR | 0x0720); // !!! = 0x46139008 + write32 (DEFAULT_DMIBAR | 0x0720, 0x46139008); + read32 (DEFAULT_DMIBAR | 0x0c04); // !!! = 0x2e680008 + write32 (DEFAULT_DMIBAR | 0x0c04, 0x2e680008); + read32 (DEFAULT_DMIBAR | 0x0904); // !!! = 0x7a1842ec + write32 (DEFAULT_DMIBAR | 0x0904, 0x3a1842ec); + read32 (DEFAULT_DMIBAR | 0x0924); // !!! = 0x7a1842ec + write32 (DEFAULT_DMIBAR | 0x0924, 0x3a1842ec); + read32 (DEFAULT_DMIBAR | 0x0910); // !!! = 0x00006300 + write32 (DEFAULT_DMIBAR | 0x0910, 0x00004300); + read32 (DEFAULT_DMIBAR | 0x0930); // !!! = 0x00006300 + write32 (DEFAULT_DMIBAR | 0x0930, 0x00004300); + read32 (DEFAULT_DMIBAR | 0x0a00); // !!! = 0x03042010 + write32 (DEFAULT_DMIBAR | 0x0a00, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0a10); // !!! = 0x03042010 + write32 (DEFAULT_DMIBAR | 0x0a10, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0a20); // !!! = 0x03042010 + write32 (DEFAULT_DMIBAR | 0x0a20, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0a30); // !!! = 0x03042010 + write32 (DEFAULT_DMIBAR | 0x0a30, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0c00); // !!! = 0x29700c08 + write32 (DEFAULT_DMIBAR | 0x0c00, 0x29700c08); + read32 (DEFAULT_DMIBAR | 0x0a04); // !!! = 0x0c0708f0 + write32 (DEFAULT_DMIBAR | 0x0a04, 0x0c0718f0); + read32 (DEFAULT_DMIBAR | 0x0a14); // !!! = 0x0c0708f0 + write32 (DEFAULT_DMIBAR | 0x0a14, 0x0c0718f0); + read32 (DEFAULT_DMIBAR | 0x0a24); // !!! = 0x0c0708f0 + write32 (DEFAULT_DMIBAR | 0x0a24, 0x0c0718f0); + read32 (DEFAULT_DMIBAR | 0x0a34); // !!! = 0x0c0708f0 + write32 (DEFAULT_DMIBAR | 0x0a34, 0x0c0718f0); + read32 (DEFAULT_DMIBAR | 0x0900); // !!! = 0x50000000 + write32 (DEFAULT_DMIBAR | 0x0900, 0x50000000); + read32 (DEFAULT_DMIBAR | 0x0920); // !!! = 0x50000000 + write32 (DEFAULT_DMIBAR | 0x0920, 0x50000000); + read32 (DEFAULT_DMIBAR | 0x0908); // !!! = 0x51ffffff + write32 (DEFAULT_DMIBAR | 0x0908, 0x51ffffff); + read32 (DEFAULT_DMIBAR | 0x0928); // !!! = 0x51ffffff + write32 (DEFAULT_DMIBAR | 0x0928, 0x51ffffff); + read32 (DEFAULT_DMIBAR | 0x0a00); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a00, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0a10); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a10, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0a20); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a20, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0a30); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a30, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0700); // !!! = 0x46139008 + write32 (DEFAULT_DMIBAR | 0x0700, 0x46139008); + read32 (DEFAULT_DMIBAR | 0x0720); // !!! = 0x46139008 + write32 (DEFAULT_DMIBAR | 0x0720, 0x46139008); + read32 (DEFAULT_DMIBAR | 0x0904); // !!! = 0x3a1842ec + write32 (DEFAULT_DMIBAR | 0x0904, 0x3a1846ec); + read32 (DEFAULT_DMIBAR | 0x0924); // !!! = 0x3a1842ec + write32 (DEFAULT_DMIBAR | 0x0924, 0x3a1846ec); + read32 (DEFAULT_DMIBAR | 0x0a00); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a00, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0a10); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a10, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0a20); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a20, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0a30); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a30, 0x03042018); + read32 (DEFAULT_DMIBAR | 0x0908); // !!! = 0x51ffffff + write32 (DEFAULT_DMIBAR | 0x0908, 0x51ffffff); + read32 (DEFAULT_DMIBAR | 0x0928); // !!! = 0x51ffffff + write32 (DEFAULT_DMIBAR | 0x0928, 0x51ffffff); + read32 (DEFAULT_DMIBAR | 0x0c00); // !!! = 0x29700c08 + write32 (DEFAULT_DMIBAR | 0x0c00, 0x29700c08); + read32 (DEFAULT_DMIBAR | 0x0c0c); // !!! = 0x16063400 + write32 (DEFAULT_DMIBAR | 0x0c0c, 0x00063400); + read32 (DEFAULT_DMIBAR | 0x0700); // !!! = 0x46139008 + write32 (DEFAULT_DMIBAR | 0x0700, 0x46339008); + read32 (DEFAULT_DMIBAR | 0x0720); // !!! = 0x46139008 + write32 (DEFAULT_DMIBAR | 0x0720, 0x46339008); + read32 (DEFAULT_DMIBAR | 0x0700); // !!! = 0x46339008 + write32 (DEFAULT_DMIBAR | 0x0700, 0x45339008); + read32 (DEFAULT_DMIBAR | 0x0720); // !!! = 0x46339008 + write32 (DEFAULT_DMIBAR | 0x0720, 0x45339008); + read32 (DEFAULT_DMIBAR | 0x0700); // !!! = 0x45339008 + write32 (DEFAULT_DMIBAR | 0x0700, 0x453b9008); + read32 (DEFAULT_DMIBAR | 0x0720); // !!! = 0x45339008 + write32 (DEFAULT_DMIBAR | 0x0720, 0x453b9008); + read32 (DEFAULT_DMIBAR | 0x0700); // !!! = 0x453b9008 + write32 (DEFAULT_DMIBAR | 0x0700, 0x45bb9008); + read32 (DEFAULT_DMIBAR | 0x0720); // !!! = 0x453b9008 + write32 (DEFAULT_DMIBAR | 0x0720, 0x45bb9008); + read32 (DEFAULT_DMIBAR | 0x0700); // !!! = 0x45bb9008 + write32 (DEFAULT_DMIBAR | 0x0700, 0x45fb9008); + read32 (DEFAULT_DMIBAR | 0x0720); // !!! = 0x45bb9008 + write32 (DEFAULT_DMIBAR | 0x0720, 0x45fb9008); + read32 (DEFAULT_DMIBAR | 0x0914); // !!! = 0x9021a080 + write32 (DEFAULT_DMIBAR | 0x0914, 0x9021a280); + read32 (DEFAULT_DMIBAR | 0x0934); // !!! = 0x9021a080 + write32 (DEFAULT_DMIBAR | 0x0934, 0x9021a280); + read32 (DEFAULT_DMIBAR | 0x0914); // !!! = 0x9021a280 + write32 (DEFAULT_DMIBAR | 0x0914, 0x9821a280); + read32 (DEFAULT_DMIBAR | 0x0934); // !!! = 0x9021a280 + write32 (DEFAULT_DMIBAR | 0x0934, 0x9821a280); + read32 (DEFAULT_DMIBAR | 0x0a00); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a00, 0x03242018); + read32 (DEFAULT_DMIBAR | 0x0a10); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a10, 0x03242018); + read32 (DEFAULT_DMIBAR | 0x0a20); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a20, 0x03242018); + read32 (DEFAULT_DMIBAR | 0x0a30); // !!! = 0x03042018 + write32 (DEFAULT_DMIBAR | 0x0a30, 0x03242018); + read32 (DEFAULT_DMIBAR | 0x0258); // !!! = 0x40000600 + write32 (DEFAULT_DMIBAR | 0x0258, 0x60000600); + read32 (DEFAULT_DMIBAR | 0x0904); // !!! = 0x3a1846ec + write32 (DEFAULT_DMIBAR | 0x0904, 0x2a1846ec); + read32 (DEFAULT_DMIBAR | 0x0914); // !!! = 0x9821a280 + write32 (DEFAULT_DMIBAR | 0x0914, 0x98200280); + read32 (DEFAULT_DMIBAR | 0x0924); // !!! = 0x3a1846ec + write32 (DEFAULT_DMIBAR | 0x0924, 0x2a1846ec); + read32 (DEFAULT_DMIBAR | 0x0934); // !!! = 0x9821a280 + write32 (DEFAULT_DMIBAR | 0x0934, 0x98200280); + read32 (DEFAULT_DMIBAR | 0x022c); // !!! = 0x00c26460 + write32 (DEFAULT_DMIBAR | 0x022c, 0x00c2403c); + read8 (DEFAULT_RCBA | 0x21a4); // !!! = 0x42 + + read32 (DEFAULT_RCBA | 0x21a4); // !!! = 0x00012c42 + read32 (DEFAULT_RCBA | 0x2340); // !!! = 0x0013001b + write32 (DEFAULT_RCBA | 0x2340, 0x003a001b); + read8 (DEFAULT_RCBA | 0x21b0); // !!! = 0x01 + write8 (DEFAULT_RCBA | 0x21b0, 0x02); + read32 (DEFAULT_DMIBAR | 0x0084); // !!! = 0x0041ac41 + write32 (DEFAULT_DMIBAR | 0x0084, 0x0041ac42); + read8 (DEFAULT_DMIBAR | 0x0088); // !!! = 0x00 + write8 (DEFAULT_DMIBAR | 0x0088, 0x20); + read16 (DEFAULT_DMIBAR | 0x008a); // !!! = 0x0041 + read8 (DEFAULT_DMIBAR | 0x0088); // !!! = 0x00 + write8 (DEFAULT_DMIBAR | 0x0088, 0x20); + read16 (DEFAULT_DMIBAR | 0x008a); // !!! = 0x0042 + read16 (DEFAULT_DMIBAR | 0x008a); // !!! = 0x0042 + + read32 (DEFAULT_DMIBAR | 0x0014); // !!! = 0x8000007f + write32 (DEFAULT_DMIBAR | 0x0014, 0x80000019); + read32 (DEFAULT_DMIBAR | 0x0020); // !!! = 0x01000000 + write32 (DEFAULT_DMIBAR | 0x0020, 0x81000022); + read32 (DEFAULT_DMIBAR | 0x002c); // !!! = 0x02000000 + write32 (DEFAULT_DMIBAR | 0x002c, 0x82000044); + read32 (DEFAULT_DMIBAR | 0x0038); // !!! = 0x07000080 + write32 (DEFAULT_DMIBAR | 0x0038, 0x87000080); + read8 (DEFAULT_DMIBAR | 0x0004); // !!! = 0x00 + write8 (DEFAULT_DMIBAR | 0x0004, 0x01); + + read32 (DEFAULT_RCBA | 0x0050); // !!! = 0x01200654 + write32 (DEFAULT_RCBA | 0x0050, 0x01200654); + read32 (DEFAULT_RCBA | 0x0050); // !!! = 0x01200654 + write32 (DEFAULT_RCBA | 0x0050, 0x012a0654); + read32 (DEFAULT_RCBA | 0x0050); // !!! = 0x012a0654 + read8 (DEFAULT_RCBA | 0x1114); // !!! = 0x00 + write8 (DEFAULT_RCBA | 0x1114, 0x05); + read32 (DEFAULT_RCBA | 0x2014); // !!! = 0x80000011 + write32 (DEFAULT_RCBA | 0x2014, 0x80000019); + read32 (DEFAULT_RCBA | 0x2020); // !!! = 0x00000000 + write32 (DEFAULT_RCBA | 0x2020, 0x81000022); + read32 (DEFAULT_RCBA | 0x2020); // !!! = 0x81000022 + read32 (DEFAULT_RCBA | 0x2030); // !!! = 0x00000000 + write32 (DEFAULT_RCBA | 0x2030, 0x82000044); + read32 (DEFAULT_RCBA | 0x2030); // !!! = 0x82000044 + read32 (DEFAULT_RCBA | 0x2040); // !!! = 0x00000000 + write32 (DEFAULT_RCBA | 0x2040, 0x87000080); + read32 (DEFAULT_RCBA | 0x0050); // !!! = 0x012a0654 + write32 (DEFAULT_RCBA | 0x0050, 0x812a0654); + read32 (DEFAULT_RCBA | 0x0050); // !!! = 0x812a0654 + read16 (DEFAULT_RCBA | 0x201a); // !!! = 0x0000 + read16 (DEFAULT_RCBA | 0x2026); // !!! = 0x0000 + read16 (DEFAULT_RCBA | 0x2036); // !!! = 0x0000 + read16 (DEFAULT_RCBA | 0x2046); // !!! = 0x0000 + read16 (DEFAULT_DMIBAR | 0x001a); // !!! = 0x0000 + read16 (DEFAULT_DMIBAR | 0x0026); // !!! = 0x0000 + read16 (DEFAULT_DMIBAR | 0x0032); // !!! = 0x0000 + read16 (DEFAULT_DMIBAR | 0x003e); // !!! = 0x0000 +} + +void +early_pch_init_native (void) +{ + pcie_write_config8 (SOUTHBRIDGE, 0xa6, + pcie_read_config8 (SOUTHBRIDGE, 0xa6) | 2); + + write32 (DEFAULT_RCBA | 0x2088, 0x00109000); + read32 (DEFAULT_RCBA | 0x20ac); // !!! = 0x00000000 + write32 (DEFAULT_RCBA | 0x20ac, 0x40000000); + write32 (DEFAULT_RCBA | 0x100c, 0x01110000); + write8 (DEFAULT_RCBA | 0x2340, 0x1b); + read32 (DEFAULT_RCBA | 0x2314); // !!! = 0x0a080000 + write32 (DEFAULT_RCBA | 0x2314, 0x0a280000); + read32 (DEFAULT_RCBA | 0x2310); // !!! = 0xc809605b + write32 (DEFAULT_RCBA | 0x2310, 0xa809605b); + write32 (DEFAULT_RCBA | 0x2324, 0x00854c74); + read8 (DEFAULT_RCBA | 0x0400); // !!! = 0x00 + read32 (DEFAULT_RCBA | 0x2310); // !!! = 0xa809605b + write32 (DEFAULT_RCBA | 0x2310, 0xa809605b); + read32 (DEFAULT_RCBA | 0x2310); // !!! = 0xa809605b + write32 (DEFAULT_RCBA | 0x2310, 0xa809605b); + + write_2338 (0xea007f62, 0x00590133); + write_2338 (0xec007f62, 0x00590133); + write_2338 (0xec007f64, 0x59555588); + write_2338 (0xea0040b9, 0x0001051c); + write_2338 (0xeb0040a1, 0x800084ff); + write_2338 (0xec0040a1, 0x800084ff); + write_2338 (0xea004001, 0x00008400); + write_2338 (0xeb004002, 0x40201758); + write_2338 (0xec004002, 0x40201758); + write_2338 (0xea004002, 0x00601758); + write_2338 (0xea0040a1, 0x810084ff); + write_2338 (0xeb0040b1, 0x0001c598); + write_2338 (0xec0040b1, 0x0001c598); + write_2338 (0xeb0040b6, 0x0001c598); + write_2338 (0xea0000a9, 0x80ff969f); + write_2338 (0xea0001a9, 0x80ff969f); + write_2338 (0xeb0040b2, 0x0001c396); + write_2338 (0xeb0040b3, 0x0001c396); + write_2338 (0xec0040b2, 0x0001c396); + write_2338 (0xea0001a9, 0x80ff94ff); + write_2338 (0xea000151, 0x0088037f); + write_2338 (0xea0000a9, 0x80ff94ff); + write_2338 (0xea000051, 0x0088037f); + + write_2338 (0xea007f05, 0x00010642); + write_2338 (0xea0040b7, 0x0001c91c); + write_2338 (0xea0040b8, 0x0001c91c); + write_2338 (0xeb0040a1, 0x820084ff); + write_2338 (0xec0040a1, 0x820084ff); + write_2338 (0xea007f0a, 0xc2480000); + + write_2338 (0xec00404d, 0x1ff177f); + write_2338 (0xec000084, 0x5a600000); + write_2338 (0xec000184, 0x5a600000); + write_2338 (0xec000284, 0x5a600000); + write_2338 (0xec000384, 0x5a600000); + write_2338 (0xec000094, 0x000f0501); + write_2338 (0xec000194, 0x000f0501); + write_2338 (0xec000294, 0x000f0501); + write_2338 (0xec000394, 0x000f0501); + write_2338 (0xec000096, 0x00000001); + write_2338 (0xec000196, 0x00000001); + write_2338 (0xec000296, 0x00000001); + write_2338 (0xec000396, 0x00000001); + write_2338 (0xec000001, 0x00008c08); + write_2338 (0xec000101, 0x00008c08); + write_2338 (0xec000201, 0x00008c08); + write_2338 (0xec000301, 0x00008c08); + write_2338 (0xec0040b5, 0x0001c518); + write_2338 (0xec000087, 0x06077597); + write_2338 (0xec000187, 0x06077597); + write_2338 (0xec000287, 0x06077597); + write_2338 (0xec000387, 0x06077597); + write_2338 (0xea000050, 0x00bb0157); + write_2338 (0xea000150, 0x00bb0157); + write_2338 (0xec007f60, 0x77777d77); + write_2338 (0xea00008d, 0x01320000); + write_2338 (0xea00018d, 0x01320000); + write_2338 (0xec0007b2, 0x04514b5e); + write_2338 (0xec00078c, 0x40000200); + write_2338 (0xec000780, 0x02000020); + + init_dmi(); +} diff --git a/src/southbridge/intel/bd82x6x/early_thermal.c b/src/southbridge/intel/bd82x6x/early_thermal.c new file mode 100644 index 0000000..02ec9a7 --- /dev/null +++ b/src/southbridge/intel/bd82x6x/early_thermal.c @@ -0,0 +1,70 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Vladimir Serbinenko + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <arch/io.h> +#include "pch.h" +#include "cpu/intel/model_206ax/model_206ax.h" +#include <cpu/x86/msr.h> + +/* Early thermal init, must be done prior to giving ME its memory + which is done at the end of raminit. */ +void early_thermal_init(void) +{ + device_t dev; + msr_t msr; + + dev = PCI_DEV(0x0, 0x1f, 0x6); + + /* Program address for temporary BAR. */ + pci_write_config32(dev, 0x40, 0x40000000); + pci_write_config32(dev, 0x44, 0x0); + + /* Activate temporary BAR. */ + pci_write_config32(dev, 0x40, + pci_read_config32(dev, 0x40) | 5); + + + write16 (0x40000004, 0x3a2b); + write8 (0x4000000c, 0xff); + write8 (0x4000000d, 0x00); + write8 (0x4000000e, 0x40); + write8 (0x40000082, 0x00); + write8 (0x40000001, 0xba); + + /* Perform init. */ + /* Configure TJmax. */ + msr = rdmsr(MSR_TEMPERATURE_TARGET); + write16(0x40000012, ((msr.lo >> 16) & 0xff) << 6); + /* Northbridge temperature slope and offset. */ + write16(0x40000016, 0x808c); + + write16 (0x40000014, 0xde87); + + /* Enable thermal data reporting, processor, PCH and northbridge. */ + write16(0x4000001a, (read16(0x4000001a) & ~0xf) | 0x10f0); + + /* Disable temporary BAR. */ + pci_write_config32(dev, 0x40, + pci_read_config32(dev, 0x40) & ~1); + pci_write_config32(dev, 0x40, 0); + + write32 (DEFAULT_RCBA | 0x38b0, + (read32 (DEFAULT_RCBA | 0x38b0) & 0xffff8003) | 0x403c); +} diff --git a/src/southbridge/intel/bd82x6x/pch.h b/src/southbridge/intel/bd82x6x/pch.h index 90de855..83128e2 100644 --- a/src/southbridge/intel/bd82x6x/pch.h +++ b/src/southbridge/intel/bd82x6x/pch.h @@ -74,6 +74,8 @@ void enable_smbus(void); void enable_usb_bar(void); int smbus_read_byte(unsigned device, unsigned address); int early_spi_read(u32 offset, u32 size, u8 *buffer); +void early_thermal_init(void); +void early_pch_init_native(void); #endif #endif diff --git a/src/southbridge/intel/bd82x6x/smi.c b/src/southbridge/intel/bd82x6x/smi.c index 0166edf..a20232e 100644 --- a/src/southbridge/intel/bd82x6x/smi.c +++ b/src/southbridge/intel/bd82x6x/smi.c @@ -29,10 +29,7 @@ #include <cpu/x86/smm.h> #include <string.h> #include "pch.h" - -#if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE #include "northbridge/intel/sandybridge/sandybridge.h" -#endif extern unsigned char _binary_smm_start; extern unsigned char _binary_smm_end; diff --git a/src/southbridge/intel/bd82x6x/usb_ehci.c b/src/southbridge/intel/bd82x6x/usb_ehci.c index 78f92d9..97f20bd 100644 --- a/src/southbridge/intel/bd82x6x/usb_ehci.c +++ b/src/southbridge/intel/bd82x6x/usb_ehci.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <kconfig.h> #include <console/console.h> #include <device/device.h> #include <device/pci.h> @@ -36,11 +37,43 @@ static void usb_ehci_init(struct device *dev) RCBA32(0x35b0) = reg32; printk(BIOS_DEBUG, "EHCI: Setting up controller.. "); + + /* For others, done in MRC. */ +#if IS_ENABLED(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE) + pci_write_config32(dev, 0x84, 0x930c8811); + pci_write_config32(dev, 0x88, 0x24000d30); + pci_write_config32(dev, 0xf4, 0x80408588); + pci_write_config32(dev, 0xf4, 0x80808588); + pci_write_config32(dev, 0xf4, 0x00808588); + pci_write_config32(dev, 0xfc, 0x205b1708); +#endif + reg32 = pci_read_config32(dev, PCI_COMMAND); reg32 |= PCI_COMMAND_MASTER; //reg32 |= PCI_COMMAND_SERR; pci_write_config32(dev, PCI_COMMAND, reg32); + /* For others, done in MRC. */ +#if IS_ENABLED(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE) + struct resource *res; + u8 access_cntl; + + access_cntl = pci_read_config8(dev, 0x80); + + /* Enable writes to protected registers. */ + pci_write_config8(dev, 0x80, access_cntl | 1); + + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res) { + /* Number of ports and companion controllers. */ + reg32 = read32(res->base + 4); + write32(res->base + 4, (reg32 & 0xfff00000) | 3); + } + + /* Restore protection. */ + pci_write_config8(dev, 0x80, access_cntl); +#endif + printk(BIOS_DEBUG, "done.\n"); } diff --git a/src/southbridge/intel/ibexpeak/me.c b/src/southbridge/intel/ibexpeak/me.c index bc56012..0e1b5b8 100644 --- a/src/southbridge/intel/ibexpeak/me.c +++ b/src/southbridge/intel/ibexpeak/me.c @@ -377,125 +377,7 @@ static int mkhi_end_of_post(void) printk(BIOS_INFO, "ME: END OF POST message successful\n"); return 0; } -#endif - -#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) && !defined(__SMM__) && (CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) -/* Get ME firmware version */ -static int mkhi_get_fw_version(void) -{ - struct me_fw_version version; - struct mkhi_header mkhi = { - .group_id = MKHI_GROUP_ID_GEN, - .command = MKHI_GET_FW_VERSION, - }; - struct mei_header mei = { - .is_complete = 1, - .host_address = MEI_HOST_ADDRESS, - .client_address = MEI_ADDRESS_MKHI, - .length = sizeof(mkhi), - }; - - /* Send request and wait for response */ - if (mei_sendrecv(&mei, &mkhi, NULL, &version, sizeof(version)) < 0) { - printk(BIOS_ERR, "ME: GET FW VERSION message failed\n"); - return -1; - } - - printk(BIOS_INFO, "ME: Firmware Version %u.%u.%u.%u (code) " - "%u.%u.%u.%u (recovery)\n", - version.code_major, version.code_minor, - version.code_build_number, version.code_hot_fix, - version.recovery_major, version.recovery_minor, - version.recovery_build_number, version.recovery_hot_fix); - - return 0; -} - -static inline void print_cap(const char *name, int state) -{ - printk(BIOS_DEBUG, "ME Capability: %-30s : %sabled\n", - name, state ? "en" : "dis"); -} - -/* Get ME Firmware Capabilities */ -static int mkhi_get_fwcaps(void) -{ - u32 rule_id = 0; - struct me_fwcaps cap; - struct mkhi_header mkhi = { - .group_id = MKHI_GROUP_ID_FWCAPS, - .command = MKHI_FWCAPS_GET_RULE, - }; - struct mei_header mei = { - .is_complete = 1, - .host_address = MEI_HOST_ADDRESS, - .client_address = MEI_ADDRESS_MKHI, - .length = sizeof(mkhi) + sizeof(rule_id), - }; - - /* Send request and wait for response */ - if (mei_sendrecv(&mei, &mkhi, &rule_id, &cap, sizeof(cap)) < 0) { - printk(BIOS_ERR, "ME: GET FWCAPS message failed\n"); - return -1; - } - - print_cap("Full Network manageability", cap.caps_sku.full_net); - print_cap("Regular Network manageability", cap.caps_sku.std_net); - print_cap("Manageability", cap.caps_sku.manageability); - print_cap("Small business technology", cap.caps_sku.small_business); - print_cap("Level III manageability", cap.caps_sku.l3manageability); - print_cap("IntelR Anti-Theft (AT)", cap.caps_sku.intel_at); - print_cap("IntelR Capability Licensing Service (CLS)", - cap.caps_sku.intel_cls); - print_cap("IntelR Power Sharing Technology (MPC)", - cap.caps_sku.intel_mpc); - print_cap("ICC Over Clocking", cap.caps_sku.icc_over_clocking); - print_cap("Protected Audio Video Path (PAVP)", cap.caps_sku.pavp); - print_cap("IPV6", cap.caps_sku.ipv6); - print_cap("KVM Remote Control (KVM)", cap.caps_sku.kvm); - print_cap("Outbreak Containment Heuristic (OCH)", cap.caps_sku.och); - print_cap("Virtual LAN (VLAN)", cap.caps_sku.vlan); - print_cap("TLS", cap.caps_sku.tls); - print_cap("Wireless LAN (WLAN)", cap.caps_sku.wlan); - - return 0; -} -#endif -#if CONFIG_CHROMEOS && 0 /* DISABLED */ -/* Tell ME to issue a global reset */ -int mkhi_global_reset(void) -{ - struct me_global_reset reset = { - .request_origin = GLOBAL_RESET_BIOS_POST, - .reset_type = CBM_RR_GLOBAL_RESET, - }; - struct mkhi_header mkhi = { - .group_id = MKHI_GROUP_ID_CBM, - .command = MKHI_GLOBAL_RESET, - }; - struct mei_header mei = { - .is_complete = 1, - .length = sizeof(mkhi) + sizeof(reset), - .host_address = MEI_HOST_ADDRESS, - .client_address = MEI_ADDRESS_MKHI, - }; - - printk(BIOS_NOTICE, "ME: Requesting global reset\n"); - - /* Send request and wait for response */ - if (mei_sendrecv(&mei, &mkhi, &reset, NULL, 0) < 0) { - /* No response means reset will happen shortly... */ - hlt(); - } - - /* If the ME responded it rejected the reset request */ - printk(BIOS_ERR, "ME: Global Reset failed\n"); - return -1; -} -#endif - -#ifdef __SMM__ static void intel_me7_finalize_smm(void) { struct me_hfs hfs; @@ -723,13 +605,6 @@ static void intel_me_init(device_t dev) if (intel_mei_setup(dev) < 0) break; -#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) && (CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) - /* Print ME firmware version */ - mkhi_get_fw_version(); - /* Print ME firmware capabilities */ - mkhi_get_fwcaps(); -#endif - /* * Leave the ME unlocked in this path. * It will be locked via SMI command later. diff --git a/src/southbridge/intel/ibexpeak/smi.c b/src/southbridge/intel/ibexpeak/smi.c index 981be3b..2ce9072 100644 --- a/src/southbridge/intel/ibexpeak/smi.c +++ b/src/southbridge/intel/ibexpeak/smi.c @@ -31,13 +31,7 @@ #include <string.h> #include "pch.h" -#if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE -#include "northbridge/intel/sandybridge/sandybridge.h" -#endif - -#if CONFIG_NORTHBRIDGE_INTEL_NEHALEM #include "northbridge/intel/nehalem/nehalem.h" -#endif extern unsigned char _binary_smm_start; extern unsigned char _binary_smm_end; diff --git a/src/southbridge/intel/ibexpeak/usb_ehci.c b/src/southbridge/intel/ibexpeak/usb_ehci.c index 21a257f..ea767c4 100644 --- a/src/southbridge/intel/ibexpeak/usb_ehci.c +++ b/src/southbridge/intel/ibexpeak/usb_ehci.c @@ -30,6 +30,8 @@ static void usb_ehci_init(struct device *dev) { u32 reg32; + struct resource *res; + u8 access_cntl; /* Disable Wake on Disconnect in RMH */ reg32 = RCBA32(0x35b0); @@ -50,6 +52,21 @@ static void usb_ehci_init(struct device *dev) //reg32 |= PCI_COMMAND_SERR; pci_write_config32(dev, PCI_COMMAND, reg32); + access_cntl = pci_read_config8(dev, 0x80); + + /* Enable writes to protected registers. */ + pci_write_config8(dev, 0x80, access_cntl | 1); + + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res) { + /* Number of ports and companion controllers. */ + reg32 = read32(res->base + 4); + write32(res->base + 4, (reg32 & 0xfff00000) | 3); + } + + /* Restore protection. */ + pci_write_config8(dev, 0x80, access_cntl); + printk(BIOS_DEBUG, "done.\n"); }
1
0
0
0
← Newer
1
2
3
4
5
6
...
107
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
Results per page:
10
25
50
100
200