Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/20985
Change subject: drvs/ec/lenovo/h8: Add ssdt generator ......................................................................
drvs/ec/lenovo/h8: Add ssdt generator
Add SSDT generator to add dynamic ACPI code. Implement GBDC and SBDC for thinkpad_acpi kernel module.
Tested on Lenovo T430: The bluetooth module is detected and can be powercycled using network manager.
Change-Id: Ida825196650966194a883945896a038b0790fe45 Signed-off-by: Patrick Rudolph siro@das-labor.org --- M src/ec/lenovo/h8/Makefile.inc M src/ec/lenovo/h8/h8.c M src/ec/lenovo/h8/h8.h A src/ec/lenovo/h8/ssdt.c 4 files changed, 136 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/85/20985/1
diff --git a/src/ec/lenovo/h8/Makefile.inc b/src/ec/lenovo/h8/Makefile.inc index a02543a..5c85e6f 100644 --- a/src/ec/lenovo/h8/Makefile.inc +++ b/src/ec/lenovo/h8/Makefile.inc @@ -3,6 +3,7 @@ ramstage-y += h8.c ramstage-y += bluetooth.c ramstage-y += wwan.c +ramstage-$(CONFIG_HAVE_ACPI_TABLES) += ssdt.c smm-y += smm.c
endif diff --git a/src/ec/lenovo/h8/h8.c b/src/ec/lenovo/h8/h8.c index 882ac02..8b8f49f 100644 --- a/src/ec/lenovo/h8/h8.c +++ b/src/ec/lenovo/h8/h8.c @@ -181,10 +181,21 @@ pc_keyboard_init(NO_AUX_DEVICE); }
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) +static const char* h8_acpi_name(struct device *dev) +{ + return "EC"; +} +#endif + struct device_operations h8_dev_ops = { #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLES) .get_smbios_strings = h8_smbios_strings, #endif +#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) + .acpi_fill_ssdt_generator = h8_ssdt_generator, + .acpi_name = h8_acpi_name, +#endif .init = h8_init, };
diff --git a/src/ec/lenovo/h8/h8.h b/src/ec/lenovo/h8/h8.h index 4175463..951d22f 100644 --- a/src/ec/lenovo/h8/h8.h +++ b/src/ec/lenovo/h8/h8.h @@ -39,6 +39,8 @@ bool h8_wwan_nv_enable(void); bool h8_has_wwan(struct device *dev);
+void h8_ssdt_generator(struct device *dev); + /* EC registers */ #define H8_CONFIG0 0x00 #define H8_CONFIG0_EVENTS_ENABLE 0x02 diff --git a/src/ec/lenovo/h8/ssdt.c b/src/ec/lenovo/h8/ssdt.c new file mode 100644 index 0000000..eb9f2c1 --- /dev/null +++ b/src/ec/lenovo/h8/ssdt.c @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Patrick Rudolph siro@das-labor.org + * + * 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. + */ + +#include <southbridge/intel/common/gpio.h> +#include <console/console.h> +#include <device/device.h> +#include <ec/acpi/ec.h> +#include <arch/acpigen.h> +#include <option.h> +#include <string.h> + +#include "h8.h" +#include "chip.h" + +static char *h8_dsdt_scope(struct device *dev, const char *scope) +{ + static char buf[DEVICE_PATH_MAX] = {}; + const char *path = acpi_device_path(dev); + + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "%s.%s", path, scope); + + return buf; +} + +/* Generate ACPI methods GBDC and SBDC */ +static void h8_dsdt_bluetooth(struct device *dev) +{ + const bool has_bdc = h8_has_bdc(dev); + + /* Method (GBDC, 0) */ + acpigen_write_method("GBDC", 0); + /* Store(Zero, Local0) */ + acpigen_write_store_ops(ZERO_OP, LOCAL0_OP); + if (has_bdc) { + /* BDC present */ + /* Or(Local0, One, Local0) */ + acpigen_write_or(LOCAL0_OP, ONE_OP, LOCAL0_OP); + + /* If(LEqual(_SB.PCI0.LPCB.EC.BTEB, One)) */ + acpigen_write_if(); + acpigen_emit_byte(LEQUAL_OP); + acpigen_emit_namestring(h8_dsdt_scope(dev, "BTEB")); + acpigen_emit_byte(ONE_OP); + + /* Or(Local0, 2, Local0) */ + acpigen_emit_byte(OR_OP); + acpigen_emit_byte(LOCAL0_OP); + acpigen_write_integer(2); + acpigen_emit_byte(LOCAL0_OP); + acpigen_pop_len(); /* If */ + + /* State at resume: Enabled */ + /* Or(Local0, 4, Local0) */ + acpigen_emit_byte(OR_OP); + acpigen_emit_byte(LOCAL0_OP); + acpigen_write_integer(4); + acpigen_emit_byte(LOCAL0_OP); + } + /* Return(Local0) */ + acpigen_emit_byte(RETURN_OP); + acpigen_emit_byte(LOCAL0_OP); + acpigen_pop_len(); /* Method */ + + /* Method (SBDC, 0) */ + acpigen_write_method("SBDC", 1); + if (has_bdc) { + /* And(Arg0, 2, Local0) */ + acpigen_emit_byte(AND_OP); + acpigen_emit_byte(ARG0_OP); + acpigen_write_integer(2); + acpigen_emit_byte(LOCAL0_OP); + /* If(Lequal(Local0, 2)) */ + acpigen_write_if_lequal_op_int(LOCAL0_OP, 2); + /* Store(One, _SB.PCI0.LPCB.EC.BTEB) */ + acpigen_write_store(); + acpigen_emit_byte(ONE_OP); + acpigen_emit_namestring(h8_dsdt_scope(dev, "BTEB")); + acpigen_pop_len(); /* If */ + /* Else */ + acpigen_write_else(); + /* Store(Zero, _SB.PCI0.LPCB.EC.BTEB) */ + acpigen_write_store(); + acpigen_emit_byte(ZERO_OP); + acpigen_emit_namestring(h8_dsdt_scope(dev, "BTEB")); + acpigen_pop_len(); /* Else */ + + /* FIXME: Implement state at resume */ + } + acpigen_pop_len(); /* Method */ +} + +/* + * Generates EC SSDT. + */ +void h8_ssdt_generator(struct device *dev) +{ + if (!acpi_device_path(dev)) + return; + + printk(BIOS_INFO, "ACPI: * H8\n"); + + /* Scope HKEY */ + acpigen_write_scope(h8_dsdt_scope(dev, "HKEY")); + + /* Used by thinkpad_acpi */ + h8_dsdt_bluetooth(dev); + + acpigen_pop_len(); /* Scope HKEY */ +}