Selaa lähdekoodia

Merge branch 'next' of https://gitlab.denx.de/u-boot/custodians/u-boot-x86 into next

- Enhance the 'zboot' command to be more like 'bootm' with sub-commands
- The last series of ACPI core changes for programmatic generation of
  ACPI tables
- Add all required ACPI tables for ApolloLake and enable ACPIGEN on
  Chromebook Coral
- A feature minor enhancements to the 'hob' command
- Intel edison: Support for writing an xFSTK image via binman
Tom Rini 3 vuotta sitten
vanhempi
commit
0ac83d080a
100 muutettua tiedostoa jossa 7688 lisäystä ja 178 poistoa
  1. 4 0
      README
  2. 47 0
      arch/x86/Kconfig
  3. 4 0
      arch/x86/cpu/apollolake/Kconfig
  4. 1 0
      arch/x86/cpu/apollolake/Makefile
  5. 211 0
      arch/x86/cpu/apollolake/acpi.c
  6. 77 0
      arch/x86/cpu/apollolake/cpu.c
  7. 2 0
      arch/x86/cpu/apollolake/fsp_s.c
  8. 236 7
      arch/x86/cpu/apollolake/hostbridge.c
  9. 18 0
      arch/x86/cpu/apollolake/lpc.c
  10. 2 6
      arch/x86/cpu/apollolake/pmc.c
  11. 15 0
      arch/x86/cpu/cpu.c
  12. 23 0
      arch/x86/cpu/i386/cpu.c
  13. 7 0
      arch/x86/cpu/intel_common/Makefile
  14. 377 0
      arch/x86/cpu/intel_common/acpi.c
  15. 79 0
      arch/x86/cpu/intel_common/cpu.c
  16. 120 0
      arch/x86/cpu/intel_common/generic_wifi.c
  17. 168 0
      arch/x86/cpu/intel_common/intel_opregion.c
  18. 19 5
      arch/x86/cpu/mtrr.c
  19. 1 0
      arch/x86/cpu/tangier/Kconfig
  20. 5 0
      arch/x86/cpu/x86_64/cpu.c
  21. 212 14
      arch/x86/dts/chromebook_coral.dts
  22. 34 0
      arch/x86/dts/edison.dts
  23. 7 9
      arch/x86/dts/emulation-u-boot.dtsi
  24. 3 5
      arch/x86/dts/quark-u-boot.dtsi
  25. 0 7
      arch/x86/dts/u-boot.dtsi
  26. 108 0
      arch/x86/include/asm/acpi/chromeos.asl
  27. 25 0
      arch/x86/include/asm/acpi/cpu.asl
  28. 22 0
      arch/x86/include/asm/acpi/cros_ec/ac.asl
  29. 56 0
      arch/x86/include/asm/acpi/cros_ec/als.asl
  30. 411 0
      arch/x86/include/asm/acpi/cros_ec/battery.asl
  31. 57 0
      arch/x86/include/asm/acpi/cros_ec/cros_ec.asl
  32. 557 0
      arch/x86/include/asm/acpi/cros_ec/ec.asl
  33. 53 0
      arch/x86/include/asm/acpi/cros_ec/emem.asl
  34. 52 0
      arch/x86/include/asm/acpi/cros_ec/keyboard_backlight.asl
  35. 15 0
      arch/x86/include/asm/acpi/cros_ec/pd.asl
  36. 159 0
      arch/x86/include/asm/acpi/cros_ec/superio.asl
  37. 23 0
      arch/x86/include/asm/acpi/cros_ec/tbmc.asl
  38. 29 0
      arch/x86/include/asm/acpi/cros_gnvs.asl
  39. 65 0
      arch/x86/include/asm/acpi/dptf/charger.asl
  40. 186 0
      arch/x86/include/asm/acpi/dptf/cpu.asl
  41. 121 0
      arch/x86/include/asm/acpi/dptf/dptf.asl
  42. 57 0
      arch/x86/include/asm/acpi/dptf/fan.asl
  43. 521 0
      arch/x86/include/asm/acpi/dptf/thermal.asl
  44. 4 1
      arch/x86/include/asm/acpi/global_nvs.h
  45. 141 0
      arch/x86/include/asm/acpi/lpc.asl
  46. 21 0
      arch/x86/include/asm/acpi/pci_osc.asl
  47. 80 0
      arch/x86/include/asm/acpi/pcr.asl
  48. 32 0
      arch/x86/include/asm/acpi/ramoops.asl
  49. 7 5
      arch/x86/include/asm/acpi/sleepstates.asl
  50. 162 0
      arch/x86/include/asm/acpi_table.h
  51. 35 0
      arch/x86/include/asm/acpigen.h
  52. 18 0
      arch/x86/include/asm/arch-apollolake/acpi.h
  53. 35 0
      arch/x86/include/asm/arch-apollolake/acpi/dptf.asl
  54. 41 0
      arch/x86/include/asm/arch-apollolake/acpi/globalnvs.asl
  55. 191 0
      arch/x86/include/asm/arch-apollolake/acpi/gpio.asl
  56. 109 0
      arch/x86/include/asm/arch-apollolake/acpi/gpiolib.asl
  57. 105 0
      arch/x86/include/asm/arch-apollolake/acpi/lpss.asl
  58. 120 0
      arch/x86/include/asm/arch-apollolake/acpi/northbridge.asl
  59. 77 0
      arch/x86/include/asm/arch-apollolake/acpi/pch_hda.asl
  60. 52 0
      arch/x86/include/asm/arch-apollolake/acpi/pci_irqs.asl
  61. 22 0
      arch/x86/include/asm/arch-apollolake/acpi/pcie.asl
  62. 113 0
      arch/x86/include/asm/arch-apollolake/acpi/pcie_port.asl
  63. 10 0
      arch/x86/include/asm/arch-apollolake/acpi/platform.asl
  64. 49 0
      arch/x86/include/asm/arch-apollolake/acpi/pmc_ipc.asl
  65. 173 0
      arch/x86/include/asm/arch-apollolake/acpi/scs.asl
  66. 50 0
      arch/x86/include/asm/arch-apollolake/acpi/soc_int.asl
  67. 34 0
      arch/x86/include/asm/arch-apollolake/acpi/southbridge.asl
  68. 33 0
      arch/x86/include/asm/arch-apollolake/acpi/xhci.asl
  69. 23 0
      arch/x86/include/asm/arch-apollolake/acpi/xhci_apl_ports.asl
  70. 24 0
      arch/x86/include/asm/arch-apollolake/acpi/xhci_glk_ports.asl
  71. 1 22
      arch/x86/include/asm/arch-apollolake/global_nvs.h
  72. 135 0
      arch/x86/include/asm/arch-apollolake/gpe.h
  73. 3 0
      arch/x86/include/asm/arch-apollolake/gpio.h
  74. 16 0
      arch/x86/include/asm/arch-apollolake/iomap.h
  75. 39 1
      arch/x86/include/asm/arch-apollolake/pm.h
  76. 31 0
      arch/x86/include/asm/arch-apollolake/systemagent.h
  77. 19 6
      arch/x86/include/asm/bootparam.h
  78. 9 0
      arch/x86/include/asm/cpu.h
  79. 56 0
      arch/x86/include/asm/cpu_common.h
  80. 2 2
      arch/x86/include/asm/e820.h
  81. 12 3
      arch/x86/include/asm/fsp/fsp_api.h
  82. 25 0
      arch/x86/include/asm/fsp/fsp_hob.h
  83. 52 0
      arch/x86/include/asm/intel_acpi.h
  84. 44 0
      arch/x86/include/asm/intel_gnvs.h
  85. 247 0
      arch/x86/include/asm/intel_opregion.h
  86. 12 3
      arch/x86/include/asm/mtrr.h
  87. 27 0
      arch/x86/include/asm/smm.h
  88. 29 1
      arch/x86/include/asm/zimage.h
  89. 1 0
      arch/x86/lib/Makefile
  90. 368 15
      arch/x86/lib/acpi_table.c
  91. 96 0
      arch/x86/lib/acpigen.c
  92. 1 1
      arch/x86/lib/bootm.c
  93. 16 0
      arch/x86/lib/fsp/fsp_common.c
  94. 17 0
      arch/x86/lib/fsp/fsp_dram.c
  95. 32 0
      arch/x86/lib/fsp/fsp_graphics.c
  96. 3 1
      arch/x86/lib/fsp2/fsp_silicon_init.c
  97. 14 8
      arch/x86/lib/fsp2/fsp_support.c
  98. 429 55
      arch/x86/lib/zimage.c
  99. 1 1
      board/google/chromebook_coral/Kconfig
  100. 1 0
      board/google/chromebook_coral/Makefile

+ 4 - 0
README

@@ -3425,6 +3425,10 @@ List of environment variables (most likely not complete):
   mempos	- Index position of the last match found by the 'ms' command,
 		  in units of the size (.b, .w, .l) of the search
 
+  zbootbase	- (x86 only) Base address of the bzImage 'setup' block
+
+  zbootaddr	- (x86 only) Address of the loaded bzImage, typically
+		  BZIMAGE_LOAD_ADDR which is 0x100000
 
 The following image location variables contain the location of images
 used in booting. The "Image" column gives the role of the image and is

+ 47 - 0
arch/x86/Kconfig

@@ -788,6 +788,13 @@ config GENERATE_ACPI_TABLE
 	  by the operating system. It defines platform-independent interfaces
 	  for configuration and power management monitoring.
 
+config ACPI_GNVS_EXTERNAL
+	bool
+	help
+	  Put the GNVS (Global Non-Volatile Sleeping) table separate from the
+	  DSDT and add a pointer to the table from the DSDT. This allows
+	  U-Boot to better control the address of the GNVS.
+
 endmenu
 
 config HAVE_ACPI_RESUME
@@ -976,4 +983,44 @@ config TPL_ACPI_GPE
 
 	  See https://queue.acm.org/blogposting.cfm?id=18977 for more info
 
+config SA_PCIEX_LENGTH
+	hex
+	default 0x10000000 if (PCIEX_LENGTH_256MB)
+	default 0x8000000 if (PCIEX_LENGTH_128MB)
+	default 0x4000000 if (PCIEX_LENGTH_64MB)
+	default 0x10000000
+	help
+	  This option allows you to select length of PCIEX region.
+
+config PCIEX_LENGTH_256MB
+	bool
+
+config PCIEX_LENGTH_128MB
+	bool
+
+config PCIEX_LENGTH_64MB
+	bool
+
+config INTEL_GMA_ACPI
+	bool "Generate ACPI table for Intel GMA graphics"
+	help
+	  The Intel GMA graphics driver in Linux expects an ACPI table
+	  which describes the layout of the registers and the display
+	  connected to the device. Enable this option to create this
+	  table so that graphics works correctly.
+
+config INTEL_GENERIC_WIFI
+	bool "Enable generation of ACPI tables for Intel WiFi"
+	help
+	  Select this option to provide code to a build generic WiFi ACPI table
+	  for Intel WiFi devices. This is not a WiFi driver and offers no
+	  network functionality. It is only here to generate the ACPI tables
+	  required by Linux.
+
+config INTEL_GMA_SWSMISCI
+	bool
+	help
+	  Select this option for Atom-based platforms which use the SWSMISCI
+	  register (0xe0) rather than the SWSCI register (0xe8).
+
 endmenu

+ 4 - 0
arch/x86/cpu/apollolake/Kconfig

@@ -13,9 +13,12 @@ config INTEL_APOLLOLAKE
 	select TPL_X86_TSC_TIMER_NATIVE
 	select SPL_PCH_SUPPORT
 	select TPL_PCH_SUPPORT
+	select PCIEX_LENGTH_256MB
 	select PCH_SUPPORT
 	select P2SB
 	select SMP_AP_WORK
+	select INTEL_GMA_SWSMISCI
+	select ACPI_GNVS_EXTERNAL
 	imply ENABLE_MRC_CACHE
 	imply AHCI_PCI
 	imply SCSI
@@ -46,6 +49,7 @@ config INTEL_APOLLOLAKE
 	imply CMD_CLK
 	imply CLK_INTEL
 	imply ACPI_GPE
+	imply INTEL_GMA_ACPI
 
 if INTEL_APOLLOLAKE
 

+ 1 - 0
arch/x86/cpu/apollolake/Makefile

@@ -16,6 +16,7 @@ obj-y += fsp_m.o
 endif
 endif
 ifndef CONFIG_SPL_BUILD
+obj-y += acpi.o
 obj-y += fsp_s.o
 endif
 

+ 211 - 0
arch/x86/cpu/apollolake/acpi.c

@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Intel Corp.
+ * Copyright (C) 2017-2019 Siemens AG
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot apollolake/acpi.c
+ */
+
+#define LOG_CATEGORY LOGC_ACPI
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <log.h>
+#include <p2sb.h>
+#include <pci.h>
+#include <acpi/acpigen.h>
+#include <acpi/acpi_s3.h>
+#include <asm/acpi_table.h>
+#include <asm/cpu_common.h>
+#include <asm/intel_acpi.h>
+#include <asm/intel_gnvs.h>
+#include <asm/intel_pinctrl.h>
+#include <asm/intel_pinctrl_defs.h>
+#include <asm/intel_regs.h>
+#include <asm/io.h>
+#include <asm/mpspec.h>
+#include <asm/tables.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/systemagent.h>
+#include <dm/acpi.h>
+#include <dm/uclass-internal.h>
+#include <power/acpi_pmc.h>
+
+int arch_read_sci_irq_select(void)
+{
+	struct acpi_pmc_upriv *upriv;
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_ACPI_PMC, &dev);
+	if (ret)
+		return log_msg_ret("pmc", ret);
+	upriv = dev_get_uclass_priv(dev);
+
+	return readl(upriv->pmc_bar0 + IRQ_REG);
+}
+
+int arch_write_sci_irq_select(uint scis)
+{
+	struct acpi_pmc_upriv *upriv;
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_ACPI_PMC, &dev);
+	if (ret)
+		return log_msg_ret("pmc", ret);
+	upriv = dev_get_uclass_priv(dev);
+	writel(scis, upriv->pmc_bar0 + IRQ_REG);
+
+	return 0;
+}
+
+int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+	struct udevice *cpu;
+	int ret;
+
+	/* Clear out GNV */
+	memset(gnvs, '\0', sizeof(*gnvs));
+
+	/* TODO(sjg@chromium.org): Add the console log to gnvs->cbmc */
+
+#ifdef CONFIG_CHROMEOS
+	/* Initialise Verified Boot data */
+	chromeos_init_acpi(&gnvs->chromeos);
+	gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO;
+#endif
+	/* Set unknown wake source */
+	gnvs->pm1i = ~0ULL;
+
+	/* CPU core count */
+	gnvs->pcnt = 1;
+	ret = uclass_find_first_device(UCLASS_CPU, &cpu);
+	if (cpu) {
+		ret = cpu_get_count(cpu);
+		if (ret > 0)
+			gnvs->pcnt = ret;
+	}
+
+	return 0;
+}
+
+uint32_t acpi_fill_soc_wake(uint32_t generic_pm1_en)
+{
+	/*
+	 * WAK_STS bit is set when the system is in one of the sleep states
+	 * (via the SLP_EN bit) and an enabled wake event occurs. Upon setting
+	 * this bit, the PMC will transition the system to the ON state and
+	 * can only be set by hardware and can only be cleared by writing a one
+	 * to this bit position.
+	 */
+	generic_pm1_en |= WAK_STS | RTC_EN | PWRBTN_EN;
+
+	return generic_pm1_en;
+}
+
+int arch_madt_sci_irq_polarity(int sci)
+{
+	return MP_IRQ_POLARITY_LOW;
+}
+
+void fill_fadt(struct acpi_fadt *fadt)
+{
+	fadt->pm_tmr_blk = IOMAP_ACPI_BASE + PM1_TMR;
+
+	fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
+	fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
+
+	fadt->pm_tmr_len = 4;
+	fadt->duty_width = 3;
+
+	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
+
+	fadt->x_pm_tmr_blk.space_id = 1;
+	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
+	fadt->x_pm_tmr_blk.addrl = IOMAP_ACPI_BASE + PM1_TMR;
+}
+
+void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
+		      void *dsdt)
+{
+	struct acpi_table_header *header = &fadt->header;
+
+	acpi_fadt_common(fadt, facs, dsdt);
+	intel_acpi_fill_fadt(fadt);
+	fill_fadt(fadt);
+	header->checksum = table_compute_checksum(fadt, header->length);
+}
+
+int apl_acpi_fill_dmar(struct acpi_ctx *ctx)
+{
+	struct udevice *dev, *sa_dev;
+	u64 gfxvtbar = readq(MCHBAR_REG(GFXVTBAR)) & VTBAR_MASK;
+	u64 defvtbar = readq(MCHBAR_REG(DEFVTBAR)) & VTBAR_MASK;
+	bool gfxvten = readl(MCHBAR_REG(GFXVTBAR)) & VTBAR_ENABLED;
+	bool defvten = readl(MCHBAR_REG(DEFVTBAR)) & VTBAR_ENABLED;
+	void *tmp;
+	int ret;
+
+	uclass_find_first_device(UCLASS_VIDEO, &dev);
+	ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa_dev);
+	if (ret)
+		return log_msg_ret("no sa", ret);
+
+	/* IGD has to be enabled, GFXVTBAR set and enabled */
+	if (dev && device_active(dev) && gfxvtbar && gfxvten) {
+		tmp = ctx->current;
+
+		acpi_create_dmar_drhd(ctx, 0, 0, gfxvtbar);
+		ret = acpi_create_dmar_ds_pci(ctx, PCI_BDF(0, 2, 0));
+		if (ret)
+			return log_msg_ret("ds_pci", ret);
+		acpi_dmar_drhd_fixup(ctx, tmp);
+
+		/* Add RMRR entry */
+		tmp = ctx->current;
+		acpi_create_dmar_rmrr(ctx->current, 0, sa_get_gsm_base(sa_dev),
+				      sa_get_tolud_base(sa_dev) - 1);
+		acpi_create_dmar_ds_pci(ctx->current, PCI_BDF(0, 2, 0));
+		acpi_dmar_rmrr_fixup(ctx, tmp);
+	}
+
+	/* DEFVTBAR has to be set and enabled */
+	if (defvtbar && defvten) {
+		struct udevice *p2sb_dev;
+		u16 ibdf, hbdf;
+		uint ioapic, hpet;
+		int ret;
+
+		tmp = ctx->current;
+		/*
+		 * P2SB may already be hidden. There's no clear rule, when.
+		 * It is needed to get bus, device and function for IOAPIC and
+		 * HPET device which is stored in P2SB device. So unhide it to
+		 * get the info and hide it again when done.
+		 *
+		 * TODO(sjg@chromium.org): p2sb_unhide() ?
+		 */
+		ret = uclass_first_device_err(UCLASS_P2SB, &p2sb_dev);
+		if (ret)
+			return log_msg_ret("p2sb", ret);
+
+		dm_pci_read_config16(p2sb_dev, PCH_P2SB_IBDF, &ibdf);
+		ioapic = PCI_TO_BDF(ibdf);
+		dm_pci_read_config16(p2sb_dev, PCH_P2SB_HBDF, &hbdf);
+		hpet = PCI_TO_BDF(hbdf);
+		/* TODO(sjg@chromium.org): p2sb_hide() ? */
+
+		acpi_create_dmar_drhd(ctx, DRHD_INCLUDE_PCI_ALL, 0, defvtbar);
+		acpi_create_dmar_ds_ioapic(ctx, 2, ioapic);
+		acpi_create_dmar_ds_msi_hpet(ctx, 0, hpet);
+		acpi_dmar_drhd_fixup(tmp, ctx->current);
+	}
+
+	return 0;
+}

+ 77 - 0
arch/x86/cpu/apollolake/cpu.c

@@ -6,14 +6,90 @@
 #include <common.h>
 #include <cpu.h>
 #include <dm.h>
+#include <log.h>
+#include <acpi/acpigen.h>
+#include <acpi/acpi_table.h>
 #include <asm/cpu_common.h>
 #include <asm/cpu_x86.h>
+#include <asm/intel_acpi.h>
+#include <asm/msr.h>
+#include <dm/acpi.h>
+
+#define CSTATE_RES(address_space, width, offset, address)		\
+	{								\
+	.space_id = address_space,					\
+	.bit_width = width,						\
+	.bit_offset = offset,						\
+	.addrl = address,						\
+	}
+
+static struct acpi_cstate cstate_map[] = {
+	{
+		/* C1 */
+		.ctype = 1,		/* ACPI C1 */
+		.latency = 1,
+		.power = 1000,
+		.resource = {
+			.space_id = ACPI_ADDRESS_SPACE_FIXED,
+		},
+	}, {
+		.ctype = 2,		/* ACPI C2 */
+		.latency = 50,
+		.power = 10,
+		.resource = {
+			.space_id = ACPI_ADDRESS_SPACE_IO,
+			.bit_width = 8,
+			.addrl = 0x415,
+		},
+	}, {
+		.ctype = 3,		/* ACPI C3 */
+		.latency = 150,
+		.power = 10,
+		.resource = {
+			.space_id = ACPI_ADDRESS_SPACE_IO,
+			.bit_width = 8,
+			.addrl = 0x419,
+		},
+	},
+};
 
 static int apl_get_info(const struct udevice *dev, struct cpu_info *info)
 {
 	return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
 }
 
+static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+	uint core_id = dev->req_seq;
+	int cores_per_package;
+	int ret;
+
+	cores_per_package = cpu_get_cores_per_package();
+	ret = acpi_generate_cpu_header(ctx, core_id, cstate_map,
+				       ARRAY_SIZE(cstate_map));
+
+	/* Generate P-state tables */
+	generate_p_state_entries(ctx, core_id, cores_per_package);
+
+	/* Generate T-state tables */
+	generate_t_state_entries(ctx, core_id, cores_per_package, NULL, 0);
+
+	acpigen_pop_len(ctx);
+
+	if (device_is_last_sibling(dev)) {
+		ret = acpi_generate_cpu_package_final(ctx, cores_per_package);
+
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+struct acpi_ops apl_cpu_acpi_ops = {
+	.fill_ssdt	= acpi_cpu_fill_ssdt,
+};
+
 static const struct cpu_ops cpu_x86_apl_ops = {
 	.get_desc	= cpu_x86_get_desc,
 	.get_info	= apl_get_info,
@@ -32,5 +108,6 @@ U_BOOT_DRIVER(cpu_x86_apl_drv) = {
 	.of_match	= cpu_x86_apl_ids,
 	.bind		= cpu_x86_bind,
 	.ops		= &cpu_x86_apl_ops,
+	ACPI_OPS_PTR(&apl_cpu_acpi_ops)
 	.flags		= DM_FLAG_PRE_RELOC,
 };

+ 2 - 0
arch/x86/cpu/apollolake/fsp_s.c

@@ -157,6 +157,8 @@ int arch_fsps_preinit(void)
 	struct udevice *itss;
 	int ret;
 
+	if (!ll_boot_init())
+		return 0;
 	ret = irq_first_device_type(X86_IRQT_ITSS, &itss);
 	if (ret)
 		return log_msg_ret("no itss", ret);

+ 236 - 7
arch/x86/cpu/apollolake/hostbridge.c

@@ -1,17 +1,45 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright 2019 Google LLC
+ * Copyright (C) 2015 - 2017 Intel Corp.
+ * Copyright (C) 2017 - 2019 Siemens AG
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
+ * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
+ *
+ * Portions from coreboot soc/intel/apollolake/chip.c
  */
 
+#define LOG_CATEGORY UCLASS_NORTHBRIDGE
+
 #include <common.h>
 #include <dm.h>
 #include <dt-structs.h>
 #include <log.h>
 #include <spl.h>
+#include <tables_csum.h>
+#include <acpi/acpi_table.h>
+#include <asm/acpi_nhlt.h>
 #include <asm/intel_pinctrl.h>
 #include <asm/intel_regs.h>
+#include <asm/io.h>
 #include <asm/pci.h>
+#include <asm/arch/acpi.h>
 #include <asm/arch/systemagent.h>
+#include <dt-bindings/sound/nhlt.h>
+#include <dm/acpi.h>
+
+enum {
+	PCIEXBAR		= 0x60,
+	PCIEXBAR_LENGTH_256MB	= 0,
+	PCIEXBAR_LENGTH_128MB,
+	PCIEXBAR_LENGTH_64MB,
+
+	PCIEXBAR_PCIEXBAREN	= 1 << 0,
+
+	BGSM			= 0xb4,  /* Base GTT Stolen Memory */
+	TSEG			= 0xb8,  /* TSEG base */
+	TOLUD			= 0xbc,
+};
 
 /**
  * struct apl_hostbridge_platdata - platform data for hostbridge
@@ -32,15 +60,100 @@ struct apl_hostbridge_platdata {
 	pci_dev_t bdf;
 };
 
-enum {
-	PCIEXBAR		= 0x60,
-	PCIEXBAR_LENGTH_256MB	= 0,
-	PCIEXBAR_LENGTH_128MB,
-	PCIEXBAR_LENGTH_64MB,
+static const struct nhlt_format_config dmic_1ch_formats[] = {
+	/* 48 KHz 16-bits per sample. */
+	{
+		.num_channels = 1,
+		.sample_freq_khz = 48,
+		.container_bits_per_sample = 16,
+		.valid_bits_per_sample = 16,
+		.settings_file = "dmic-1ch-48khz-16b.dat",
+	},
+};
 
-	PCIEXBAR_PCIEXBAREN	= 1 << 0,
+static const struct nhlt_dmic_array_config dmic_1ch_mic_config = {
+	.tdm_config = {
+		.config_type = NHLT_TDM_MIC_ARRAY,
+	},
+	.array_type = NHLT_MIC_ARRAY_VENDOR_DEFINED,
+};
 
-	TSEG			= 0xb8,  /* TSEG base */
+static const struct nhlt_endp_descriptor dmic_1ch_descriptors[] = {
+	{
+		.link = NHLT_LINK_PDM,
+		.device = NHLT_PDM_DEV,
+		.direction = NHLT_DIR_CAPTURE,
+		.vid = NHLT_VID,
+		.did = NHLT_DID_DMIC,
+		.cfg = &dmic_1ch_mic_config,
+		.cfg_size = sizeof(dmic_1ch_mic_config),
+		.formats = dmic_1ch_formats,
+		.num_formats = ARRAY_SIZE(dmic_1ch_formats),
+	},
+};
+
+static const struct nhlt_format_config dmic_2ch_formats[] = {
+	/* 48 KHz 16-bits per sample. */
+	{
+		.num_channels = 2,
+		.sample_freq_khz = 48,
+		.container_bits_per_sample = 16,
+		.valid_bits_per_sample = 16,
+		.settings_file = "dmic-2ch-48khz-16b.dat",
+	},
+};
+
+static const struct nhlt_dmic_array_config dmic_2ch_mic_config = {
+	.tdm_config = {
+		.config_type = NHLT_TDM_MIC_ARRAY,
+	},
+	.array_type = NHLT_MIC_ARRAY_2CH_SMALL,
+};
+
+static const struct nhlt_endp_descriptor dmic_2ch_descriptors[] = {
+	{
+		.link = NHLT_LINK_PDM,
+		.device = NHLT_PDM_DEV,
+		.direction = NHLT_DIR_CAPTURE,
+		.vid = NHLT_VID,
+		.did = NHLT_DID_DMIC,
+		.cfg = &dmic_2ch_mic_config,
+		.cfg_size = sizeof(dmic_2ch_mic_config),
+		.formats = dmic_2ch_formats,
+		.num_formats = ARRAY_SIZE(dmic_2ch_formats),
+	},
+};
+
+static const struct nhlt_format_config dmic_4ch_formats[] = {
+	/* 48 KHz 16-bits per sample. */
+	{
+		.num_channels = 4,
+		.sample_freq_khz = 48,
+		.container_bits_per_sample = 16,
+		.valid_bits_per_sample = 16,
+		.settings_file = "dmic-4ch-48khz-16b.dat",
+	},
+};
+
+static const struct nhlt_dmic_array_config dmic_4ch_mic_config = {
+	.tdm_config = {
+		.config_type = NHLT_TDM_MIC_ARRAY,
+	},
+	.array_type = NHLT_MIC_ARRAY_4CH_L_SHAPED,
+};
+
+static const struct nhlt_endp_descriptor dmic_4ch_descriptors[] = {
+	{
+		.link = NHLT_LINK_PDM,
+		.device = NHLT_PDM_DEV,
+		.direction = NHLT_DIR_CAPTURE,
+		.vid = NHLT_VID,
+		.did = NHLT_DID_DMIC,
+		.cfg = &dmic_4ch_mic_config,
+		.cfg_size = sizeof(dmic_4ch_mic_config),
+		.formats = dmic_4ch_formats,
+		.num_formats = ARRAY_SIZE(dmic_4ch_formats),
+	},
 };
 
 static int apl_hostbridge_early_init_pinctrl(struct udevice *dev)
@@ -165,6 +278,119 @@ static int apl_hostbridge_probe(struct udevice *dev)
 	return 0;
 }
 
+static int apl_acpi_hb_get_name(const struct udevice *dev, char *out_name)
+{
+	return acpi_copy_name(out_name, "RHUB");
+}
+
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+static int apl_acpi_hb_write_tables(const struct udevice *dev,
+				    struct acpi_ctx *ctx)
+{
+	struct acpi_table_header *header;
+	struct acpi_dmar *dmar;
+	u32 val;
+
+	/*
+	 * Create DMAR table only if virtualization is enabled. Due to some
+	 * constraints on Apollo Lake SoC (some stepping affected), VTD could
+	 * not be enabled together with IPU. Doing so will override and disable
+	 * VTD while leaving CAPID0_A still reporting that VTD is available.
+	 * As in this case FSP will lock VTD to disabled state, we need to make
+	 * sure that DMAR table generation only happens when at least DEFVTBAR
+	 * is enabled. Otherwise the DMAR header will be generated while the
+	 * content of the table will be missing.
+	 */
+	dm_pci_read_config32(dev, CAPID0_A, &val);
+	if ((val & VTD_DISABLE) ||
+	    !(readl(MCHBAR_REG(DEFVTBAR)) & VTBAR_ENABLED))
+		return 0;
+
+	log_debug("ACPI:    * DMAR\n");
+	dmar = (struct acpi_dmar *)ctx->current;
+	header = &dmar->header;
+	acpi_create_dmar(dmar, DMAR_INTR_REMAP);
+	ctx->current += sizeof(struct acpi_dmar);
+	apl_acpi_fill_dmar(ctx);
+
+	/* (Re)calculate length and checksum */
+	header->length = ctx->current - (void *)dmar;
+	header->checksum = table_compute_checksum((void *)dmar, header->length);
+
+	acpi_align(ctx);
+	acpi_add_table(ctx, dmar);
+
+	return 0;
+}
+#endif
+
+static int apl_acpi_setup_nhlt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+	struct nhlt *nhlt = ctx->nhlt;
+	u32 channels;
+	ofnode node;
+
+	node = ofnode_find_subnode(dev_ofnode(dev), "nhlt");
+	if (ofnode_read_u32(node, "intel,dmic-channels", &channels))
+		return log_msg_ret("channels", -EINVAL);
+	switch (channels) {
+	case 1:
+		return nhlt_add_endpoints(nhlt, dmic_1ch_descriptors,
+					  ARRAY_SIZE(dmic_1ch_descriptors));
+	case 2:
+		return nhlt_add_endpoints(nhlt, dmic_2ch_descriptors,
+					  ARRAY_SIZE(dmic_2ch_descriptors));
+	case 4:
+		return nhlt_add_endpoints(nhlt, dmic_4ch_descriptors,
+					  ARRAY_SIZE(dmic_4ch_descriptors));
+	}
+
+	return log_msg_ret("channels", -EINVAL);
+}
+
+static int apl_hostbridge_remove(struct udevice *dev)
+{
+	/*
+	 * TODO(sjg@chromium.org): Consider adding code from coreboot's
+	 * platform_fsp_notify_status()
+	 */
+
+	return 0;
+}
+
+static ulong sa_read_reg(struct udevice *dev, int reg)
+{
+	u32 val;
+
+	/* All regions concerned for have 1 MiB alignment */
+	dm_pci_read_config32(dev, BGSM, &val);
+
+	return ALIGN_DOWN(val, 1 << 20);
+}
+
+ulong sa_get_tolud_base(struct udevice *dev)
+{
+	return sa_read_reg(dev, TOLUD);
+}
+
+ulong sa_get_gsm_base(struct udevice *dev)
+{
+	return sa_read_reg(dev, BGSM);
+}
+
+ulong sa_get_tseg_base(struct udevice *dev)
+{
+	return sa_read_reg(dev, TSEG);
+}
+
+struct acpi_ops apl_hostbridge_acpi_ops = {
+	.get_name	= apl_acpi_hb_get_name,
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+	.write_tables	= apl_acpi_hb_write_tables,
+#endif
+	.setup_nhlt	= apl_acpi_setup_nhlt,
+};
+
 static const struct udevice_id apl_hostbridge_ids[] = {
 	{ .compatible = "intel,apl-hostbridge" },
 	{ }
@@ -176,5 +402,8 @@ U_BOOT_DRIVER(apl_hostbridge_drv) = {
 	.of_match	= apl_hostbridge_ids,
 	.ofdata_to_platdata = apl_hostbridge_ofdata_to_platdata,
 	.probe		= apl_hostbridge_probe,
+	.remove		= apl_hostbridge_remove,
 	.platdata_auto_alloc_size = sizeof(struct apl_hostbridge_platdata),
+	ACPI_OPS_PTR(&apl_hostbridge_acpi_ops)
+	.flags		= DM_FLAG_OS_PREPARE,
 };

+ 18 - 0
arch/x86/cpu/apollolake/lpc.c

@@ -9,10 +9,14 @@
 #include <dm.h>
 #include <log.h>
 #include <spl.h>
+#include <acpi/acpi_table.h>
+#include <asm/cpu_common.h>
+#include <asm/intel_acpi.h>
 #include <asm/lpc_common.h>
 #include <asm/pci.h>
 #include <asm/arch/iomap.h>
 #include <asm/arch/lpc.h>
+#include <dm/acpi.h>
 #include <linux/log2.h>
 
 void lpc_enable_fixed_io_ranges(uint io_enables)
@@ -110,6 +114,19 @@ void lpc_io_setup_comm_a_b(void)
 	lpc_enable_fixed_io_ranges(com_enable);
 }
 
+static int apl_acpi_lpc_get_name(const struct udevice *dev, char *out_name)
+{
+	return acpi_copy_name(out_name, "LPCB");
+}
+
+struct acpi_ops apl_lpc_acpi_ops = {
+	.get_name	= apl_acpi_lpc_get_name,
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+	.write_tables	= intel_southbridge_write_acpi_tables,
+#endif
+	.inject_dsdt	= southbridge_inject_dsdt,
+};
+
 static const struct udevice_id apl_lpc_ids[] = {
 	{ .compatible = "intel,apl-lpc" },
 	{ }
@@ -120,4 +137,5 @@ U_BOOT_DRIVER(apl_lpc_drv) = {
 	.name		= "intel_apl_lpc",
 	.id		= UCLASS_LPC,
 	.of_match	= apl_lpc_ids,
+	ACPI_OPS_PTR(&apl_lpc_acpi_ops)
 };

+ 2 - 6
arch/x86/cpu/apollolake/pmc.c

@@ -118,7 +118,8 @@ int apl_pmc_ofdata_to_uc_platdata(struct udevice *dev)
 	int size;
 	int ret;
 
-	ret = dev_read_u32_array(dev, "early-regs", base, ARRAY_SIZE(base));
+	ret = dev_read_u32_array(dev, "early-regs", base,
+				 ARRAY_SIZE(base));
 	if (ret)
 		return log_msg_ret("Missing/short early-regs", ret);
 	if (spl_phase() == PHASE_TPL) {
@@ -133,11 +134,6 @@ int apl_pmc_ofdata_to_uc_platdata(struct udevice *dev)
 	}
 	upriv->acpi_base = base[4];
 
-	/* Since PCI is not enabled, we must get the BDF manually */
-	plat->bdf = pci_get_devfn(dev);
-	if (plat->bdf < 0)
-		return log_msg_ret("Cannot get PMC PCI address", plat->bdf);
-
 	/* Get the dwX values for pmc gpe settings */
 	size = dev_read_size(dev, "gpe0-dw");
 	if (size < 0)

+ 15 - 0
arch/x86/cpu/cpu.c

@@ -189,6 +189,14 @@ __weak void board_final_init(void)
 {
 }
 
+/*
+ * Implement a weak default function for boards that need to do some final
+ * processing before booting the OS.
+ */
+__weak void board_final_cleanup(void)
+{
+}
+
 int last_stage_init(void)
 {
 	struct acpi_fadt __maybe_unused *fadt;
@@ -218,6 +226,13 @@ int last_stage_init(void)
 		}
 	}
 
+	/*
+	 * TODO(sjg@chromium.org): Move this to bootm_announce_and_cleanup()
+	 * once APL FSP-S at 0x200000 does not overlap with the bzimage at
+	 * 0x100000.
+	 */
+	board_final_cleanup();
+
 	return 0;
 }
 #endif

+ 23 - 0
arch/x86/cpu/i386/cpu.c

@@ -34,6 +34,10 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define CPUID_FEATURE_PAE	BIT(6)
+#define CPUID_FEATURE_PSE36	BIT(17)
+#define CPUID_FEAURE_HTT	BIT(28)
+
 /*
  * Constructor for a conventional segment GDT (or LDT) entry
  * This is a macro so it can be used in initialisers
@@ -388,6 +392,25 @@ static void setup_identity(void)
 	}
 }
 
+static uint cpu_cpuid_extended_level(void)
+{
+	return cpuid_eax(0x80000000);
+}
+
+int cpu_phys_address_size(void)
+{
+	if (!has_cpuid())
+		return 32;
+
+	if (cpu_cpuid_extended_level() >= 0x80000008)
+		return cpuid_eax(0x80000008) & 0xff;
+
+	if (cpuid_edx(1) & (CPUID_FEATURE_PAE | CPUID_FEATURE_PSE36))
+		return 36;
+
+	return 32;
+}
+
 /* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
 static void setup_pci_ram_top(void)
 {

+ 7 - 0
arch/x86/cpu/intel_common/Makefile

@@ -2,6 +2,8 @@
 #
 # Copyright (c) 2016 Google, Inc
 
+obj-$(CONFIG_INTEL_ACPIGEN) += acpi.o
+
 ifdef CONFIG_HAVE_MRC
 obj-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += car.o
 obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += me_status.o
@@ -9,6 +11,10 @@ obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
 obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
 endif
 
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_INTEL_GMA_ACPI) += intel_opregion.o
+endif
+
 ifdef CONFIG_INTEL_CAR_CQOS
 obj-$(CONFIG_TPL_BUILD) += car2.o
 ifndef CONFIG_SPL_BUILD
@@ -20,6 +26,7 @@ obj-y += cpu.o
 obj-y += fast_spi.o
 obj-y += lpc.o
 obj-y += lpss.o
+obj-$(CONFIG_INTEL_GENERIC_WIFI) += generic_wifi.o
 ifndef CONFIG_TARGET_EFI_APP
 obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o
 ifndef CONFIG_$(SPL_)X86_64

+ 377 - 0
arch/x86/cpu/intel_common/acpi.c

@@ -0,0 +1,377 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Generic Intel ACPI table generation
+ *
+ * Copyright (C) 2017 Intel Corp.
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot src/soc/intel/common/block/acpi.c
+ */
+
+#include <common.h>
+#include <bloblist.h>
+#include <cpu.h>
+#include <dm.h>
+#include <acpi/acpigen.h>
+#include <asm/acpigen.h>
+#include <asm/acpi_table.h>
+#include <asm/cpu.h>
+#include <asm/cpu_common.h>
+#include <asm/intel_acpi.h>
+#include <asm/ioapic.h>
+#include <asm/mpspec.h>
+#include <asm/smm.h>
+#include <asm/turbo.h>
+#include <asm/intel_gnvs.h>
+#include <asm/arch/iomap.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/systemagent.h>
+#include <dm/acpi.h>
+#include <linux/err.h>
+#include <power/acpi_pmc.h>
+
+u32 acpi_fill_mcfg(u32 current)
+{
+	/* PCI Segment Group 0, Start Bus Number 0, End Bus Number is 255 */
+	current += acpi_create_mcfg_mmconfig((void *)current,
+					     CONFIG_MMCONF_BASE_ADDRESS, 0, 0,
+					     (CONFIG_SA_PCIEX_LENGTH >> 20)
+					     - 1);
+	return current;
+}
+
+static int acpi_sci_irq(void)
+{
+	int sci_irq = 9;
+	uint scis;
+	int ret;
+
+	ret = arch_read_sci_irq_select();
+	if (IS_ERR_VALUE(ret))
+		return log_msg_ret("sci_irq", ret);
+	scis = ret;
+	scis &= SCI_IRQ_MASK;
+	scis >>= SCI_IRQ_SHIFT;
+
+	/* Determine how SCI is routed. */
+	switch (scis) {
+	case SCIS_IRQ9:
+	case SCIS_IRQ10:
+	case SCIS_IRQ11:
+		sci_irq = scis - SCIS_IRQ9 + 9;
+		break;
+	case SCIS_IRQ20:
+	case SCIS_IRQ21:
+	case SCIS_IRQ22:
+	case SCIS_IRQ23:
+		sci_irq = scis - SCIS_IRQ20 + 20;
+		break;
+	default:
+		log_warning("Invalid SCI route! Defaulting to IRQ9\n");
+		sci_irq = 9;
+		break;
+	}
+
+	log_debug("SCI is IRQ%d\n", sci_irq);
+
+	return sci_irq;
+}
+
+static unsigned long acpi_madt_irq_overrides(unsigned long current)
+{
+	int sci = acpi_sci_irq();
+	u16 flags = MP_IRQ_TRIGGER_LEVEL;
+
+	if (sci < 0)
+		return log_msg_ret("sci irq", sci);
+
+	/* INT_SRC_OVR */
+	current += acpi_create_madt_irqoverride((void *)current, 0, 0, 2, 0);
+
+	flags |= arch_madt_sci_irq_polarity(sci);
+
+	/* SCI */
+	current +=
+	    acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags);
+
+	return current;
+}
+
+u32 acpi_fill_madt(u32 current)
+{
+	/* Local APICs */
+	current += acpi_create_madt_lapics(current);
+
+	/* IOAPIC */
+	current += acpi_create_madt_ioapic((void *)current, 2, IO_APIC_ADDR, 0);
+
+	return acpi_madt_irq_overrides(current);
+}
+
+void intel_acpi_fill_fadt(struct acpi_fadt *fadt)
+{
+	const u16 pmbase = IOMAP_ACPI_BASE;
+
+	/* Use ACPI 3.0 revision. */
+	fadt->header.revision = acpi_get_table_revision(ACPITAB_FADT);
+
+	fadt->sci_int = acpi_sci_irq();
+	fadt->smi_cmd = APM_CNT;
+	fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
+	fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
+	fadt->s4bios_req = 0x0;
+	fadt->pstate_cnt = 0;
+
+	fadt->pm1a_evt_blk = pmbase + PM1_STS;
+	fadt->pm1b_evt_blk = 0x0;
+	fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
+	fadt->pm1b_cnt_blk = 0x0;
+
+	fadt->gpe0_blk = pmbase + GPE0_STS;
+
+	fadt->pm1_evt_len = 4;
+	fadt->pm1_cnt_len = 2;
+
+	/* GPE0 STS/EN pairs each 32 bits wide. */
+	fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
+
+	fadt->flush_size = 0x400;	/* twice of cache size */
+	fadt->flush_stride = 0x10;	/* Cache line width  */
+	fadt->duty_offset = 1;
+	fadt->day_alrm = 0xd;
+
+	fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+	    ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
+	    ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE |
+	    ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
+
+	fadt->reset_reg.space_id = 1;
+	fadt->reset_reg.bit_width = 8;
+	fadt->reset_reg.addrl = IO_PORT_RESET;
+	fadt->reset_value = RST_CPU | SYS_RST;
+
+	fadt->x_pm1a_evt_blk.space_id = 1;
+	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
+	fadt->x_pm1a_evt_blk.addrl = pmbase + PM1_STS;
+
+	fadt->x_pm1b_evt_blk.space_id = 1;
+
+	fadt->x_pm1a_cnt_blk.space_id = 1;
+	fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
+	fadt->x_pm1a_cnt_blk.addrl = pmbase + PM1_CNT;
+
+	fadt->x_pm1b_cnt_blk.space_id = 1;
+
+	fadt->x_gpe1_blk.space_id = 1;
+}
+
+int intel_southbridge_write_acpi_tables(const struct udevice *dev,
+					struct acpi_ctx *ctx)
+{
+	int ret;
+
+	ret = acpi_write_dbg2_pci_uart(ctx, gd->cur_serial_dev,
+				       ACPI_ACCESS_SIZE_DWORD_ACCESS);
+	if (ret)
+		return log_msg_ret("dbg2", ret);
+
+	ret = acpi_write_hpet(ctx);
+	if (ret)
+		return log_msg_ret("hpet", ret);
+
+	return 0;
+}
+
+__weak u32 acpi_fill_soc_wake(u32 generic_pm1_en,
+			      const struct chipset_power_state *ps)
+{
+	return generic_pm1_en;
+}
+
+__weak int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+	return 0;
+}
+
+int southbridge_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+	struct acpi_global_nvs *gnvs;
+	int ret;
+
+	ret = bloblist_ensure_size(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs),
+				   (void **)&gnvs);
+	if (ret)
+		return log_msg_ret("bloblist", ret);
+	memset(gnvs, '\0', sizeof(*gnvs));
+
+	ret = acpi_create_gnvs(gnvs);
+	if (ret)
+		return log_msg_ret("gnvs", ret);
+
+	/*
+	 * TODO(sjg@chromum.org): tell SMI about it
+	 * smm_setup_structures(gnvs, NULL, NULL);
+	 */
+
+	/* Add it to DSDT */
+	acpigen_write_scope(ctx, "\\");
+	acpigen_write_name_dword(ctx, "NVSA", (uintptr_t)gnvs);
+	acpigen_pop_len(ctx);
+
+	return 0;
+}
+
+static int calculate_power(int tdp, int p1_ratio, int ratio)
+{
+	u32 m;
+	u32 power;
+
+	/*
+	 * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
+	 *
+	 * Power = (ratio / p1_ratio) * m * tdp
+	 */
+
+	m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
+	m = (m * m) / 1000;
+
+	power = ((ratio * 100000 / p1_ratio) / 100);
+	power *= (m / 100) * (tdp / 1000);
+	power /= 1000;
+
+	return power;
+}
+
+void generate_p_state_entries(struct acpi_ctx *ctx, int core,
+			      int cores_per_package)
+{
+	int ratio_min, ratio_max, ratio_turbo, ratio_step;
+	int coord_type, power_max, num_entries;
+	int ratio, power, clock, clock_max;
+	bool turbo;
+
+	coord_type = cpu_get_coord_type();
+	ratio_min = cpu_get_min_ratio();
+	ratio_max = cpu_get_max_ratio();
+	clock_max = (ratio_max * cpu_get_bus_clock_khz()) / 1000;
+	turbo = (turbo_get_state() == TURBO_ENABLED);
+
+	/* Calculate CPU TDP in mW */
+	power_max = cpu_get_power_max();
+
+	/* Write _PCT indicating use of FFixedHW */
+	acpigen_write_empty_pct(ctx);
+
+	/* Write _PPC with no limit on supported P-state */
+	acpigen_write_ppc_nvs(ctx);
+	/* Write PSD indicating configured coordination type */
+	acpigen_write_psd_package(ctx, core, 1, coord_type);
+
+	/* Add P-state entries in _PSS table */
+	acpigen_write_name(ctx, "_PSS");
+
+	/* Determine ratio points */
+	ratio_step = PSS_RATIO_STEP;
+	do {
+		num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
+		if (((ratio_max - ratio_min) % ratio_step) > 0)
+			num_entries += 1;
+		if (turbo)
+			num_entries += 1;
+		if (num_entries > PSS_MAX_ENTRIES)
+			ratio_step += 1;
+	} while (num_entries > PSS_MAX_ENTRIES);
+
+	/* _PSS package count depends on Turbo */
+	acpigen_write_package(ctx, num_entries);
+
+	/* P[T] is Turbo state if enabled */
+	if (turbo) {
+		ratio_turbo = cpu_get_max_turbo_ratio();
+
+		/* Add entry for Turbo ratio */
+		acpigen_write_pss_package(ctx, clock_max + 1,	/* MHz */
+					  power_max,		/* mW */
+					  PSS_LATENCY_TRANSITION,/* lat1 */
+					  PSS_LATENCY_BUSMASTER,/* lat2 */
+					  ratio_turbo << 8,	/* control */
+					  ratio_turbo << 8);	/* status */
+		num_entries -= 1;
+	}
+
+	/* First regular entry is max non-turbo ratio */
+	acpigen_write_pss_package(ctx, clock_max,	/* MHz */
+				  power_max,		/* mW */
+				  PSS_LATENCY_TRANSITION,/* lat1 */
+				  PSS_LATENCY_BUSMASTER,/* lat2 */
+				  ratio_max << 8,	/* control */
+				  ratio_max << 8);	/* status */
+	num_entries -= 1;
+
+	/* Generate the remaining entries */
+	for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
+	     ratio >= ratio_min; ratio -= ratio_step) {
+		/* Calculate power at this ratio */
+		power = calculate_power(power_max, ratio_max, ratio);
+		clock = (ratio * cpu_get_bus_clock_khz()) / 1000;
+
+		acpigen_write_pss_package(ctx, clock,		/* MHz */
+					  power,		/* mW */
+					  PSS_LATENCY_TRANSITION,/* lat1 */
+					  PSS_LATENCY_BUSMASTER,/* lat2 */
+					  ratio << 8,		/* control */
+					  ratio << 8);		/* status */
+	}
+	/* Fix package length */
+	acpigen_pop_len(ctx);
+}
+
+void generate_t_state_entries(struct acpi_ctx *ctx, int core,
+			      int cores_per_package, struct acpi_tstate *entry,
+			      int nentries)
+{
+	if (!nentries)
+		return;
+
+	/* Indicate SW_ALL coordination for T-states */
+	acpigen_write_tsd_package(ctx, core, cores_per_package, SW_ALL);
+
+	/* Indicate FixedHW so OS will use MSR */
+	acpigen_write_empty_ptc(ctx);
+
+	/* Set NVS controlled T-state limit */
+	acpigen_write_tpc(ctx, "\\TLVL");
+
+	/* Write TSS table for MSR access */
+	acpigen_write_tss_package(ctx, entry, nentries);
+}
+
+int acpi_generate_cpu_header(struct acpi_ctx *ctx, int core_id,
+			     const struct acpi_cstate *c_state_map,
+			     int num_cstates)
+{
+	bool is_first = !core_id;
+
+	/* Generate processor \_PR.CPUx */
+	acpigen_write_processor(ctx, core_id, is_first ? ACPI_BASE_ADDRESS : 0,
+				is_first ? 6 : 0);
+
+	/* Generate C-state tables */
+	acpigen_write_cst_package(ctx, c_state_map, num_cstates);
+
+	return 0;
+}
+
+int acpi_generate_cpu_package_final(struct acpi_ctx *ctx, int cores_per_package)
+{
+	/*
+	 * PPKG is usually used for thermal management of the first and only
+	 * package
+	 */
+	acpigen_write_processor_package(ctx, "PPKG", 0, cores_per_package);
+
+	/* Add a method to notify processor nodes */
+	acpigen_write_processor_cnot(ctx, cores_per_package);
+
+	return 0;
+}

+ 79 - 0
arch/x86/cpu/intel_common/cpu.c

@@ -12,6 +12,7 @@
 #include <dm.h>
 #include <errno.h>
 #include <log.h>
+#include <acpi/acpigen.h>
 #include <asm/cpu.h>
 #include <asm/cpu_common.h>
 #include <asm/intel_regs.h>
@@ -126,6 +127,7 @@ int cpu_intel_get_info(struct cpu_info *info, int bclk)
 	info->cpu_freq = ((msr.lo >> 8) & 0xff) * bclk * 1000000;
 	info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU |
 		1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID;
+	info->address_width = cpu_phys_address_size();
 
 	return 0;
 }
@@ -227,3 +229,80 @@ void cpu_set_eist(bool eist_status)
 		msr.lo &= ~MISC_ENABLE_ENHANCED_SPEEDSTEP;
 	msr_write(MSR_IA32_MISC_ENABLE, msr);
 }
+
+int cpu_get_coord_type(void)
+{
+	return HW_ALL;
+}
+
+int cpu_get_min_ratio(void)
+{
+	msr_t msr;
+
+	/* Get bus ratio limits and calculate clock speeds */
+	msr = msr_read(MSR_PLATFORM_INFO);
+
+	return (msr.hi >> 8) & 0xff;	/* Max Efficiency Ratio */
+}
+
+int cpu_get_max_ratio(void)
+{
+	u32 ratio_max;
+	msr_t msr;
+
+	if (cpu_config_tdp_levels()) {
+		/* Set max ratio to nominal TDP ratio */
+		msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+		ratio_max = msr.lo & 0xff;
+	} else {
+		msr = msr_read(MSR_PLATFORM_INFO);
+		/* Max Non-Turbo Ratio */
+		ratio_max = (msr.lo >> 8) & 0xff;
+	}
+
+	return ratio_max;
+}
+
+int cpu_get_bus_clock_khz(void)
+{
+	/*
+	 * CPU bus clock is set by default here to 100MHz. This function returns
+	 * the bus clock in KHz.
+	 */
+	return INTEL_BCLK_MHZ * 1000;
+}
+
+int cpu_get_power_max(void)
+{
+	int power_unit;
+	msr_t msr;
+
+	msr = msr_read(MSR_PKG_POWER_SKU_UNIT);
+	power_unit = 2 << ((msr.lo & 0xf) - 1);
+	msr = msr_read(MSR_PKG_POWER_SKU);
+
+	return (msr.lo & 0x7fff) * 1000 / power_unit;
+}
+
+int cpu_get_max_turbo_ratio(void)
+{
+	msr_t msr;
+
+	msr = msr_read(MSR_TURBO_RATIO_LIMIT);
+
+	return msr.lo & 0xff;
+}
+
+int cpu_get_cores_per_package(void)
+{
+	struct cpuid_result result;
+	int cores = 1;
+
+	if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
+		return 1;
+
+	result = cpuid_ext(0xb, 1);
+	cores = result.ebx & 0xff;
+
+	return cores;
+}

+ 120 - 0
arch/x86/cpu/intel_common/generic_wifi.c

@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Generic WiFi ACPI info
+ *
+ * Copyright 2019 Google LLC
+ * Modified from coreboot src/drivers/wifi/generic.c
+ */
+
+#include <common.h>
+#include <log.h>
+#include <acpi/acpigen.h>
+#include <acpi/acpi_device.h>
+#include <dm.h>
+#include <dm/acpi.h>
+
+/* WRDS Spec Revision */
+#define WRDS_REVISION 0x0
+
+/* EWRD Spec Revision */
+#define EWRD_REVISION 0x0
+
+/* WRDS Domain type */
+#define WRDS_DOMAIN_TYPE_WIFI 0x7
+
+/* EWRD Domain type */
+#define EWRD_DOMAIN_TYPE_WIFI 0x7
+
+/* WGDS Domain type */
+#define WGDS_DOMAIN_TYPE_WIFI 0x7
+
+/*
+ * WIFI ACPI NAME = "WF" + hex value of last 8 bits of dev_path_encode + '\0'
+ * The above representation returns unique and consistent name every time
+ * generate_wifi_acpi_name is invoked. The last 8 bits of dev_path_encode is
+ * chosen since it contains the bus address of the device.
+ */
+#define WIFI_ACPI_NAME_MAX_LEN 5
+
+/**
+ * struct generic_wifi_config - Data structure to contain common wifi config
+ * @wake: Wake pin for ACPI _PRW
+ * @maxsleep: Maximum sleep state to wake from
+ */
+struct generic_wifi_config {
+	unsigned int wake;
+	unsigned int maxsleep;
+};
+
+static int generic_wifi_fill_ssdt(struct acpi_ctx *ctx,
+				  const struct udevice *dev,
+				  const struct generic_wifi_config *config)
+{
+	char name[ACPI_NAME_MAX];
+	char path[ACPI_PATH_MAX];
+	pci_dev_t bdf;
+	u32 address;
+	int ret;
+
+	ret = acpi_device_path(dev_get_parent(dev), path, sizeof(path));
+	if (ret)
+		return log_msg_ret("path", ret);
+	ret = acpi_get_name(dev, name);
+	if (ret)
+		return log_msg_ret("name", ret);
+
+	/* Device */
+	acpigen_write_scope(ctx, path);
+	acpigen_write_device(ctx, name);
+	acpigen_write_name_integer(ctx, "_UID", 0);
+	acpigen_write_name_string(ctx, "_DDN",
+				  dev_read_string(dev, "acpi,ddn"));
+
+	/* Address */
+	bdf = dm_pci_get_bdf(dev);
+	address = (PCI_DEV(bdf) << 16) | PCI_FUNC(bdf);
+	acpigen_write_name_dword(ctx, "_ADR", address);
+
+	/* Wake capabilities */
+	if (config)
+		acpigen_write_prw(ctx, config->wake, config->maxsleep);
+
+	acpigen_pop_len(ctx); /* Device */
+	acpigen_pop_len(ctx); /* Scope */
+
+	return 0;
+}
+
+static int intel_wifi_acpi_fill_ssdt(const struct udevice *dev,
+				     struct acpi_ctx *ctx)
+{
+	struct generic_wifi_config config;
+	bool have_config;
+	int ret;
+
+	ret = dev_read_u32(dev, "acpi,wake", &config.wake);
+	have_config = !ret;
+	/* By default, all intel wifi chips wake from S3 */
+	config.maxsleep = 3;
+	ret = generic_wifi_fill_ssdt(ctx, dev, have_config ? &config : NULL);
+	if (ret)
+		return log_msg_ret("wifi", ret);
+
+	return 0;
+}
+
+struct acpi_ops wifi_acpi_ops = {
+	.fill_ssdt	= intel_wifi_acpi_fill_ssdt,
+};
+
+static const struct udevice_id intel_wifi_ids[] = {
+	{ .compatible = "intel,generic-wifi" },
+	{ }
+};
+
+U_BOOT_DRIVER(intel_wifi) = {
+	.name		= "intel_wifi",
+	.id		= UCLASS_MISC,
+	.of_match	= intel_wifi_ids,
+	ACPI_OPS_PTR(&wifi_acpi_ops)
+};

+ 168 - 0
arch/x86/cpu/intel_common/intel_opregion.c

@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Writing IntelGraphicsMem table for ACPI
+ *
+ * Copyright 2019 Google LLC
+ * Modified from coreboot src/soc/intel/gma/opregion.c
+ */
+
+#include <common.h>
+#include <binman.h>
+#include <bloblist.h>
+#include <dm.h>
+#include <spi_flash.h>
+#include <asm/intel_opregion.h>
+
+static char vbt_data[8 << 10];
+
+static int locate_vbt(char **vbtp, int *sizep)
+{
+	struct binman_entry vbt;
+	struct udevice *dev;
+	u32 vbtsig = 0;
+	int size;
+	int ret;
+
+	ret = binman_entry_find("intel-vbt", &vbt);
+	if (ret)
+		return log_msg_ret("find VBT", ret);
+	ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
+	if (ret)
+		return log_msg_ret("find flash", ret);
+	size = vbt.size;
+	if (size > sizeof(vbt_data))
+		return log_msg_ret("vbt", -E2BIG);
+	ret = spi_flash_read_dm(dev, vbt.image_pos, size, vbt_data);
+	if (ret)
+		return log_msg_ret("read", ret);
+
+	memcpy(&vbtsig, vbt_data, sizeof(vbtsig));
+	if (vbtsig != VBT_SIGNATURE) {
+		log_err("Missing/invalid signature in VBT data file!\n");
+		return -EINVAL;
+	}
+
+	log_info("Found a VBT of %u bytes\n", size);
+	*sizep = size;
+	*vbtp = vbt_data;
+
+	return 0;
+}
+
+/* Write ASLS PCI register and prepare SWSCI register */
+static int intel_gma_opregion_register(struct udevice *dev, ulong opregion)
+{
+	int sci_reg;
+
+	if (!device_active(dev))
+		return -ENOENT;
+
+	/*
+	 * Intel BIOS Specification
+	 * Chapter 5.3.7 "Initialise Hardware State"
+	 */
+	dm_pci_write_config32(dev, ASLS, opregion);
+
+	/*
+	 * Atom-based platforms use a combined SMI/SCI register,
+	 * whereas non-Atom platforms use a separate SCI register
+	 */
+	if (IS_ENABLED(CONFIG_INTEL_GMA_SWSMISCI))
+		sci_reg = SWSMISCI;
+	else
+		sci_reg = SWSCI;
+
+	/*
+	 * Intel's Windows driver relies on this:
+	 * Intel BIOS Specification
+	 * Chapter 5.4 "ASL Software SCI Handler"
+	 */
+	dm_pci_clrset_config16(dev, sci_reg, GSSCIE, SMISCISEL);
+
+	return 0;
+}
+
+int intel_gma_init_igd_opregion(struct udevice *dev,
+				struct igd_opregion *opregion)
+{
+	struct optionrom_vbt *vbt = NULL;
+	char *vbt_buf;
+	int vbt_size;
+	int ret;
+
+	ret = locate_vbt(&vbt_buf, &vbt_size);
+	if (ret) {
+		log_err("GMA: VBT couldn't be found\n");
+		return log_msg_ret("find vbt", ret);
+	}
+	vbt = (struct optionrom_vbt *)vbt_buf;
+
+	memset(opregion, '\0', sizeof(struct igd_opregion));
+
+	memcpy(&opregion->header.signature, IGD_OPREGION_SIGNATURE,
+	       sizeof(opregion->header.signature));
+	memcpy(opregion->header.vbios_version, vbt->coreblock_biosbuild,
+	       ARRAY_SIZE(vbt->coreblock_biosbuild));
+	/* Extended VBT support */
+	if (vbt->hdr_vbt_size > sizeof(opregion->vbt.gvd1)) {
+		struct optionrom_vbt *ext_vbt;
+
+		ret = bloblist_ensure_size(BLOBLISTT_INTEL_VBT,
+					   vbt->hdr_vbt_size,
+					   (void **)&ext_vbt);
+		if (ret) {
+			log_err("GMA: Unable to add Ext VBT to bloblist\n");
+			return log_msg_ret("blob", ret);
+		}
+
+		memcpy(ext_vbt, vbt, vbt->hdr_vbt_size);
+		opregion->mailbox3.rvda = (uintptr_t)ext_vbt;
+		opregion->mailbox3.rvds = vbt->hdr_vbt_size;
+	} else {
+		/* Raw VBT size which can fit in gvd1 */
+		printf("copy to %p\n", opregion->vbt.gvd1);
+		memcpy(opregion->vbt.gvd1, vbt, vbt->hdr_vbt_size);
+	}
+
+	/* 8kb */
+	opregion->header.size = sizeof(struct igd_opregion) / 1024;
+
+	/*
+	 * Left-shift version field to accommodate Intel Windows driver quirk
+	 * when not using a VBIOS.
+	 * Required for Legacy boot + NGI, UEFI + NGI, and UEFI + GOP driver.
+	 *
+	 * No adverse effects when using VBIOS or booting Linux.
+	 */
+	opregion->header.version = IGD_OPREGION_VERSION << 24;
+
+	/* We just assume we're mobile for now */
+	opregion->header.mailboxes = MAILBOXES_MOBILE;
+
+	/* Initialise Mailbox 1 */
+	opregion->mailbox1.clid = 1;
+
+	/* Initialise Mailbox 3 */
+	opregion->mailbox3.bclp = IGD_BACKLIGHT_BRIGHTNESS;
+	opregion->mailbox3.pfit = IGD_FIELD_VALID | IGD_PFIT_STRETCH;
+	opregion->mailbox3.pcft = 0; /* should be (IMON << 1) & 0x3e */
+	opregion->mailbox3.cblv = IGD_FIELD_VALID | IGD_INITIAL_BRIGHTNESS;
+	opregion->mailbox3.bclm[0] = IGD_WORD_FIELD_VALID + 0x0000;
+	opregion->mailbox3.bclm[1] = IGD_WORD_FIELD_VALID + 0x0a19;
+	opregion->mailbox3.bclm[2] = IGD_WORD_FIELD_VALID + 0x1433;
+	opregion->mailbox3.bclm[3] = IGD_WORD_FIELD_VALID + 0x1e4c;
+	opregion->mailbox3.bclm[4] = IGD_WORD_FIELD_VALID + 0x2866;
+	opregion->mailbox3.bclm[5] = IGD_WORD_FIELD_VALID + 0x327f;
+	opregion->mailbox3.bclm[6] = IGD_WORD_FIELD_VALID + 0x3c99;
+	opregion->mailbox3.bclm[7] = IGD_WORD_FIELD_VALID + 0x46b2;
+	opregion->mailbox3.bclm[8] = IGD_WORD_FIELD_VALID + 0x50cc;
+	opregion->mailbox3.bclm[9] = IGD_WORD_FIELD_VALID + 0x5ae5;
+	opregion->mailbox3.bclm[10] = IGD_WORD_FIELD_VALID + 0x64ff;
+
+	/* Write ASLS PCI register and prepare SWSCI register */
+	ret = intel_gma_opregion_register(dev, (ulong)opregion);
+	if (ret)
+		return log_msg_ret("write asls", ret);
+
+	return 0;
+}

+ 19 - 5
arch/x86/cpu/mtrr.c

@@ -19,6 +19,7 @@
 #include <common.h>
 #include <cpu_func.h>
 #include <log.h>
+#include <sort.h>
 #include <asm/cache.h>
 #include <asm/io.h>
 #include <asm/mp.h>
@@ -66,9 +67,10 @@ static void set_var_mtrr(uint reg, uint type, uint64_t start, uint64_t size)
 
 void mtrr_read_all(struct mtrr_info *info)
 {
+	int reg_count = mtrr_get_var_count();
 	int i;
 
-	for (i = 0; i < MTRR_COUNT; i++) {
+	for (i = 0; i < reg_count; i++) {
 		info->mtrr[i].base = native_read_msr(MTRR_PHYS_BASE_MSR(i));
 		info->mtrr[i].mask = native_read_msr(MTRR_PHYS_MASK_MSR(i));
 	}
@@ -76,10 +78,11 @@ void mtrr_read_all(struct mtrr_info *info)
 
 void mtrr_write_all(struct mtrr_info *info)
 {
+	int reg_count = mtrr_get_var_count();
 	struct mtrr_state state;
 	int i;
 
-	for (i = 0; i < MTRR_COUNT; i++) {
+	for (i = 0; i < reg_count; i++) {
 		mtrr_open(&state, true);
 		wrmsrl(MTRR_PHYS_BASE_MSR(i), info->mtrr[i].base);
 		wrmsrl(MTRR_PHYS_MASK_MSR(i), info->mtrr[i].mask);
@@ -124,6 +127,16 @@ static int mtrr_copy_to_aps(void)
 	return 0;
 }
 
+static int h_comp_mtrr(const void *p1, const void *p2)
+{
+	const struct mtrr_request *req1 = p1;
+	const struct mtrr_request *req2 = p2;
+
+	s64 diff = req1->start - req2->start;
+
+	return diff < 0 ? -1 : diff > 0 ? 1 : 0;
+}
+
 int mtrr_commit(bool do_caches)
 {
 	struct mtrr_request *req = gd->arch.mtrr_req;
@@ -139,12 +152,13 @@ int mtrr_commit(bool do_caches)
 	debug("open\n");
 	mtrr_open(&state, do_caches);
 	debug("open done\n");
+	qsort(req, gd->arch.mtrr_req_count, sizeof(*req), h_comp_mtrr);
 	for (i = 0; i < gd->arch.mtrr_req_count; i++, req++)
 		set_var_mtrr(i, req->type, req->start, req->size);
 
 	/* Clear the ones that are unused */
 	debug("clear\n");
-	for (; i < MTRR_COUNT; i++)
+	for (; i < MTRR_MAX_COUNT; i++)
 		wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
 	debug("close\n");
 	mtrr_close(&state, do_caches);
@@ -184,7 +198,7 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size)
 	return 0;
 }
 
-static int get_var_mtrr_count(void)
+int mtrr_get_var_count(void)
 {
 	return msr_read(MSR_MTRR_CAP_MSR).lo & MSR_MTRR_CAP_VCNT;
 }
@@ -195,7 +209,7 @@ static int get_free_var_mtrr(void)
 	int vcnt;
 	int i;
 
-	vcnt = get_var_mtrr_count();
+	vcnt = mtrr_get_var_count();
 
 	/* Identify the first var mtrr which is not valid */
 	for (i = 0; i < vcnt; i++) {

+ 1 - 0
arch/x86/cpu/tangier/Kconfig

@@ -12,6 +12,7 @@ config INTEL_TANGIER
 	imply MMC_SDHCI_TANGIER
 	imply USB
 	imply USB_DWC3
+	imply BINMAN
 
 if INTEL_TANGIER
 

+ 5 - 0
arch/x86/cpu/x86_64/cpu.c

@@ -70,3 +70,8 @@ int x86_cpu_reinit_f(void)
 {
 	return 0;
 }
+
+int cpu_phys_address_size(void)
+{
+	return CONFIG_CPU_ADDR_BITS;
+}

+ 212 - 14
arch/x86/dts/chromebook_coral.dts

@@ -15,14 +15,20 @@
 #include "flashmap-16mb-rw.dtsi"
 #endif
 
+#include <dt-bindings/clock/intel-clock.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/x86-irq.h>
+#include <asm/e820.h>
 #include <asm/intel_pinctrl_defs.h>
 #include <asm/arch-apollolake/cpu.h>
+#include <asm/arch-apollolake/gpe.h>
 #include <asm/arch-apollolake/gpio.h>
 #include <asm/arch-apollolake/iomap.h>
 #include <asm/arch-apollolake/pm.h>
 #include <dt-bindings/clock/intel-clock.h>
 #include <asm/arch-apollolake/fsp/fsp_m_upd.h>
 #include <asm/arch-apollolake/fsp/fsp_s_upd.h>
+#include <dt-bindings/sound/nhlt.h>
 
 / {
 	model = "Google Coral";
@@ -40,6 +46,14 @@
 		i2c5 = &i2c_5;
 		i2c6 = &i2c_6;
 		i2c7 = &i2c_7;
+		mmc1 = &sdmmc;
+	};
+
+	board: board {
+		compatible = "google,coral";
+		recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>;
+		write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>;
+		phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>;
 	};
 
 	config {
@@ -48,6 +62,15 @@
 
 	chosen {
 		stdout-path = &serial;
+		e820-entries = /bits/ 64 <
+			IOMAP_P2SB_BAR IOMAP_P2SB_SIZE E820_RESERVED
+			MCH_BASE_ADDRESS     MCH_SIZE  E820_RESERVED>;
+		u-boot,acpi-ssdt-order = <&cpu_0 &cpu_1 &cpu_2 &cpu_3
+			&i2c_0 &i2c_1 &i2c_2 &i2c_3 &i2c_4 &i2c_5
+			&sdmmc &maxim_codec &wifi &da_codec &tpm
+			&elan_touchscreen &raydium_touchscreen
+			&elan_touchpad &synaptics_touchpad &wacom_digitizer>;
+		u-boot,acpi-dsdt-order = <&board &lpc>;
 	};
 
 	clk: clock {
@@ -60,7 +83,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu@0 {
+		cpu_0: cpu@0 {
 			u-boot,dm-pre-reloc;
 			device_type = "cpu";
 			compatible = "intel,apl-cpu";
@@ -68,21 +91,21 @@
 			intel,apic-id = <0>;
 		};
 
-		cpu@1 {
+		cpu_1: cpu@1 {
 			device_type = "cpu";
 			compatible = "intel,apl-cpu";
 			reg = <1>;
 			intel,apic-id = <2>;
 		};
 
-		cpu@2 {
+		cpu_2: cpu@2 {
 			device_type = "cpu";
 			compatible = "intel,apl-cpu";
 			reg = <2>;
 			intel,apic-id = <4>;
 		};
 
-		cpu@3 {
+		cpu_3: cpu@3 {
 			device_type = "cpu";
 			compatible = "intel,apl-cpu";
 			reg = <3>;
@@ -128,6 +151,10 @@
 			 */
 			fsp_s: fsp-s {
 			};
+
+			nhlt {
+				intel,dmic-channels = <4>;
+			};
 		};
 
 		punit@0,1 {
@@ -136,21 +163,29 @@
 			compatible = "intel,apl-punit";
 		};
 
+		gma@2,0 {
+			reg = <0x00001000 0 0 0 0>;
+			compatible = "fsp-fb";
+		};
+
 		p2sb: p2sb@d,0 {
 			u-boot,dm-pre-reloc;
 			reg = <0x02006810 0 0 0 0>;
 			compatible = "intel,p2sb";
 			early-regs = <IOMAP_P2SB_BAR 0x100000>;
+			pci,no-autoconfig;
 
 			n {
 				compatible = "intel,apl-pinctrl";
 				u-boot,dm-pre-reloc;
 				intel,p2sb-port-id = <PID_GPIO_N>;
+				acpi,path = "\\_SB.GPO0";
 				gpio_n: gpio-n {
 					compatible = "intel,gpio";
 					u-boot,dm-pre-reloc;
 					gpio-controller;
 					#gpio-cells = <2>;
+					linux-name = "INT3452:00";
 				};
 			};
 
@@ -159,11 +194,13 @@
 				compatible = "intel,apl-pinctrl";
 				intel,p2sb-port-id = <PID_GPIO_NW>;
 				#gpio-cells = <2>;
+				acpi,path = "\\_SB.GPO1";
 				gpio_nw: gpio-nw {
 					compatible = "intel,gpio";
 					u-boot,dm-pre-reloc;
 					gpio-controller;
 					#gpio-cells = <2>;
+					linux-name = "INT3452:01";
 				};
 			};
 
@@ -172,11 +209,13 @@
 				compatible = "intel,apl-pinctrl";
 				intel,p2sb-port-id = <PID_GPIO_W>;
 				#gpio-cells = <2>;
+				acpi,path = "\\_SB.GPO2";
 				gpio_w: gpio-w {
 					compatible = "intel,gpio";
 					u-boot,dm-pre-reloc;
 					gpio-controller;
 					#gpio-cells = <2>;
+					linux-name = "INT3452:02";
 				};
 			};
 
@@ -185,11 +224,13 @@
 				compatible = "intel,apl-pinctrl";
 				intel,p2sb-port-id = <PID_GPIO_SW>;
 				#gpio-cells = <2>;
+				acpi,path = "\\_SB.GPO3";
 				gpio_sw: gpio-sw {
 					compatible = "intel,gpio";
 					u-boot,dm-pre-reloc;
 					gpio-controller;
 					#gpio-cells = <2>;
+					linux-name = "INT3452:03";
 				};
 			};
 
@@ -238,6 +279,24 @@
 			gpe0-en = <0x30>;
 		};
 
+		audio@e,0 {
+			reg = <0x7000 0 0 0 0>;
+			compatible = "simple-bus";
+			acpi,name = "HDAS";
+			i2s {
+				compatible = "fred";
+			};
+			maxim_codec: maxim-codec {
+				compatible = "maxim,max98357a";
+				acpi,ddn = "Maxim Integrated 98357A Amplifier";
+				sdmode-gpios = <&gpio_n GPIO_76 GPIO_ACTIVE_HIGH>;
+				sdmode-delay = <5>;
+				acpi,name = "MAXM";
+				acpi,hid = "MX98357A";
+				acpi,audio-link = <AUDIO_LINK_SSP5>;
+			};
+		};
+
 		spi: fast-spi@d,2 {
 			u-boot,dm-pre-reloc;
 			reg = <0x02006a10 0 0 0 0>;
@@ -267,19 +326,63 @@
 			};
 		};
 
+		/* WiFi */
+		pcie-a0@14,0 {
+			reg = <0x0000a000 0 0 0 0>;
+			acpi,name = "RP01";
+			wifi: wifi {
+				compatible = "intel,generic-wifi";
+				acpi,ddn = "Intel WiFi";
+				acpi,name = "WF00";
+				acpi,wake = <GPE0_DW3_00>;
+				interrupts-extended = <&acpi_gpe 0x3c 0>;
+			};
+		};
+
 		i2c_0: i2c2@16,0 {
 			compatible = "intel,apl-i2c";
 			reg = <0x0200b010 0 0 0 0>;
 			clocks = <&clk CLK_I2C>;
 			i2c-scl-rising-time-ns = <104>;
 			i2c-scl-falling-time-ns = <52>;
+			clock-frequency = <400000>;
+			i2c,speeds = <100000 400000 1000000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			da_codec: da-codec {
+				reg = <0x1a>;
+				compatible = "dlg,da7219";
+				interrupts-extended = <&acpi_gpe GPIO_116_IRQ
+					(IRQ_TYPE_LEVEL_LOW | X86_IRQ_TYPE_SHARED)>;
+				acpi,name = "DLG7";
+				acpi,ddn = "Dialog Semiconductor DA7219 Audio Codec";
+				acpi,audio-link = <AUDIO_LINK_SSP1>;
+				dlg,micbias-lvl = <2600>;
+				dlg,mic-amp-in-sel = "diff";
+				da7219_aad {
+					dlg,btn-cfg = <50>;
+					dlg,mic-det-thr = <500>;
+					dlg,jack-ins-deb = <20>;
+					dlg,jack-det-rate = "32ms_64ms";
+					dlg,jack-rem-deb = <1>;
+					dlg,a-d-btn-thr = <0xa>;
+					dlg,d-b-btn-thr = <0x16>;
+					dlg,b-c-btn-thr = <0x21>;
+					dlg,c-mic-btn-thr = <0x3e>;
+					dlg,btn-avg = <4>;
+					dlg,adc-1bit-rpt = <1>;
+				};
+			};
 		};
 
 		i2c_1: i2c2@16,1 {
 			compatible = "intel,apl-i2c";
 			reg = <0x0200b110 0 0 0 0>;
 			clocks = <&clk CLK_I2C>;
-			status = "disabled";
+			clock-frequency = <400000>;
+			i2c,speeds = <100000 400000 1000000 3400000>;
+			i2c-scl-rising-time-ns = <52>;
+			i2c-scl-falling-time-ns = <52>;
 		};
 
 		i2c_2: i2c2@16,2 {
@@ -288,53 +391,130 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clock-frequency = <400000>;
+			i2c,speeds = <100000 400000 1000000>;
 			clocks = <&clk CLK_I2C>;
 			i2c-scl-rising-time-ns = <57>;
 			i2c-scl-falling-time-ns = <28>;
-			tpm@50 {
+			tpm: tpm@50 {
 				reg = <0x50>;
 				compatible = "google,cr50";
 				u-boot,i2c-offset-len = <0>;
 				ready-gpios = <&gpio_n 28 GPIO_ACTIVE_LOW>;
-				interrupts-extended = <&acpi_gpe 0x3c 0>;
+				interrupts-extended = <&acpi_gpe GPIO_28_IRQ
+					 IRQ_TYPE_EDGE_FALLING>;
+				acpi,hid = "GOOG0005";
+				acpi,ddn = "I2C TPM";
+				acpi,name = "TPMI";
 			};
 		};
 
 		i2c_3: i2c2@16,3 {
 			compatible = "intel,apl-i2c";
-			reg = <0x0200b110 0 0 0 0>;
+			reg = <0x0200b310 0 0 0 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 			clocks = <&clk CLK_I2C>;
 			i2c-scl-rising-time-ns = <76>;
 			i2c-scl-falling-time-ns = <164>;
+			clock-frequency = <400000>;
+			i2c,speeds = <100000 400000>;
+			elan_touchscreen: elan-touchscreen@10 {
+				compatible = "i2c-chip";
+				reg = <0x10>;
+				acpi,hid = "ELAN0001";
+				acpi,ddn = "ELAN Touchscreen";
+				interrupts-extended = <&acpi_gpe GPIO_21_IRQ
+					IRQ_TYPE_EDGE_FALLING>;
+				linux,probed;
+				reset-gpios = <&gpio_n GPIO_36 GPIO_ACTIVE_HIGH>;
+				reset-delay-ms = <20>;
+				enable-gpios = <&gpio_n GPIO_152 GPIO_ACTIVE_HIGH>;
+				enable-delay-ms = <1>;
+				acpi,has-power-resource;
+			};
+
+			raydium_touchscreen: raydium-touchscreen@39 {
+				compatible = "i2c-chip";
+				reg = <0x39>;
+				acpi,hid = "RAYD0001";
+				acpi,ddn = "Raydium Touchscreen";
+				interrupts-extended = <&acpi_gpe GPIO_21_IRQ
+					IRQ_TYPE_EDGE_FALLING>;
+				linux,probed;
+				reset-gpios = <&gpio_n GPIO_36 GPIO_ACTIVE_HIGH>;
+				reset-delay-ms = <1>;
+				enable-gpios = <&gpio_n GPIO_152 GPIO_ACTIVE_HIGH>;
+				enable-delay-ms = <50>;
+				acpi,has-power-resource;
+			};
 		};
 
 		i2c_4: i2c2@17,0 {
 			compatible = "intel,apl-i2c";
-			reg = <0x0200b110 0 0 0 0>;
+			reg = <0x0200b810 0 0 0 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 			clocks = <&clk CLK_I2C>;
 			i2c-sda-hold-time-ns = <350>;
 			i2c-scl-rising-time-ns = <114>;
 			i2c-scl-falling-time-ns = <164>;
+			clock-frequency = <400000>;
+			i2c,speeds = <100000 400000>;
+			elan_touchpad: elan-touchpad@15 {
+				compatible = "i2c-chip";
+				reg = <0x15>;
+				u-boot,i2c-offset-len = <0>;
+				acpi,hid = "ELAN0000";
+				acpi,ddn = "ELAN Touchpad";
+				interrupts-extended = <&acpi_gpe GPIO_18_IRQ
+					 IRQ_TYPE_EDGE_FALLING>;
+				acpi,wake = <GPE0_DW1_15>;
+				linux,probed;
+			};
+			synaptics_touchpad: synaptics-touchpad@2c {
+				compatible = "hid-over-i2c";
+				reg = <0x2c>;
+				acpi,hid = "PNP0C50";
+				acpi,ddn = "Synaptics Touchpad";
+				interrupts-extended = <&acpi_gpe GPIO_18_IRQ
+					 IRQ_TYPE_EDGE_FALLING>;
+				acpi,wake = <GPE0_DW1_15>;
+				linux,probed;
+				hid-descr-addr = <0x20>;
+			};
 		};
 
 		i2c_5: i2c2@17,1 {
 			compatible = "intel,apl-i2c";
-			reg = <0x0200b110 0 0 0 0>;
+			reg = <0x0200b910 0 0 0 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 			clocks = <&clk CLK_I2C>;
 			i2c-scl-rising-time-ns = <76>;
 			i2c-scl-falling-time-ns = <164>;
+			clock-frequency = <400000>;
+			i2c,speeds = <100000 400000 1000000>;
+			wacom_digitizer: wacom-digitizer@9 {
+				compatible = "hid-over-i2c";
+				reg = <0x9>;
+				acpi,hid = "WCOM50C1";
+				acpi,ddn = "WCOM Digitizer";
+				interrupts-extended = <&acpi_gpe GPIO_13_IRQ
+					(IRQ_TYPE_LEVEL_LOW | X86_IRQ_TYPE_SHARED)>;
+				hid-descr-addr = <0x1>;
+			};
 		};
 
 		i2c_6: i2c2@17,2 {
 			compatible = "intel,apl-i2c";
-			reg = <0x0200b110 0 0 0 0>;
+			reg = <0x0200ba10 0 0 0 0>;
 			clocks = <&clk CLK_I2C>;
 			status = "disabled";
 		};
 
 		i2c_7: i2c2@17,3 {
 			compatible = "intel,apl-i2c";
-			reg = <0x0200b110 0 0 0 0>;
+			reg = <0x0200bb10 0 0 0 0>;
 			clocks = <&clk CLK_I2C>;
 			status = "disabled";
 		};
@@ -347,6 +527,15 @@
 			reg-shift = <2>;
 			clock-frequency = <1843200>;
 			current-speed = <115200>;
+			acpi,name = "URT3";
+			pci,no-autoconfig;
+		};
+
+		sdmmc: sdmmc@1b,0 {
+			reg = <0x0000d800 0 0 0 0>;
+			compatible = "intel,apl-sd";
+			cd-gpios = <&gpio_n GPIO_177 GPIO_ACTIVE_LOW>;
+			acpi,name = "SDCD";
 		};
 
 		pch: pch@1f,0 {
@@ -356,7 +545,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 
-			lpc {
+			lpc: lpc {
 				compatible = "intel,apl-lpc";
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -594,12 +783,17 @@
 	 * [6:0] steps of delay for HS200, each 125ps
 	 */
 	/* Enable DPTF */
-	dptf-enable;
+	fsps,dptf-enabled;
 	fsps,emmc-tx-data-cntl1 = <0x0c16>;
 	fsps,emmc-tx-data-cntl2 = <0x28162828>;
 	fsps,emmc-rx-cmd-data-cntl1 = <0x00181717>;
 	fsps,emmc-rx-cmd-data-cntl2 = <0x10008>;
 
+	/* Enable Audio Clock and Power gating */
+	fsps,hd-audio-clk-gate = <1>;
+	fsps,hd-audio-pwr-gate = <1>;
+	fsps,bios-cfg-lock-down = <1>;
+
 	/* Enable WiFi */
 	fsps,pcie-root-port-en = [01 00 00 00 00 00];
 	fsps,pcie-rp-hot-plug = [00 00 00 00 00 00];
@@ -611,6 +805,10 @@
 	fsps,port-usb20-per-port-pe-txi-set = [07 07 06 06 07 07 07 01];
 	fsps,port-usb20-per-port-txi-set = [00 02 00 00 00 00 00 03];
 
+	fsps,lpss-s0ix-enable = <1>;
+	fsps,usb-otg = <0>;
+	fsps,monitor-mwait-enable = <0>;
+
 	/*
 	 * TODO(sjg@chromium.org): Move this to the I2C nodes
 	 * Intel Common SoC Config

+ 34 - 0
arch/x86/dts/edison.dts

@@ -22,6 +22,10 @@
 		serial2 = &serial2;
 	};
 
+	binman: binman {
+		multiple-images;
+	};
+
 	chosen {
 		stdout-path = &serial2;
 	};
@@ -130,3 +134,33 @@
 		};
 	};
 };
+
+&binman {
+	u-boot-edison {
+		filename = "u-boot-edison.img";
+
+		/* This is the OSIP */
+		blob {
+			filename = "edison-osip.dat";
+		};
+
+		u-boot {
+			offset = <0x200>;
+		};
+
+		u-boot-env {
+			offset = <0x200200>;
+			filename = "edison-environment.txt";
+			size = <0x10000>;
+			fill-byte = [ff];
+		};
+
+		u-boot-env2 {
+			type = "u-boot-env";
+			offset = <0x500200>;
+			filename = "edison-environment.txt";
+			size = <0x10000>;
+			fill-byte = [ff];
+		};
+	};
+};

+ 7 - 9
arch/x86/dts/emulation-u-boot.dtsi

@@ -7,17 +7,15 @@
 #include <u-boot.dtsi>
 
 #ifdef CONFIG_ROM_SIZE
-/ {
-	binman {
+&rom {
 #ifdef CONFIG_SPL
-		u-boot-spl-with-ucode-ptr {
-			optional-ucode;
-		};
+	u-boot-spl-with-ucode-ptr {
+		optional-ucode;
+	};
 #else
-		u-boot-with-ucode-ptr {
-			optional-ucode;
-		};
-#endif
+	u-boot-with-ucode-ptr {
+		optional-ucode;
 	};
+#endif
 };
 #endif

+ 3 - 5
arch/x86/dts/quark-u-boot.dtsi

@@ -6,11 +6,9 @@
 #include <u-boot.dtsi>
 
 #ifdef CONFIG_ROM_SIZE
-/ {
-	binman {
-		u-boot-with-ucode-ptr {
-			optional-ucode;
-		};
+&rom {
+	u-boot-with-ucode-ptr {
+		optional-ucode;
 	};
 };
 #endif

+ 0 - 7
arch/x86/dts/u-boot.dtsi

@@ -6,7 +6,6 @@
 
 #include <config.h>
 
-#ifdef CONFIG_CHROMEOS
 / {
 	binman {
 		multiple-images;
@@ -14,12 +13,6 @@
 		};
 	};
 };
-#else
-/ {
-	rom: binman {
-	};
-};
-#endif
 
 #ifdef CONFIG_ROM_SIZE
 &rom {

+ 108 - 0
arch/x86/include/asm/acpi/chromeos.asl

@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+ */
+
+#ifdef CONFIG_CHROMEOS
+
+#define CONFIG_VBOOT_VBNV_OFFSET 0x26
+
+#include <asm/acpi/vbnv_layout.h>
+
+/* GPIO package generated at run time. */
+External (OIPG)
+
+Device (CRHW)
+{
+	Name(_HID, EISAID("GGL0001"))
+
+	Method(_STA, 0, Serialized)
+	{
+		Return (0xb)
+	}
+
+	Method(CHSW, 0, Serialized)
+	{
+		Name (WSHC, Package() { VBT3 })
+		Return (WSHC)
+	}
+
+	Method(FWID, 0, Serialized)
+	{
+		Name (DIW1, "")
+		ToString(VBT5, 63, DIW1)
+		Name (DIWF, Package() { DIW1 })
+		Return(DIWF)
+	}
+
+	Method(FRID, 0, Serialized)
+	{
+		Name (DIR1, "")
+		ToString(VBT6, 63, DIR1)
+		Name (DIRF, Package() { DIR1 })
+		Return (DIRF)
+	}
+
+	Method(HWID, 0, Serialized)
+	{
+		Name (DIW0, "")
+		ToString(VBT4, 255, DIW0)
+		Name (DIWH, Package() { DIW0 })
+		Return (DIWH)
+	}
+
+	Method(BINF, 0, Serialized)
+	{
+		Name (FNIB, Package() { VBT0, VBT1, VBT2, VBT7, VBT8 })
+		Return (FNIB)
+	}
+
+	Method(GPIO, 0, Serialized)
+	{
+		Return (OIPG)
+
+	}
+
+	Method(VBNV, 0, Serialized)
+	{
+		Name(VNBV, Package() {
+			// See src/vendorcode/google/chromeos/Kconfig
+			// for the definition of these:
+			CONFIG_VBOOT_VBNV_OFFSET,
+			VBOOT_VBNV_BLOCK_SIZE
+		})
+		Return(VNBV)
+	}
+
+	Method(VDAT, 0, Serialized)
+	{
+		Name(TAD0,"")
+		ToBuffer(CHVD, TAD0)
+		Name (TADV, Package() { TAD0 })
+		Return (TADV)
+	}
+
+	Method(FMAP, 0, Serialized)
+	{
+		Name(PAMF, Package() { VBT9 })
+		Return(PAMF)
+	}
+
+	Method(MECK, 0, Serialized)
+	{
+		Name(HASH, Package() { MEHH })
+		Return(HASH)
+	}
+
+	Method(MLST, 0, Serialized)
+	{
+		Name(TSLM, Package() { "CHSW", "FWID", "HWID", "FRID", "BINF",
+			   "GPIO", "VBNV", "VDAT", "FMAP", "MECK"
+		})
+		Return (TSLM)
+	}
+}
+
+#include "ramoops.asl"
+
+#endif

+ 25 - 0
arch/x86/include/asm/acpi/cpu.asl

@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+/* These come from the dynamically created CPU SSDT */
+External (\_PR.CNOT, MethodObj)
+
+/* Notify OS to re-read CPU tables */
+Method (PNOT)
+{
+	\_PR.CNOT (0x81)
+}
+
+/* Notify OS to re-read CPU _PPC limit */
+Method (PPCN)
+{
+	\_PR.CNOT (0x80)
+}
+
+/* Notify OS to re-read Throttle Limit tables */
+Method (TNOT)
+{
+	\_PR.CNOT (0x82)
+}

+ 22 - 0
arch/x86/include/asm/acpi/cros_ec/ac.asl

@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 The Chromium OS Authors. All rights reserved.
+ */
+
+// Scope (EC0)
+
+Device (AC)
+{
+	Name (_HID, "ACPI0003")
+	Name (_PCL, Package () { \_SB })
+
+	Method (_PSR)
+	{
+		Return (ACEX)
+	}
+
+	Method (_STA)
+	{
+		Return (0x0F)
+	}
+}

+ 56 - 0
arch/x86/include/asm/acpi/cros_ec/als.asl

@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014 Google Inc.
+ */
+
+Device (ALS)
+{
+	Name (_HID, "ACPI0008")
+	Name (_UID, 1)
+
+	Method (_STA, 0, NotSerialized)
+	{
+		Return (0xF)
+	}
+
+	/*
+	 * Returns the current ambient light illuminance reading in lux
+	 *
+	 *  0: Reading is below the range of sensitivity of the sensor
+	 * -1: Reading is above the range or sensitivity of the sensor
+	 */
+	Method (_ALI, 0, NotSerialized)
+	{
+		Return (^^ALS0)
+	}
+
+	/*
+	 * Returns a recommended polling frequency in tenths of seconds
+	 *
+	 *  0: No need to poll, async notifications will indicate changes
+	 */
+	Name (_ALP, 10)
+
+	/*
+	 * Returns a package of packages where each tuple consists of a pair
+	 * of integers mapping ambient light illuminance to display brightness.
+	 *
+	 * {<display luminance adjustment>, <ambient light illuminance>}
+	 *
+	 * Ambient light illuminance values are specified in lux.
+	 *
+	 * Display luminance adjustment values are relative percentages where
+	 * 100 is no (0%) display brightness adjustment.  Values <100 indicate
+	 * negative adjustment (dimming) and values >100 indicate positive
+	 * adjustment (brightening).
+	 *
+	 * This is currently unused by the Linux kernel ACPI ALS driver but
+	 * is required by the ACPI specification so just define a basic two
+	 * point response curve.
+	 */
+	Name (_ALR, Package ()
+	{
+		Package () { 70, 30 },    // Min { -30% adjust at 30 lux }
+		Package () { 150, 1000 }  // Max { +50% adjust at 1000 lux }
+	})
+}

+ 411 - 0
arch/x86/include/asm/acpi/cros_ec/battery.asl

@@ -0,0 +1,411 @@
+/*/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
+ */
+
+// Scope (EC0)
+
+/* Mutex for EC battery index interface */
+Mutex (BATM, 0)
+
+// Wait for desired battery index to be presented in shared memory
+//   Arg0 = battery index
+//   Returns Zero on success, One on error.
+Method (BTSW, 1)
+{
+#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE
+	If (LEqual (BTIX, Arg0)) {
+		Return (Zero)
+	}
+	If (LGreaterEqual (Arg0, BTCN)) {
+		Return (One)
+	}
+	Store (Arg0, \_SB.PCI0.LPCB.EC0.BTID)
+	Store (5, Local0)      // Timeout 5 msec
+	While (LNotEqual (BTIX, Arg0))
+	{
+		Sleep (1)
+		Decrement (Local0)
+		If (LEqual (Local0, Zero))
+		{
+			Return (One)
+		}
+	}
+#else
+	If (LNotEqual (0, Arg0)) {
+		Return (One)
+	}
+#endif
+	Return (Zero)
+}
+
+// _STA implementation.
+//   Arg0 = battery index
+Method (BSTA, 1, Serialized)
+{
+	If (Acquire (^BATM, 1000)) {
+		Return (Zero)
+	}
+
+	If (And(Not(BTSW (Arg0)), BTEX)) {
+		Store (0x1F, Local0)
+	} Else {
+		Store (0x0F, Local0)
+	}
+
+	Release (^BATM)
+	Return (Local0)
+}
+
+// _BIF implementation.
+//   Arg0 = battery index
+//   Arg1 = PBIF
+Method (BBIF, 2, Serialized)
+{
+	If (Acquire (^BATM, 1000)) {
+		Return (Arg1)
+	}
+
+	If (BTSW (Arg0)) {
+		Release (^BATM)
+		Return (Arg1)
+	}
+	// Last Full Charge Capacity
+	Store (BTDF, Index (Arg1, 2))
+
+	// Design Voltage
+	Store (BTDV, Index (Arg1, 4))
+
+	// Design Capacity
+	Store (BTDA, Local0)
+	Store (Local0, Index (Arg1, 1))
+
+	// Design Capacity of Warning
+	Divide (Multiply (Local0, DWRN), 100, , Local2)
+	Store (Local2, Index (Arg1, 5))
+
+	// Design Capacity of Low
+	Divide (Multiply (Local0, DLOW), 100, , Local2)
+	Store (Local2, Index (Arg1, 6))
+
+	// Get battery info from mainboard
+	Store (ToString(Concatenate(BMOD, 0x00)), Index (Arg1, 9))
+	Store (ToString(Concatenate(BSER, 0x00)), Index (Arg1, 10))
+	Store (ToString(Concatenate(BMFG, 0x00)), Index (Arg1, 12))
+
+	Release (^BATM)
+	Return (Arg1)
+}
+
+// _BIX implementation.
+//   Arg0 = battery index
+//   Arg1 = PBIX
+Method (BBIX, 2, Serialized)
+{
+	If (Acquire (^BATM, 1000)) {
+		Return (Arg1)
+	}
+
+	If (BTSW (Arg0)) {
+		Release (^BATM)
+		Return (Arg1)
+	}
+	// Last Full Charge Capacity
+	Store (BTDF, Index (Arg1, 3))
+
+	// Design Voltage
+	Store (BTDV, Index (Arg1, 5))
+
+	// Design Capacity
+	Store (BTDA, Local0)
+	Store (Local0, Index (Arg1, 2))
+
+	// Design Capacity of Warning
+	Divide (Multiply (Local0, DWRN), 100, , Local2)
+	Store (Local2, Index (Arg1, 6))
+
+	// Design Capacity of Low
+	Divide (Multiply (Local0, DLOW), 100, , Local2)
+	Store (Local2, Index (Arg1, 7))
+
+	// Cycle Count
+	Store (BTCC, Index (Arg1, 8))
+
+	// Get battery info from mainboard
+	Store (ToString(Concatenate(BMOD, 0x00)), Index (Arg1, 16))
+	Store (ToString(Concatenate(BSER, 0x00)), Index (Arg1, 17))
+	Store (ToString(Concatenate(BMFG, 0x00)), Index (Arg1, 19))
+
+	Release (^BATM)
+	Return (Arg1)
+}
+
+// _BST implementation.
+//   Arg0 = battery index
+//   Arg1 = PBST
+//   Arg2 = BSTP
+//   Arg3 = BFWK
+Method (BBST, 4, Serialized)
+{
+	If (Acquire (^BATM, 1000)) {
+		Return (Arg1)
+	}
+
+	If (BTSW (Arg0)) {
+		Release (^BATM)
+		Return (Arg1)
+	}
+	//
+	// 0: BATTERY STATE
+	//
+	// bit 0 = discharging
+	// bit 1 = charging
+	// bit 2 = critical level
+	//
+	Store (Zero, Local1)
+
+	// Check if AC is present
+	If (ACEX) {
+		If (BFCG) {
+			Store (0x02, Local1)
+		} ElseIf (BFDC) {
+			Store (0x01, Local1)
+		}
+	} Else {
+		// Always discharging when on battery power
+		Store (0x01, Local1)
+	}
+
+	// Check for critical battery level
+	If (BFCR) {
+		Or (Local1, 0x04, Local1)
+	}
+	Store (Local1, Index (Arg1, 0))
+
+	// Notify if battery state has changed since last time
+	If (LNotEqual (Local1, DeRefOf (Arg2))) {
+		Store (Local1, Arg2)
+		If (LEqual(Arg0, 0)) {
+			Notify (BAT0, 0x80)
+		}
+#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE
+		Else {
+			Notify (BAT1, 0x80)
+		}
+#endif
+	}
+
+	//
+	// 1: BATTERY PRESENT RATE
+	//
+	Store (BTPR, Index (Arg1, 1))
+
+	//
+	// 2: BATTERY REMAINING CAPACITY
+	//
+	Store (BTRA, Local1)
+	If (LAnd (Arg3, LAnd (ACEX, LNot (LAnd (BFDC, BFCG))))) {
+		// On AC power and battery is neither charging
+		// nor discharging.  Linux expects a full battery
+		// to report same capacity as last full charge.
+		// https://bugzilla.kernel.org/show_bug.cgi?id=12632
+		Store (BTDF, Local2)
+
+		// See if within ~6% of full
+		ShiftRight (Local2, 4, Local3)
+		If (LAnd (LGreater (Local1, Subtract (Local2, Local3)),
+		          LLess (Local1, Add (Local2, Local3))))
+		{
+			Store (Local2, Local1)
+		}
+	}
+	Store (Local1, Index (Arg1, 2))
+
+	//
+	// 3: BATTERY PRESENT VOLTAGE
+	//
+	Store (BTVO, Index (Arg1, 3))
+
+	Release (^BATM)
+	Return (Arg1)
+}
+
+Device (BAT0)
+{
+	Name (_HID, EISAID ("PNP0C0A"))
+	Name (_UID, 1)
+	Name (_PCL, Package () { \_SB })
+
+	Name (PBIF, Package () {
+		0x00000001,  // 0x00: Power Unit: mAh
+		0xFFFFFFFF,  // 0x01: Design Capacity
+		0xFFFFFFFF,  // 0x02: Last Full Charge Capacity
+		0x00000001,  // 0x03: Battery Technology: Rechargeable
+		0xFFFFFFFF,  // 0x04: Design Voltage
+		0x00000003,  // 0x05: Design Capacity of Warning
+		0xFFFFFFFF,  // 0x06: Design Capacity of Low
+		0x00000001,  // 0x07: Capacity Granularity 1
+		0x00000001,  // 0x08: Capacity Granularity 2
+		"",          // 0x09: Model Number
+		"",          // 0x0a: Serial Number
+		"LION",      // 0x0b: Battery Type
+		""           // 0x0c: OEM Information
+	})
+
+	Name (PBIX, Package () {
+		0x00000000,  // 0x00: Revision
+		0x00000001,  // 0x01: Power Unit: mAh
+		0xFFFFFFFF,  // 0x02: Design Capacity
+		0xFFFFFFFF,  // 0x03: Last Full Charge Capacity
+		0x00000001,  // 0x04: Battery Technology: Rechargeable
+		0xFFFFFFFF,  // 0x05: Design Voltage
+		0x00000003,  // 0x06: Design Capacity of Warning
+		0xFFFFFFFF,  // 0x07: Design Capacity of Low
+		0x00000000,  // 0x08: Cycle Count
+		0x00018000,  // 0x09: Measurement Accuracy (98.3%?)
+		0x000001F4,  // 0x0a: Max Sampling Time (500ms)
+		0x0000000a,  // 0x0b: Min Sampling Time (10ms)
+		0xFFFFFFFF,  // 0x0c: Max Averaging Interval
+		0xFFFFFFFF,  // 0x0d: Min Averaging Interval
+		0x00000001,  // 0x0e: Capacity Granularity 1
+		0x00000001,  // 0x0f: Capacity Granularity 2
+		"",          // 0x10 Model Number
+		"",          // 0x11: Serial Number
+		"LION",      // 0x12: Battery Type
+		""           // 0x13: OEM Information
+	})
+
+	Name (PBST, Package () {
+		0x00000000,  // 0x00: Battery State
+		0xFFFFFFFF,  // 0x01: Battery Present Rate
+		0xFFFFFFFF,  // 0x02: Battery Remaining Capacity
+		0xFFFFFFFF,  // 0x03: Battery Present Voltage
+	})
+	Name (BSTP, Zero)
+
+	// Workaround for full battery status, disabled by default
+	Name (BFWK, Zero)
+
+	// Method to enable full battery workaround
+	Method (BFWE)
+	{
+		Store (One, BFWK)
+	}
+
+	// Method to disable full battery workaround
+	Method (BFWD)
+	{
+		Store (Zero, BFWK)
+	}
+
+	Method (_STA, 0, Serialized)
+	{
+		Return (BSTA (0))
+	}
+
+	Method (_BIF, 0, Serialized)
+	{
+		Return (BBIF (0, PBIF))
+	}
+
+	Method (_BIX, 0, Serialized)
+	{
+		Return (BBIX (0, PBIX))
+	}
+
+	Method (_BST, 0, Serialized)
+	{
+		Return (BBST (0, PBST, RefOf (BSTP), BFWK))
+	}
+}
+
+#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE
+Device (BAT1)
+{
+	Name (_HID, EISAID ("PNP0C0A"))
+	Name (_UID, 1)
+	Name (_PCL, Package () { \_SB })
+
+	Name (PBIF, Package () {
+		0x00000001,  // 0x00: Power Unit: mAh
+		0xFFFFFFFF,  // 0x01: Design Capacity
+		0xFFFFFFFF,  // 0x02: Last Full Charge Capacity
+		0x00000001,  // 0x03: Battery Technology: Rechargeable
+		0xFFFFFFFF,  // 0x04: Design Voltage
+		0x00000003,  // 0x05: Design Capacity of Warning
+		0xFFFFFFFF,  // 0x06: Design Capacity of Low
+		0x00000001,  // 0x07: Capacity Granularity 1
+		0x00000001,  // 0x08: Capacity Granularity 2
+		"",          // 0x09: Model Number
+		"",          // 0x0a: Serial Number
+		"LION",      // 0x0b: Battery Type
+		""           // 0x0c: OEM Information
+	})
+
+	Name (PBIX, Package () {
+		0x00000000,  // 0x00: Revision
+		0x00000001,  // 0x01: Power Unit: mAh
+		0xFFFFFFFF,  // 0x02: Design Capacity
+		0xFFFFFFFF,  // 0x03: Last Full Charge Capacity
+		0x00000001,  // 0x04: Battery Technology: Rechargeable
+		0xFFFFFFFF,  // 0x05: Design Voltage
+		0x00000003,  // 0x06: Design Capacity of Warning
+		0xFFFFFFFF,  // 0x07: Design Capacity of Low
+		0x00000000,  // 0x08: Cycle Count
+		0x00018000,  // 0x09: Measurement Accuracy (98.3%?)
+		0x000001F4,  // 0x0a: Max Sampling Time (500ms)
+		0x0000000a,  // 0x0b: Min Sampling Time (10ms)
+		0xFFFFFFFF,  // 0x0c: Max Averaging Interval
+		0xFFFFFFFF,  // 0x0d: Min Averaging Interval
+		0x00000001,  // 0x0e: Capacity Granularity 1
+		0x00000001,  // 0x0f: Capacity Granularity 2
+		"",          // 0x10 Model Number
+		"",          // 0x11: Serial Number
+		"LION",      // 0x12: Battery Type
+		""           // 0x13: OEM Information
+	})
+
+	Name (PBST, Package () {
+		0x00000000,  // 0x00: Battery State
+		0xFFFFFFFF,  // 0x01: Battery Present Rate
+		0xFFFFFFFF,  // 0x02: Battery Remaining Capacity
+		0xFFFFFFFF,  // 0x03: Battery Present Voltage
+	})
+	Name (BSTP, Zero)
+
+	// Workaround for full battery status, disabled by default
+	Name (BFWK, Zero)
+
+	// Method to enable full battery workaround
+	Method (BFWE)
+	{
+		Store (One, BFWK)
+	}
+
+	// Method to disable full battery workaround
+	Method (BFWD)
+	{
+		Store (Zero, BFWK)
+	}
+
+	Method (_STA, 0, Serialized)
+	{
+		Return (BSTA (1))
+	}
+
+	Method (_BIF, 0, Serialized)
+	{
+		Return (BBIF (1, PBIF))
+	}
+
+	Method (_BIX, 0, Serialized)
+	{
+		Return (BBIX (1, PBIX))
+	}
+
+	Method (_BST, 0, Serialized)
+	{
+		Return (BBST (1, PBST, RefOf (BSTP), BFWK))
+	}
+}
+#endif

+ 57 - 0
arch/x86/include/asm/acpi/cros_ec/cros_ec.asl

@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Google Inc.
+ */
+
+Device (CREC)
+{
+	Name (_HID, "GOOG0004")
+	Name (_UID, 1)
+	Name (_DDN, "EC Command Device")
+#ifdef EC_ENABLE_WAKE_PIN
+	Name (_PRW, Package () { EC_ENABLE_WAKE_PIN, 0x5 })
+#endif
+
+#ifdef EC_ENABLE_SYNC_IRQ
+	Name (_CRS, ResourceTemplate ()
+	{
+		Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive)
+		{
+			EC_SYNC_IRQ
+		}
+	})
+#endif
+
+#ifdef EC_ENABLE_SYNC_IRQ_GPIO
+	Name (_CRS, ResourceTemplate ()
+	{
+		GpioInt (Level, ActiveLow, Exclusive, PullDefault, 0x0000,
+		         "\\_SB.GPIO", 0x00, ResourceConsumer, ,)
+		{
+			EC_SYNC_IRQ
+		}
+	})
+#endif
+
+#ifdef EC_ENABLE_MKBP_DEVICE
+	Device (CKSC)
+	{
+		Name (_HID, "GOOG0007")
+		Name (_UID, 1)
+		Name (_DDN, "EC MKBP Device")
+	}
+#endif
+
+#ifdef EC_ENABLE_CBAS_DEVICE
+	Device (CBAS)
+	{
+		Name (_HID, "GOOG000B")
+		Name (_UID, 1)
+		Name (_DDN, "EC Base Switch Device")
+	}
+#endif
+	Method(_STA, 0)
+	{
+		Return (0xB)
+	}
+}

+ 557 - 0
arch/x86/include/asm/acpi/cros_ec/ec.asl

@@ -0,0 +1,557 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 The Chromium OS Authors. All rights reserved.
+ */
+
+/*
+ * The mainboard must define a PNOT method to handle power
+ * state notifications and Notify CPU device objects to
+ * re-evaluate their _PPC and _CST tables.
+ */
+
+// Mainboard specific throttle handler
+#ifdef DPTF_ENABLE_CHARGER
+External (\_SB.DPTF.TCHG, DeviceObj)
+#endif
+
+
+Device (EC0)
+{
+	Name (_HID, EISAID ("PNP0C09"))
+	Name (_UID, 1)
+	Name (_GPE, EC_SCI_GPI)
+	Name (TOFS, EC_TEMP_SENSOR_OFFSET)
+	Name (TNCA, EC_TEMP_SENSOR_NOT_CALIBRATED)
+	Name (TNOP, EC_TEMP_SENSOR_NOT_POWERED)
+	Name (TBAD, EC_TEMP_SENSOR_ERROR)
+	Name (TNPR, EC_TEMP_SENSOR_NOT_PRESENT)
+	Name (DWRN, 15)		// Battery capacity warning at 15%
+	Name (DLOW, 10)		// Battery capacity low at 10%
+
+	OperationRegion (ERAM, EmbeddedControl, 0x00, EC_ACPI_MEM_MAPPED_BEGIN)
+	Field (ERAM, ByteAcc, Lock, Preserve)
+	{
+		Offset (0x00),
+		RAMV, 8,	// EC RAM Version
+		TSTB, 8,	// Test Byte
+		TSTC, 8,	// Complement of Test Byte
+		KBLV, 8,	// Keyboard Backlight value
+		FAND, 8,	// Set Fan Duty Cycle
+		PATI, 8,	// Programmable Auxiliary Trip Sensor ID
+		PATT, 8,	// Programmable Auxiliary Trip Threshold
+		PATC, 8,	// Programmable Auxiliary Trip Commit
+		CHGL, 8,	// Charger Current Limit
+		TBMD, 1,	// Tablet mode
+		DDPN, 3,	// Device DPTF Profile Number
+		// DFUD must be 0 for the other 31 values to be valid
+		Offset (0x0a),
+		DFUD, 1,	// Device Features Undefined
+		FLSH, 1,	// Flash commands present
+		PFAN, 1,	// PWM Fan control present
+		KBLE, 1,	// Keyboard Backlight present
+		LTBR, 1,	// Lightbar present
+		LEDC, 1,	// LED control
+		MTNS, 1,	// Motion sensors present
+		KEYB, 1,	// EC is keyboard controller
+		PSTR, 1,	// Persistent storage
+		P80P, 1,	// EC serves I/O Port 80h
+		THRM, 1,	// EC supports thermal management
+		SBKL, 1,	// Screen backlight switch present
+		WIFI, 1,	// WIFI switch present
+		HOST, 1,	// EC monitors host events (eg SCI, SMI)
+		GPIO, 1,	// EC provides GPIO commands
+		I2CB, 1,	// EC provides I2C controller access
+		CHRG, 1,	// EC provides commands for charger control
+		BATT, 1,	// Simply Battery support
+		SBAT, 1,	// Smart Battery support
+		HANG, 1,	// EC can detect host hang
+		PMUI, 1,	// Power Information
+		DSEC, 1,	// another EC exists downstream
+		UPDC, 1,	// supports USB Power Delivery
+		UMUX, 1,	// supports USB Mux
+		MSFF, 1,	// Motion Sense has FIFO
+		TVST, 1,	// supports temporary secure vstore
+		TCMV, 1,	// USB Type C Muxing is virtual (host assisted)
+		RTCD, 1,	// EC provides an RTC device
+		FPRD, 1,	// EC provides a fingerprint reader device
+		TPAD, 1,	// EC provides a touchpad device
+		RWSG, 1,	// EC has RWSIG task enabled
+		DEVE, 1,	// EC supports device events
+		// make sure we're within our space envelope
+		Offset (0x0e),
+		Offset (0x12),
+		BTID, 8,	// Battery index that host wants to read
+		USPP, 8,	// USB Port Power
+}
+
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_ACPI_MEMMAP)
+	OperationRegion (EMEM, EmbeddedControl,
+			 EC_ACPI_MEM_MAPPED_BEGIN, EC_ACPI_MEM_MAPPED_SIZE)
+	Field (EMEM, ByteAcc, Lock, Preserve)
+#else
+	OperationRegion (EMEM, SystemIO, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE)
+	Field (EMEM, ByteAcc, NoLock, Preserve)
+#endif
+	{
+		#include "emem.asl"
+	}
+
+#ifdef EC_ENABLE_LID_SWITCH
+	/* LID Switch */
+	Device (LID0)
+	{
+		Name (_HID, EisaId ("PNP0C0D"))
+		Method (_LID, 0)
+		{
+			Return (^^LIDS)
+		}
+
+#ifdef EC_ENABLE_WAKE_PIN
+		Name (_PRW, Package () { EC_ENABLE_WAKE_PIN, 0x5 })
+#endif
+	}
+#endif
+
+	Method (TINS, 1, Serialized)
+	{
+		Switch (ToInteger (Arg0))
+		{
+			Case (0) { Return (TIN0) }
+			Case (1) { Return (TIN1) }
+			Case (2) { Return (TIN2) }
+			Case (3) { Return (TIN3) }
+			Case (4) { Return (TIN4) }
+			Case (5) { Return (TIN5) }
+			Case (6) { Return (TIN6) }
+			Case (7) { Return (TIN7) }
+			Case (8) { Return (TIN8) }
+			Case (9) { Return (TIN9) }
+			Default  { Return (TIN0) }
+		}
+	}
+
+	Method (_CRS, 0, Serialized)
+	{
+		Name (ECMD, ResourceTemplate()
+		{
+			IO (Decode16,
+			    EC_LPC_ADDR_ACPI_DATA,
+			    EC_LPC_ADDR_ACPI_DATA,
+			    0, 1)
+			IO (Decode16,
+			    EC_LPC_ADDR_ACPI_CMD,
+			    EC_LPC_ADDR_ACPI_CMD,
+			    0, 1)
+		})
+		Return (ECMD)
+	}
+
+	Method (_REG, 2, NotSerialized)
+	{
+		// Initialize AC power state
+		Store (ACEX, \PWRS)
+
+		// Initialize LID switch state
+		Store (LIDS, \LIDS)
+	}
+
+	/* Read requested temperature and check against EC error values */
+	Method (TSRD, 1, Serialized)
+	{
+		Store (\_SB.PCI0.LPCB.EC0.TINS (Arg0), Local0)
+
+		/* Check for sensor not calibrated */
+		If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNCA)) {
+			Return (Zero)
+		}
+
+		/* Check for sensor not present */
+		If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNPR)) {
+			Return (Zero)
+		}
+
+		/* Check for sensor not powered */
+		If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNOP)) {
+			Return (Zero)
+		}
+
+		/* Check for sensor bad reading */
+		If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TBAD)) {
+			Return (Zero)
+		}
+
+		/* Adjust by offset to get Kelvin */
+		Add (\_SB.PCI0.LPCB.EC0.TOFS, Local0, Local0)
+
+		/* Convert to 1/10 Kelvin */
+		Multiply (Local0, 10, Local0)
+
+		Return (Local0)
+	}
+
+	// Lid Closed Event
+	Method (_Q01, 0, NotSerialized)
+	{
+		Store ("EC: LID CLOSE", Debug)
+		Store (LIDS, \LIDS)
+#ifdef EC_ENABLE_LID_SWITCH
+		Notify (LID0, 0x80)
+#endif
+	}
+
+	// Lid Open Event
+	Method (_Q02, 0, NotSerialized)
+	{
+		Store ("EC: LID OPEN", Debug)
+		Store (LIDS, \LIDS)
+		Notify (CREC, 0x2)
+#ifdef EC_ENABLE_LID_SWITCH
+		Notify (LID0, 0x80)
+#endif
+	}
+
+	// Power Button
+	Method (_Q03, 0, NotSerialized)
+	{
+		Store ("EC: POWER BUTTON", Debug)
+	}
+
+	// AC Connected
+	Method (_Q04, 0, NotSerialized)
+	{
+		Store ("EC: AC CONNECTED", Debug)
+		Store (ACEX, \PWRS)
+		Notify (AC, 0x80)
+#ifdef DPTF_ENABLE_CHARGER
+		If (CondRefOf (\_SB.DPTF.TCHG)) {
+			Notify (\_SB.DPTF.TCHG, 0x80)
+		}
+#endif
+		\PNOT ()
+	}
+
+	// AC Disconnected
+	Method (_Q05, 0, NotSerialized)
+	{
+		Store ("EC: AC DISCONNECTED", Debug)
+		Store (ACEX, \PWRS)
+		Notify (AC, 0x80)
+#ifdef DPTF_ENABLE_CHARGER
+		If (CondRefOf (\_SB.DPTF.TCHG)) {
+			Notify (\_SB.DPTF.TCHG, 0x80)
+		}
+#endif
+		\PNOT ()
+	}
+
+	// Battery Low Event
+	Method (_Q06, 0, NotSerialized)
+	{
+		Store ("EC: BATTERY LOW", Debug)
+		Notify (BAT0, 0x80)
+	}
+
+	// Battery Critical Event
+	Method (_Q07, 0, NotSerialized)
+	{
+		Store ("EC: BATTERY CRITICAL", Debug)
+		Notify (BAT0, 0x80)
+	}
+
+	// Battery Info Event
+	Method (_Q08, 0, NotSerialized)
+	{
+		Store ("EC: BATTERY INFO", Debug)
+		Notify (BAT0, 0x81)
+#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE
+		If (CondRefOf (BAT1)) {
+			Notify (BAT1, 0x81)
+		}
+#endif
+	}
+
+	// Thermal Overload Event
+	Method (_Q0A, 0, NotSerialized)
+	{
+		Store ("EC: THERMAL OVERLOAD", Debug)
+		Notify (\_TZ, 0x80)
+	}
+
+	// Thermal Event
+	Method (_Q0B, 0, NotSerialized)
+	{
+		Store ("EC: THERMAL", Debug)
+		Notify (\_TZ, 0x80)
+	}
+
+	// USB Charger
+	Method (_Q0C, 0, NotSerialized)
+	{
+		Store ("EC: USB CHARGER", Debug)
+	}
+
+	// Key Pressed
+	Method (_Q0D, 0, NotSerialized)
+	{
+		Store ("EC: KEY PRESSED", Debug)
+		Notify (CREC, 0x2)
+	}
+
+	// Thermal Shutdown Imminent
+	Method (_Q10, 0, NotSerialized)
+	{
+		Store ("EC: THERMAL SHUTDOWN", Debug)
+		Notify (\_TZ, 0x80)
+	}
+
+	// Battery Shutdown Imminent
+	Method (_Q11, 0, NotSerialized)
+	{
+		Store ("EC: BATTERY SHUTDOWN", Debug)
+		Notify (BAT0, 0x80)
+	}
+
+	// Throttle Start
+	Method (_Q12, 0, NotSerialized)
+	{
+#ifdef EC_ENABLE_THROTTLING_HANDLER
+		Store ("EC: THROTTLE START", Debug)
+		\_TZ.THRT (1)
+#endif
+	}
+
+	// Throttle Stop
+	Method (_Q13, 0, NotSerialized)
+	{
+#ifdef EC_ENABLE_THROTTLING_HANDLER
+		Store ("EC: THROTTLE STOP", Debug)
+		\_TZ.THRT (0)
+#endif
+	}
+
+#ifdef EC_ENABLE_PD_MCU_DEVICE
+	// PD event
+	Method (_Q16, 0, NotSerialized)
+	{
+		Store ("EC: GOT PD EVENT", Debug)
+		Notify (ECPD, 0x80)
+	}
+#endif
+
+	// Battery Status
+	Method (_Q17, 0, NotSerialized)
+	{
+		Store ("EC: BATTERY STATUS", Debug)
+		Notify (BAT0, 0x80)
+#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE
+		If (CondRefOf (BAT1)) {
+			Notify (BAT1, 0x80)
+		}
+#endif
+	}
+
+	// MKBP interrupt.
+	Method (_Q1B, 0, NotSerialized)
+	{
+		Store ("EC: MKBP", Debug)
+		Notify (CREC, 0x80)
+	}
+
+	// TABLET mode switch Event
+	Method (_Q1D, 0, NotSerialized)
+	{
+		Store ("EC: TABLET mode switch Event", Debug)
+		Notify (CREC, 0x2)
+#ifdef EC_ENABLE_MULTIPLE_DPTF_PROFILES
+		\_SB.DPTF.TPET()
+#endif
+#ifdef EC_ENABLE_TBMC_DEVICE
+		Notify (TBMC, 0x80)
+#endif
+	}
+
+	/*
+	 * Dynamic Platform Thermal Framework support
+	 */
+
+	/* Mutex for EC PAT interface */
+	Mutex (PATM, 1)
+
+	/*
+	 * Set Aux Trip Point 0
+	 *   Arg0 = Temp Sensor ID
+	 *   Arg1 = Value to set
+	 */
+	Method (PAT0, 2, Serialized)
+	{
+		If (Acquire (^PATM, 1000)) {
+			Return (0)
+		}
+
+		/* Set sensor ID */
+		Store (ToInteger (Arg0), ^PATI)
+
+		/* Temperature is passed in 1/10 Kelvin */
+		Divide (ToInteger (Arg1), 10, , Local1)
+
+		/* Adjust by EC temperature offset */
+		Subtract (Local1, ^TOFS, ^PATT)
+
+		/* Set commit value with SELECT=0 and ENABLE=1 */
+		Store (0x02, ^PATC)
+
+		Release (^PATM)
+		Return (1)
+	}
+
+	/*
+	 * Set Aux Trip Point 1
+	 *   Arg0 = Temp Sensor ID
+	 *   Arg1 = Value to set
+	 */
+	Method (PAT1, 2, Serialized)
+	{
+		If (Acquire (^PATM, 1000)) {
+			Return (0)
+		}
+
+		/* Set sensor ID */
+		Store (ToInteger (Arg0), ^PATI)
+
+		/* Temperature is passed in 1/10 Kelvin */
+		Divide (ToInteger (Arg1), 10, , Local1)
+
+		/* Adjust by EC temperature offset */
+		Subtract (Local1, ^TOFS, ^PATT)
+
+		/* Set commit value with SELECT=1 and ENABLE=1 */
+		Store (0x03, ^PATC)
+
+		Release (^PATM)
+		Return (1)
+	}
+
+	/* Disable Aux Trip Points
+	 *   Arg0 = Temp Sensor ID
+	 */
+	Method (PATD, 1, Serialized)
+	{
+		If (Acquire (^PATM, 1000)) {
+			Return (0)
+		}
+
+		Store (ToInteger (Arg0), ^PATI)
+		Store (0x00, ^PATT)
+
+		/* Disable PAT0 */
+		Store (0x00, ^PATC)
+
+		/* Disable PAT1 */
+		Store (0x01, ^PATC)
+
+		Release (^PATM)
+		Return (1)
+	}
+
+	/*
+	 * Thermal Threshold Event
+	 */
+	Method (_Q09, 0, NotSerialized)
+	{
+		If (LNot(Acquire (^PATM, 1000))) {
+			/* Read sensor ID for event */
+			Store (^PATI, Local0)
+
+			/* When sensor ID returns 0xFF then no more events */
+			While (LNotEqual (Local0, EC_TEMP_SENSOR_NOT_PRESENT))
+			{
+#ifdef HAVE_THERM_EVENT_HANDLER
+				\_SB.DPTF.TEVT (Local0)
+#endif
+
+				/* Keep reaading sensor ID for event */
+				Store (^PATI, Local0)
+			}
+
+			Release (^PATM)
+		}
+	}
+
+	/*
+	 * Set Charger Current Limit
+	 *   Arg0 = Current Limit in 64mA steps
+	 */
+	Method (CHGS, 1, Serialized)
+	{
+		Store (ToInteger (Arg0), ^CHGL)
+	}
+
+	/*
+	 * Disable Charger Current Limit
+	 */
+	Method (CHGD, 0, Serialized)
+	{
+		Store (0xFF, ^CHGL)
+	}
+
+	/* Read current Tablet mode */
+	Method (RCTM, 0, NotSerialized)
+	{
+		Return (^TBMD)
+	}
+
+	/* Read current Device DPTF Profile Number */
+	Method (RCDP, 0, NotSerialized)
+	{
+		/*
+		 * DDPN = 0 is reserved for backwards compatibility.
+		 * If DDPN == 0 use TBMD to load appropriate DPTF table.
+		 */
+		If (LEqual (^DDPN, 0)) {
+			Return (^TBMD)
+		} Else {
+			Subtract (^DDPN, 1, Local0)
+			Return (Local0)
+		}
+	}
+
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_ACPI_USB_PORT_POWER)
+	/*
+	 * Enable USB Port Power
+	 *   Arg0 = USB port ID
+	 */
+	Method (UPPS, 1, Serialized)
+	{
+		Or (USPP, ShiftLeft (1, Arg0), USPP)
+	}
+
+	/*
+	 * Disable USB Port Power
+	 *   Arg0 = USB port ID
+	 */
+	Method (UPPC, 1, Serialized)
+	{
+		And (USPP, Not (ShiftLeft (1, Arg0)), USPP)
+	}
+#endif
+
+	#include "ac.asl"
+	#include "battery.asl"
+	#include "cros_ec.asl"
+
+#ifdef EC_ENABLE_ALS_DEVICE
+	#include "als.asl"
+#endif
+
+#ifdef EC_ENABLE_KEYBOARD_BACKLIGHT
+	#include "keyboard_backlight.asl"
+#endif
+
+#ifdef EC_ENABLE_PD_MCU_DEVICE
+	#include "pd.asl"
+#endif
+
+#ifdef EC_ENABLE_TBMC_DEVICE
+	#include "tbmc.asl"
+#endif
+}

+ 53 - 0
arch/x86/include/asm/acpi/cros_ec/emem.asl

@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2015 The Chromium OS Authors. All rights reserved.
+ */
+
+/*
+ * EMEM data may be accessed through port 62/66 or through LPC at 900h.
+ */
+
+Offset (0x00),
+TIN0, 8,	// Temperature 0
+TIN1, 8,	// Temperature 1
+TIN2, 8,	// Temperature 2
+TIN3, 8,	// Temperature 3
+TIN4, 8,	// Temperature 4
+TIN5, 8,	// Temperature 5
+TIN6, 8,	// Temperature 6
+TIN7, 8,	// Temperature 7
+TIN8, 8,	// Temperature 8
+TIN9, 8,	// Temperature 9
+Offset (0x10),
+FAN0, 16,	// Fan Speed 0
+Offset (0x24),
+BTVR, 8,	// Battery structure version
+Offset (0x30),
+LIDS, 1,	// Lid Switch State
+PBTN, 1,	// Power Button Pressed
+WPDI, 1,	// Write Protect Disabled
+RECK, 1,	// Keyboard Initiated Recovery
+RECD, 1,	// Dedicated Recovery Mode
+Offset (0x40),
+BTVO, 32,	// Battery Present Voltage
+BTPR, 32,	// Battery Present Rate
+BTRA, 32,	// Battery Remaining Capacity
+ACEX, 1,	// AC Present
+BTEX, 1,	// Battery Present
+BFDC, 1,	// Battery Discharging
+BFCG, 1,	// Battery Charging
+BFCR, 1,	// Battery Level Critical
+Offset (0x4d),
+BTCN, 8,	// Battery Count
+BTIX, 8,	// Battery index
+Offset (0x50),
+BTDA, 32,	// Battery Design Capacity
+BTDV, 32,	// Battery Design Voltage
+BTDF, 32,	// Battery Last Full Charge Capacity
+BTCC, 32,	// Battery Cycle Count
+BMFG, 64,	// Battery Manufacturer String
+BMOD, 64,	// Battery Model String
+BSER, 64,	// Battery Serial String
+BTYP, 64,	// Battery Type String
+Offset (0x80),
+ALS0, 16,	// ALS reading 0 in lux

+ 52 - 0
arch/x86/include/asm/acpi/cros_ec/keyboard_backlight.asl

@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2015 Google Inc.
+ */
+
+Scope (\_SB)
+{
+	/*
+	 * Chrome EC Keyboard Backlight interface
+	 */
+	Device (KBLT)
+	{
+		Name (_HID, "GOOG0002")
+		Name (_UID, 1)
+
+		/* Ask EC if we even have a backlight
+		 * Return 0xf (present, enabled, show in UI, functioning) or 0
+		 *
+		 * With older EC codebases that don't support the Device
+		 * Features bitfield, this reports the keyboard backlight as
+		 * enabled since reads to undefined addresses in EC address
+		 * space return 0xff and so KBLE will be 1.
+		 */
+		Method (_STA, 0, NotSerialized)
+		{
+			/* If query is unsupported, but this code is compiled
+			 * in, assume the backlight exists physically.
+			 */
+			If (LEqual (1, \_SB.PCI0.LPCB.EC0.DFUD)) {
+				Return (0xf)
+			}
+			/* If EC reports that backlight exists, trust it */
+			If (LEqual (1, \_SB.PCI0.LPCB.EC0.KBLE)) {
+				Return (0xf)
+			}
+			/* Otherwise: no device -> disable */
+			Return (0)
+		}
+
+		/* Read current backlight value */
+		Method (KBQC, 0, NotSerialized)
+		{
+			Return (\_SB.PCI0.LPCB.EC0.KBLV)
+		}
+
+		/* Write new backlight value */
+		Method (KBCM, 1, NotSerialized)
+		{
+			Store (Arg0, \_SB.PCI0.LPCB.EC0.KBLV)
+		}
+	}
+}

+ 15 - 0
arch/x86/include/asm/acpi/cros_ec/pd.asl

@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014 Google Inc.
+ */
+
+Device (ECPD)
+{
+	Name (_HID, "GOOG0003")
+	Name (_UID, 1)
+	Name (_DDN, "EC PD Device")
+	Method(_STA, 0)
+	{
+		Return (0xB)
+	}
+}

+ 159 - 0
arch/x86/include/asm/acpi/cros_ec/superio.asl

@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 The ChromiumOS Authors.  All rights reserved.
+ */
+
+/*
+ * Chrome OS Embedded Controller interface
+ *
+ * Constants that should be defined:
+ *
+ * SIO_EC_MEMMAP_ENABLE     : Enable EC LPC memory map resources
+ * EC_LPC_ADDR_MEMMAP       : Base address of memory map range
+ * EC_MEMMAP_SIZE           : Size of memory map range
+ *
+ * SIO_EC_HOST_ENABLE       : Enable EC host command interface resources
+ * EC_LPC_ADDR_HOST_DATA    : EC host command interface data port
+ * EC_LPC_ADDR_HOST_CMD     : EC host command interface command port
+ * EC_HOST_CMD_REGION0      : EC host command buffer
+ * EC_HOST_CMD_REGION1      : EC host command buffer
+ * EC_HOST_CMD_REGION_SIZE  : EC host command buffer size
+ */
+
+// Scope is \_SB.PCI0.LPCB
+
+Device (SIO) {
+	Name (_UID, 0)
+	Name (_ADR, 0)
+
+#ifdef SIO_EC_MEMMAP_ENABLE
+	Device (ECMM) {
+		Name (_HID, EISAID ("PNP0C02"))
+		Name (_UID, 4)
+
+		Method (_STA, 0, NotSerialized) {
+			Return (0x0F)
+		}
+
+		Name (_CRS, ResourceTemplate ()
+		{
+			IO (Decode16, EC_LPC_ADDR_MEMMAP, EC_LPC_ADDR_MEMMAP,
+			    0x08, EC_MEMMAP_SIZE)
+		})
+
+		Name (_PRS, ResourceTemplate ()
+		{
+			IO (Decode16, EC_LPC_ADDR_MEMMAP, EC_LPC_ADDR_MEMMAP,
+			    0x08, EC_MEMMAP_SIZE)
+		})
+	}
+#endif
+
+#ifdef SIO_EC_HOST_ENABLE
+	Device (ECUI) {
+		Name (_HID, EISAID ("PNP0C02"))
+		Name (_UID, 3)
+
+		Method (_STA, 0, NotSerialized) {
+			Return (0x0F)
+		}
+
+		Name (_CRS, ResourceTemplate ()
+		{
+			IO (Decode16,
+			    EC_LPC_ADDR_HOST_DATA, EC_LPC_ADDR_HOST_DATA,
+			    0x01, 0x01)
+			IO (Decode16,
+			    EC_LPC_ADDR_HOST_CMD, EC_LPC_ADDR_HOST_CMD,
+			    0x01, 0x01)
+			IO (Decode16,
+			    EC_HOST_CMD_REGION0, EC_HOST_CMD_REGION0, 0x08,
+			    EC_HOST_CMD_REGION_SIZE)
+			IO (Decode16,
+			    EC_HOST_CMD_REGION1, EC_HOST_CMD_REGION1, 0x08,
+			    EC_HOST_CMD_REGION_SIZE)
+		})
+
+		Name (_PRS, ResourceTemplate ()
+		{
+			StartDependentFn (0, 0) {
+				IO (Decode16, EC_LPC_ADDR_HOST_DATA,
+				    EC_LPC_ADDR_HOST_DATA, 0x01, 0x01)
+				IO (Decode16, EC_LPC_ADDR_HOST_CMD,
+				    EC_LPC_ADDR_HOST_CMD, 0x01, 0x01)
+				IO (Decode16,
+				    EC_HOST_CMD_REGION0, EC_HOST_CMD_REGION0,
+				    0x08, EC_HOST_CMD_REGION_SIZE)
+				IO (Decode16,
+				    EC_HOST_CMD_REGION1, EC_HOST_CMD_REGION1,
+				    0x08, EC_HOST_CMD_REGION_SIZE)
+			}
+			EndDependentFn ()
+		})
+	}
+#endif
+
+#ifdef SIO_EC_ENABLE_COM1
+	Device (COM1) {
+		Name (_HID, EISAID ("PNP0501"))
+		Name (_UID, 1)
+
+		Method (_STA, 0, NotSerialized) {
+			Return (0x0F)
+		}
+
+		Name (_CRS, ResourceTemplate ()
+		{
+			IO (Decode16, 0x03F8, 0x3F8, 0x08, 0x08)
+			IRQNoFlags () {4}
+		})
+
+		Name (_PRS, ResourceTemplate ()
+		{
+			StartDependentFn (0, 0) {
+				IO (Decode16, 0x03F8, 0x3F8, 0x08, 0x08)
+				IRQNoFlags () {4}
+			}
+			EndDependentFn ()
+		})
+	}
+#endif
+}
+
+#ifdef SIO_EC_ENABLE_PS2K
+Device (PS2K)		// Keyboard
+{
+	Name (_UID, 0)
+	Name (_HID, "GOOG000A")
+	Name (_CID, Package() { EISAID("PNP0303"), EISAID("PNP030B") } )
+
+	Method (_STA, 0, NotSerialized) {
+		Return (0x0F)
+	}
+
+	Name (_CRS, ResourceTemplate()
+	{
+		IO (Decode16, 0x60, 0x60, 0x01, 0x01)
+		IO (Decode16, 0x64, 0x64, 0x01, 0x01)
+#ifdef SIO_EC_PS2K_IRQ
+		SIO_EC_PS2K_IRQ
+#else
+		IRQ (Edge, ActiveHigh, Exclusive) {1}
+#endif
+	})
+
+	Name (_PRS, ResourceTemplate()
+	{
+		StartDependentFn (0, 0) {
+			IO (Decode16, 0x60, 0x60, 0x01, 0x01)
+			IO (Decode16, 0x64, 0x64, 0x01, 0x01)
+#ifdef SIO_EC_PS2K_IRQ
+			SIO_EC_PS2K_IRQ
+#else
+			IRQ (Edge, ActiveHigh, Exclusive) {1}
+#endif
+		}
+		EndDependentFn ()
+	})
+}
+#endif

+ 23 - 0
arch/x86/include/asm/acpi/cros_ec/tbmc.asl

@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2017 Google Inc.
+ */
+
+Device (TBMC)
+{
+	Name (_HID, "GOOG0006")
+	Name (_UID, 1)
+	Name (_DDN, "Tablet Motion Control")
+	Method (TBMC)
+	{
+		If (LEqual (^^RCTM, One)) {
+			Return (0x1)
+		} Else {
+			Return (0x0)
+		}
+	}
+	Method(_STA, 0)
+	{
+		Return (0xB)
+	}
+}

+ 29 - 0
arch/x86/include/asm/acpi/cros_gnvs.asl

@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+/* This is the ChromeOS specific ACPI information needed by
+ * the mainboard's chromeos.asl
+ */
+
+VBT0,   32,	// 0x000 - Boot Reason
+VBT1,   32,	// 0x004 - Active Main Firmware
+VBT2,   32,	// 0x008 - Active EC Firmware
+VBT3,   16,	// 0x00c - CHSW
+VBT4, 2048,	// 0x00e - HWID
+VBT5,  512,	// 0x10e - FWID
+VBT6,  512,	// 0x14e - FRID
+VBT7,   32,	// 0x18e - active main firmware type
+VBT8,   32,	// 0x192 - Recovery Reason
+VBT9,   32,	// 0x196 - FMAP base address
+CHVD, 24576,	// 0x19a - VDAT space filled by verified boot
+VBTA,	32,	// 0xd9a - pointer to smbios FWID
+MEHH,  256,	// 0xd9e - Management Engine Hash
+RMOB,   32,	// 0xdbe - RAM oops base address
+RMOL,   32,	// 0xdc2 - RAM oops length
+ROVP,	32,	// 0xdc6 - pointer to RO_VPD
+ROVL,	32,	// 0xdca - size of RO_VPD
+RWVP,	32,	// 0xdce - pointer to RW_VPD
+RWVL,	32,	// 0xdd2 - size of RW_VPD
+		// 0xdd6

+ 65 - 0
arch/x86/include/asm/acpi/dptf/charger.asl

@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+Device (TCHG)
+{
+	Name (_HID, "INT3403")
+	Name (_UID, 0)
+	Name (PTYP, 0x0B)
+	Name (_STR, Unicode("Battery Charger"))
+
+	Method (_STA)
+	{
+		If (LEqual (\DPTE, One)) {
+			Return (0xF)
+		} Else {
+			Return (0x0)
+		}
+	}
+
+	/* Return charger performance states defined by mainboard */
+	Method (PPSS)
+	{
+		Return (\_SB.CHPS)
+	}
+
+	/* Return maximum charger current limit */
+	Method (PPPC)
+	{
+		/* Convert size of PPSS table to index */
+		Store (SizeOf (\_SB.CHPS), Local0)
+		Decrement (Local0)
+
+		/* Check if charging is disabled (AC removed) */
+		If (LEqual (\_SB.PCI0.LPCB.EC0.ACEX, Zero)) {
+			/* Return last power state */
+			Return (Local0)
+		} Else {
+			/* Return highest power state */
+			Return (0)
+		}
+
+		Return (0)
+	}
+
+	/* Set charger current limit */
+	Method (SPPC, 1)
+	{
+		/* Retrieve Control (index 4) for specified PPSS level */
+		Store (DeRefOf (Index (DeRefOf (Index
+			(\_SB.CHPS, ToInteger (Arg0))), 4)), Local0)
+
+		/* Pass Control value to EC to limit charging */
+		\_SB.PCI0.LPCB.EC0.CHGS (Local0)
+	}
+
+	/* Initialize charger participant */
+	Method (INIT)
+	{
+		/* Disable charge limit */
+		\_SB.PCI0.LPCB.EC0.CHGD ()
+	}
+}

+ 186 - 0
arch/x86/include/asm/acpi/dptf/cpu.asl

@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+External (\_PR.CP00._PSS, PkgObj)
+External (\_PR.CP00._TSS, PkgObj)
+External (\_PR.CP00._TPC, MethodObj)
+External (\_PR.CP00._PTC, PkgObj)
+External (\_PR.CP00._TSD, PkgObj)
+External (\_SB.MPDL, IntObj)
+
+Device (DPTF_CPU_DEVICE)
+{
+	Name(_ADR, DPTF_CPU_ADDR)
+
+	Method (_STA)
+	{
+		If (LEqual (\DPTE, One)) {
+			Return (0xF)
+		} Else {
+			Return (0x0)
+		}
+	}
+
+	/*
+	 * Processor Throttling Controls
+	 */
+
+	Method (_TSS)
+	{
+		If (CondRefOf (\_PR.CP00._TSS)) {
+			Return (\_PR.CP00._TSS)
+		} Else {
+			Return (Package ()
+			{
+				Package () { 0, 0, 0, 0, 0 }
+			})
+		}
+	}
+
+	Method (_TPC)
+	{
+		If (CondRefOf (\_PR.CP00._TPC)) {
+			Return (\_PR.CP00._TPC)
+		} Else {
+			Return (0)
+		}
+	}
+
+	Method (_PTC)
+	{
+		If (CondRefOf (\_PR.CP00._PTC)) {
+			Return (\_PR.CP00._PTC)
+		} Else {
+			Return (Package ()
+			{
+				Buffer () { 0 },
+				Buffer () { 0 }
+			})
+		}
+	}
+
+	Method (_TSD)
+	{
+		If (CondRefOf (\_PR.CP00._TSD)) {
+			Return (\_PR.CP00._TSD)
+		} Else {
+			Return (Package ()
+			{
+				Package () { 5, 0, 0, 0, 0 }
+			})
+		}
+	}
+
+	Method (_TDL)
+	{
+		If (CondRefOf (\_PR.CP00._TSS)) {
+			Store (SizeOf (\_PR.CP00._TSS), Local0)
+			Decrement (Local0)
+			Return (Local0)
+		} Else {
+			Return (0)
+		}
+	}
+
+	/*
+	 * Processor Performance Control
+	 */
+
+	Method (_PPC)
+	{
+		Return (0)
+	}
+
+	Method (SPPC, 1)
+	{
+		Store (Arg0, \PPCM)
+
+		/* Notify OS to re-read _PPC limit on each CPU */
+		\PPCN ()
+	}
+
+	Method (_PSS)
+	{
+		If (CondRefOf (\_PR.CP00._PSS)) {
+			Return (\_PR.CP00._PSS)
+		} Else {
+			Return (Package ()
+			{
+				Package () { 0, 0, 0, 0, 0, 0 }
+			})
+		}
+	}
+
+
+	Method (_PDL)
+	{
+		/* Check for mainboard specific _PDL override */
+		If (CondRefOf (\_SB.MPDL)) {
+			Return (\_SB.MPDL)
+		} ElseIf (CondRefOf (\_PR.CP00._PSS)) {
+			Store (SizeOf (\_PR.CP00._PSS), Local0)
+			Decrement (Local0)
+			Return (Local0)
+		} Else {
+			Return (0)
+		}
+	}
+
+	/* Return PPCC table defined by mainboard */
+	Method (PPCC)
+	{
+		Return (\_SB.MPPC)
+	}
+
+#ifdef DPTF_CPU_CRITICAL
+	Method (_CRT)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_CPU_CRITICAL))
+	}
+#endif
+
+#ifdef DPTF_CPU_PASSIVE
+	Method (_PSV)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_CPU_PASSIVE))
+	}
+#endif
+
+#ifdef DPTF_CPU_ACTIVE_AC0
+	Method (_AC0)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_CPU_ACTIVE_AC0))
+	}
+#endif
+
+#ifdef DPTF_CPU_ACTIVE_AC1
+	Method (_AC1)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_CPU_ACTIVE_AC1))
+	}
+#endif
+
+#ifdef DPTF_CPU_ACTIVE_AC2
+	Method (_AC2)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_CPU_ACTIVE_AC2))
+	}
+#endif
+
+#ifdef DPTF_CPU_ACTIVE_AC3
+	Method (_AC3)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_CPU_ACTIVE_AC3))
+	}
+#endif
+
+#ifdef DPTF_CPU_ACTIVE_AC4
+	Method (_AC4)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_CPU_ACTIVE_AC4))
+	}
+#endif
+}

+ 121 - 0
arch/x86/include/asm/acpi/dptf/dptf.asl

@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+Device (DPTF)
+{
+	Name (_HID, EISAID ("INT3400"))
+	Name (_UID, 0)
+
+	Name (IDSP, Package()
+	{
+		/* DPPM Passive Policy 1.0 */
+		ToUUID ("42A441D6-AE6A-462B-A84B-4A8CE79027D3"),
+
+		/* DPPM Critical Policy */
+		ToUUID ("97C68AE7-15FA-499c-B8C9-5DA81D606E0A"),
+
+		/* DPPM Cooling Policy */
+		ToUUID ("16CAF1B7-DD38-40ED-B1C1-1B8A1913D531"),
+
+#ifdef DPTF_ENABLE_FAN_CONTROL
+		/* DPPM Active Policy */
+		ToUUID ("3A95C389-E4B8-4629-A526-C52C88626BAE"),
+#endif
+	})
+
+	Method (_STA)
+	{
+		If (LEqual (\DPTE, One)) {
+			Return (0xF)
+		} Else {
+			Return (0x0)
+		}
+	}
+
+	/*
+	 * Arg0: Buffer containing UUID
+	 * Arg1: Integer containing Revision ID of buffer format
+	 * Arg2: Integer containing count of entries in Arg3
+	 * Arg3: Buffer containing list of DWORD capabilities
+	 * Return: Buffer containing list of DWORD capabilities
+	 */
+	Method (_OSC, 4, Serialized)
+	{
+		/* Check for Passive Policy UUID */
+		If (LEqual (DeRefOf (Index (IDSP, 0)), Arg0)) {
+			/* Initialize Thermal Devices */
+			^TINI ()
+
+#ifdef DPTF_ENABLE_CHARGER
+			/* Initialize Charger Device */
+			^TCHG.INIT ()
+#endif
+		}
+
+		Return (Arg3)
+	}
+
+	/* Priority based _TRT */
+	Name (TRTR, 1)
+
+	Method (_TRT)
+	{
+		Return (\_SB.DTRT)
+	}
+
+#ifdef DPTF_ENABLE_FAN_CONTROL
+	/* _ART : Active Cooling Relationship Table */
+	Method (_ART)
+	{
+		Return (\_SB.DART)
+	}
+#endif
+
+	/* Convert from Degrees C to 1/10 Kelvin for ACPI */
+	Method (CTOK, 1) {
+		/* 10th of Degrees C */
+		Multiply (Arg0, 10, Local0)
+
+		/* Convert to Kelvin */
+		Add (Local0, 2732, Local0)
+
+		Return (Local0)
+	}
+
+	/* Convert from 1/10 Kelvin to Degrees C for ACPI */
+	Method (KTOC, 1) {
+		If (LLessEqual (Arg0, 2732)) {
+			Return (0)
+		}
+
+		/* Convert to Celsius */
+		Subtract (Arg0, 2732, Local0)
+
+		/* Convert from 10th of degrees */
+		Divide (Local0, 10,, Local0)
+
+		Return (Local0)
+	}
+
+	/* Include Thermal Participants */
+	#include "thermal.asl"
+
+#ifdef DPTF_ENABLE_CHARGER
+	/* Include Charger Participant */
+	#include "charger.asl"
+#endif
+
+#ifdef DPTF_ENABLE_FAN_CONTROL
+	/* Include Fan Participant */
+	#include "fan.asl"
+#endif
+
+}
+
+Scope (\_SB.PCI0)
+{
+	#include "cpu.asl"
+}

+ 57 - 0
arch/x86/include/asm/acpi/dptf/fan.asl

@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+Device (TFN1)
+{
+	Name (_HID, "INT3404")
+	Name (_UID, 0)
+	Name (_STR, Unicode("Fan Control"))
+
+	/* _FIF: Fan Information */
+	Name (_FIF, Package ()
+	{
+		0,	// Revision
+		1,	// Fine Grained Control
+		2,	// Step Size
+		0	// No Low Speed Notification
+	})
+
+	/* Return Fan Performance States defined by mainboard */
+	Method (_FPS)
+	{
+		Return (\_SB.DFPS)
+	}
+
+	Name (TFST, Package ()
+	{
+		0,	// Revision
+		0x00,	// Control
+		0x00	// Speed
+	})
+
+	/* _FST: Fan current Status */
+	Method (_FST, 0, Serialized,,PkgObj)
+	{
+		/* Fill in TFST with current control. */
+		Store (\_SB.PCI0.LPCB.EC0.FAND, Index (TFST, 1))
+		Return (TFST)
+	}
+
+	/* _FSL: Fan Speed Level */
+	Method (_FSL, 1, Serialized)
+	{
+		Store (Arg0, \_SB.PCI0.LPCB.EC0.FAND)
+	}
+
+	Method (_STA)
+	{
+		If (LEqual (\DPTE, One))
+		{
+			Return (0xF)
+		} Else {
+			Return (0x0)
+		}
+	}
+}

+ 521 - 0
arch/x86/include/asm/acpi/dptf/thermal.asl

@@ -0,0 +1,521 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+/* Thermal Threshold Event Handler */
+#define HAVE_THERM_EVENT_HANDLER
+Method (TEVT, 1, NotSerialized)
+{
+	Store (ToInteger (Arg0), Local0)
+
+#ifdef DPTF_TSR0_SENSOR_ID
+	If (LEqual (Local0, DPTF_TSR0_SENSOR_ID)) {
+		Notify (^TSR0, 0x90)
+	}
+#endif
+#ifdef DPTF_TSR1_SENSOR_ID
+	If (LEqual (Local0, DPTF_TSR1_SENSOR_ID)) {
+		Notify (^TSR1, 0x90)
+	}
+#endif
+#ifdef DPTF_TSR2_SENSOR_ID
+	If (LEqual (Local0, DPTF_TSR2_SENSOR_ID)) {
+		Notify (^TSR2, 0x90)
+	}
+#endif
+#ifdef DPTF_TSR3_SENSOR_ID
+	If (LEqual (Local0, DPTF_TSR3_SENSOR_ID)) {
+		Notify (^TSR3, 0x90)
+	}
+#endif
+}
+
+/* Thermal device initialization - Disable Aux Trip Points */
+Method (TINI)
+{
+#ifdef DPTF_TSR0_SENSOR_ID
+	^TSR0.PATD ()
+#endif
+#ifdef DPTF_TSR1_SENSOR_ID
+	^TSR1.PATD ()
+#endif
+#ifdef DPTF_TSR2_SENSOR_ID
+	^TSR2.PATD ()
+#endif
+#ifdef DPTF_TSR3_SENSOR_ID
+	^TSR3.PATD ()
+#endif
+}
+
+/* Thermal Trip Points Change Event Handler */
+Method (TPET)
+{
+#ifdef DPTF_TSR0_SENSOR_ID
+	Notify (^TSR0, 0x81)
+#endif
+#ifdef DPTF_TSR1_SENSOR_ID
+	Notify (^TSR1, 0x81)
+#endif
+#ifdef DPTF_TSR2_SENSOR_ID
+	Notify (^TSR2, 0x81)
+#endif
+#ifdef DPTF_TSR3_SENSOR_ID
+	Notify (^TSR3, 0x81)
+#endif
+}
+
+/*
+ * Method to return trip temperature value depending upon the device mode.
+ * Arg0 --> Value to return when device is in tablet mode
+ * Arg1 --> Value to return when device is not in tablet mode.
+ */
+Method (DTRP, 2, Serialized)
+{
+#ifdef EC_ENABLE_MULTIPLE_DPTF_PROFILES
+	If (LEqual (\_SB.PCI0.LPCB.EC0.RCDP, One)) {
+		Return (CTOK (Arg0))
+	} Else {
+#endif
+		Return (CTOK (Arg1))
+#ifdef EC_ENABLE_MULTIPLE_DPTF_PROFILES
+	}
+#endif
+}
+
+#ifdef DPTF_TSR0_SENSOR_ID
+
+#ifndef DPTF_TSR0_TABLET_PASSIVE
+#define DPTF_TSR0_TABLET_PASSIVE DPTF_TSR0_PASSIVE
+#endif
+#ifndef DPTF_TSR0_TABLET_CRITICAL
+#define DPTF_TSR0_TABLET_CRITICAL DPTF_TSR0_CRITICAL
+#endif
+
+Device (TSR0)
+{
+	Name (_HID, EISAID ("INT3403"))
+	Name (_UID, 1)
+	Name (PTYP, 0x03)
+	Name (TMPI, DPTF_TSR0_SENSOR_ID)
+	Name (_STR, Unicode (DPTF_TSR0_SENSOR_NAME))
+	Name (GTSH, 20) /* 2 degree hysteresis */
+
+	Method (_STA)
+	{
+		If (LEqual (\DPTE, One)) {
+			Return (0xF)
+		} Else {
+			Return (0x0)
+		}
+	}
+
+	Method (_TMP, 0, Serialized)
+	{
+		Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
+	}
+
+	Method (_PSV)
+	{
+		Return (DTRP (DPTF_TSR0_TABLET_PASSIVE, DPTF_TSR0_PASSIVE))
+	}
+
+	Method (_CRT)
+	{
+		Return (DTRP (DPTF_TSR0_TABLET_CRITICAL, DPTF_TSR0_CRITICAL))
+	}
+
+	Name (PATC, 2)
+
+	/* Set Aux Trip Point */
+	Method (PAT0, 1, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
+	}
+
+	/* Set Aux Trip Point */
+	Method (PAT1, 1, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
+	}
+
+	/* Disable Aux Trip Point */
+	Method (PATD, 0, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PATD (TMPI)
+	}
+
+#ifdef DPTF_ENABLE_FAN_CONTROL
+#ifdef DPTF_TSR0_ACTIVE_AC0
+	Method (_AC0)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR0_ACTIVE_AC0))
+	}
+#endif
+#ifdef DPTF_TSR0_ACTIVE_AC1
+	Method (_AC1)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR0_ACTIVE_AC1))
+	}
+#endif
+#ifdef DPTF_TSR0_ACTIVE_AC2
+	Method (_AC2)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR0_ACTIVE_AC2))
+	}
+#endif
+#ifdef DPTF_TSR0_ACTIVE_AC3
+	Method (_AC3)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR0_ACTIVE_AC3))
+	}
+#endif
+#ifdef DPTF_TSR0_ACTIVE_AC4
+	Method (_AC4)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR0_ACTIVE_AC4))
+	}
+#endif
+#ifdef DPTF_TSR0_ACTIVE_AC5
+	Method (_AC5)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR0_ACTIVE_AC5))
+	}
+#endif
+#ifdef DPTF_TSR0_ACTIVE_AC6
+	Method (_AC6)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR0_ACTIVE_AC6))
+	}
+#endif
+#endif
+}
+#endif
+
+#ifdef DPTF_TSR1_SENSOR_ID
+
+#ifndef DPTF_TSR1_TABLET_PASSIVE
+#define DPTF_TSR1_TABLET_PASSIVE DPTF_TSR1_PASSIVE
+#endif
+#ifndef DPTF_TSR1_TABLET_CRITICAL
+#define DPTF_TSR1_TABLET_CRITICAL DPTF_TSR1_CRITICAL
+#endif
+
+Device (TSR1)
+{
+	Name (_HID, EISAID ("INT3403"))
+	Name (_UID, 2)
+	Name (PTYP, 0x03)
+	Name (TMPI, DPTF_TSR1_SENSOR_ID)
+	Name (_STR, Unicode (DPTF_TSR1_SENSOR_NAME))
+	Name (GTSH, 20) /* 2 degree hysteresis */
+
+	Method (_STA)
+	{
+		If (LEqual (\DPTE, One)) {
+			Return (0xF)
+		} Else {
+			Return (0x0)
+		}
+	}
+
+	Method (_TMP, 0, Serialized)
+	{
+		Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
+	}
+
+	Method (_PSV)
+	{
+		Return (DTRP (DPTF_TSR1_TABLET_PASSIVE, DPTF_TSR1_PASSIVE))
+	}
+
+	Method (_CRT)
+	{
+		Return (DTRP (DPTF_TSR1_TABLET_CRITICAL, DPTF_TSR1_CRITICAL))
+	}
+
+	Name (PATC, 2)
+
+	/* Set Aux Trip Point */
+	Method (PAT0, 1, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
+	}
+
+	/* Set Aux Trip Point */
+	Method (PAT1, 1, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
+	}
+
+	/* Disable Aux Trip Point */
+	Method (PATD, 0, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PATD (TMPI)
+	}
+
+#ifdef DPTF_ENABLE_FAN_CONTROL
+#ifdef DPTF_TSR1_ACTIVE_AC0
+	Method (_AC0)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR1_ACTIVE_AC0))
+	}
+#endif
+#ifdef DPTF_TSR1_ACTIVE_AC1
+	Method (_AC1)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR1_ACTIVE_AC1))
+	}
+#endif
+#ifdef DPTF_TSR1_ACTIVE_AC2
+	Method (_AC2)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR1_ACTIVE_AC2))
+	}
+#endif
+#ifdef DPTF_TSR1_ACTIVE_AC3
+	Method (_AC3)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR1_ACTIVE_AC3))
+	}
+#endif
+#ifdef DPTF_TSR1_ACTIVE_AC4
+	Method (_AC4)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR1_ACTIVE_AC4))
+	}
+#endif
+#ifdef DPTF_TSR1_ACTIVE_AC5
+	Method (_AC5)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR1_ACTIVE_AC5))
+	}
+#endif
+#ifdef DPTF_TSR1_ACTIVE_AC6
+	Method (_AC6)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR1_ACTIVE_AC6))
+	}
+#endif
+#endif
+}
+#endif
+
+#ifdef DPTF_TSR2_SENSOR_ID
+
+#ifndef DPTF_TSR2_TABLET_PASSIVE
+#define DPTF_TSR2_TABLET_PASSIVE DPTF_TSR2_PASSIVE
+#endif
+#ifndef DPTF_TSR2_TABLET_CRITICAL
+#define DPTF_TSR2_TABLET_CRITICAL DPTF_TSR2_CRITICAL
+#endif
+
+Device (TSR2)
+{
+	Name (_HID, EISAID ("INT3403"))
+	Name (_UID, 3)
+	Name (PTYP, 0x03)
+	Name (TMPI, DPTF_TSR2_SENSOR_ID)
+	Name (_STR, Unicode (DPTF_TSR2_SENSOR_NAME))
+	Name (GTSH, 20) /* 2 degree hysteresis */
+
+	Method (_STA)
+	{
+		If (LEqual (\DPTE, One)) {
+			Return (0xF)
+		} Else {
+			Return (0x0)
+		}
+	}
+
+	Method (_TMP, 0, Serialized)
+	{
+		Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
+	}
+
+	Method (_PSV)
+	{
+		Return (DTRP (DPTF_TSR2_TABLET_PASSIVE, DPTF_TSR2_PASSIVE))
+	}
+
+	Method (_CRT)
+	{
+		Return (DTRP (DPTF_TSR2_TABLET_CRITICAL, DPTF_TSR2_CRITICAL))
+	}
+
+	Name (PATC, 2)
+
+	/* Set Aux Trip Point */
+	Method (PAT0, 1, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
+	}
+
+	/* Set Aux Trip Point */
+	Method (PAT1, 1, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
+	}
+
+	/* Disable Aux Trip Point */
+	Method (PATD, 0, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PATD (TMPI)
+	}
+
+#ifdef DPTF_ENABLE_FAN_CONTROL
+#ifdef DPTF_TSR2_ACTIVE_AC0
+	Method (_AC0)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR2_ACTIVE_AC0))
+	}
+#endif
+#ifdef DPTF_TSR2_ACTIVE_AC1
+	Method (_AC1)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR2_ACTIVE_AC1))
+	}
+#endif
+#ifdef DPTF_TSR2_ACTIVE_AC2
+	Method (_AC2)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR2_ACTIVE_AC2))
+	}
+#endif
+#ifdef DPTF_TSR2_ACTIVE_AC3
+	Method (_AC3)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR2_ACTIVE_AC3))
+	}
+#endif
+#ifdef DPTF_TSR2_ACTIVE_AC4
+	Method (_AC4)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR2_ACTIVE_AC4))
+	}
+#endif
+#ifdef DPTF_TSR2_ACTIVE_AC5
+	Method (_AC5)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR2_ACTIVE_AC5))
+	}
+#endif
+#ifdef DPTF_TSR2_ACTIVE_AC6
+	Method (_AC6)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR2_ACTIVE_AC6))
+	}
+#endif
+#endif
+}
+#endif
+
+#ifdef DPTF_TSR3_SENSOR_ID
+
+#ifndef DPTF_TSR3_TABLET_PASSIVE
+#define DPTF_TSR3_TABLET_PASSIVE DPTF_TSR3_PASSIVE
+#endif
+#ifndef DPTF_TSR3_TABLET_CRITICAL
+#define DPTF_TSR3_TABLET_CRITICAL DPTF_TSR3_CRITICAL
+#endif
+
+Device (TSR3)
+{
+	Name (_HID, EISAID ("INT3403"))
+	Name (_UID, 4)
+	Name (PTYP, 0x03)
+	Name (TMPI, DPTF_TSR3_SENSOR_ID)
+	Name (_STR, Unicode (DPTF_TSR3_SENSOR_NAME))
+	Name (GTSH, 20) /* 2 degree hysteresis */
+
+	Method (_STA)
+	{
+		If (LEqual (\DPTE, One)) {
+			Return (0xF)
+		} Else {
+			Return (0x0)
+		}
+	}
+
+	Method (_TMP, 0, Serialized)
+	{
+		Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
+	}
+
+	Method (_PSV)
+	{
+		Return (DTRP (DPTF_TSR3_TABLET_PASSIVE, DPTF_TSR3_PASSIVE))
+	}
+
+	Method (_CRT)
+	{
+		Return (DTRP (DPTF_TSR3_TABLET_CRITICAL, DPTF_TSR3_CRITICAL))
+	}
+
+	Name (PATC, 2)
+
+	/* Set Aux Trip Point */
+	Method (PAT0, 1, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
+	}
+
+	/* Set Aux Trip Point */
+	Method (PAT1, 1, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
+	}
+
+	/* Disable Aux Trip Point */
+	Method (PATD, 0, Serialized)
+	{
+		\_SB.PCI0.LPCB.EC0.PATD (TMPI)
+	}
+
+#ifdef DPTF_ENABLE_FAN_CONTROL
+#ifdef DPTF_TSR3_ACTIVE_AC0
+	Method (_AC0)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR3_ACTIVE_AC0))
+	}
+#endif
+#ifdef DPTF_TSR3_ACTIVE_AC1
+	Method (_AC1)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR3_ACTIVE_AC1))
+	}
+#endif
+#ifdef DPTF_TSR3_ACTIVE_AC2
+	Method (_AC2)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR3_ACTIVE_AC2))
+	}
+#endif
+#ifdef DPTF_TSR3_ACTIVE_AC3
+	Method (_AC3)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR3_ACTIVE_AC3))
+	}
+#endif
+#ifdef DPTF_TSR3_ACTIVE_AC4
+	Method (_AC4)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR3_ACTIVE_AC4))
+	}
+#endif
+#ifdef DPTF_TSR3_ACTIVE_AC5
+	Method (_AC5)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR3_ACTIVE_AC5))
+	}
+#endif
+#ifdef DPTF_TSR3_ACTIVE_AC6
+	Method (_AC6)
+	{
+		Return (\_SB.DPTF.CTOK (DPTF_TSR3_ACTIVE_AC6))
+	}
+#endif
+#endif
+}
+#endif

+ 4 - 1
arch/x86/include/asm/acpi/global_nvs.h

@@ -11,8 +11,11 @@
  * ACPI_GNVS_SIZE. They are to be used in platform's global_nvs.asl file
  * to declare the GNVS OperationRegion, as well as write_acpi_tables()
  * for the GNVS address runtime fix up.
+ *
+ * If using CONFIG_ACPI_GNVS_EXTERNAL, we don't need to locate the GNVS in
+ * DSDT, since it is created by code, so ACPI_GNVS_ADDR is unused.
  */
 #define ACPI_GNVS_ADDR	0xdeadbeef
-#define ACPI_GNVS_SIZE	0x100
+#define ACPI_GNVS_SIZE	0x1000
 
 #endif /* _ACPI_GNVS_H_ */

+ 141 - 0
arch/x86/include/asm/acpi/lpc.asl

@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2015 Intel Corporation.
+ */
+
+/* Intel LPC/eSPI Bus Device  - 0:1f.0 */
+#include <asm/arch/iomap.h>
+
+Device (LPCB)
+{
+	Name (_ADR, 0x001f0000)
+	Name (_DDN, "LPC Bus Device")
+
+	/* DMA Controller */
+	Device (DMAC)
+	{
+		Name (_HID, EISAID("PNP0200"))
+		Name (_CRS, ResourceTemplate()
+		{
+			IO (Decode16, 0x00, 0x00, 0x01, 0x20)
+			IO (Decode16, 0x81, 0x81, 0x01, 0x11)
+			IO (Decode16, 0x93, 0x93, 0x01, 0x0d)
+			IO (Decode16, 0xc0, 0xc0, 0x01, 0x20)
+			DMA (Compatibility, NotBusMaster, Transfer8_16) { 4 }
+		})
+	}
+
+	/* Firmware Hub */
+	Device (FWH)
+	{
+		Name (_HID, EISAID ("INT0800"))
+		Name (_DDN, "Firmware Hub")
+		Name (_CRS, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadOnly, 0xff000000, 0x01000000)
+		})
+	}
+
+	/* High Precision Event Timer */
+	Device (HPET)
+	{
+		Name (_HID, EISAID ("PNP0103"))
+		Name (_CID, 0x010CD041)
+		Name (_DDN, "High Precision Event Timer")
+		Name (_CRS, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, HPET_BASE_ADDRESS, 0x400)
+		})
+		Method (_STA, 0)
+		{
+			Return (0xF)
+		}
+	}
+
+	/* FPU */
+	Device(MATH)
+	{
+		Name (_HID, EISAID("PNP0C04"))
+		Name (_CRS, ResourceTemplate()
+		{
+			IO (Decode16, 0xf0, 0xf0, 0x01, 0x01)
+			IRQNoFlags() { 13 }
+		})
+	}
+
+	/* AT Interrupt Controller */
+	Device (PIC)
+	{
+		Name (_HID, EISAID ("PNP0000"))
+		Name (_DDN, "8259 Interrupt Controller")
+		Name (_CRS, ResourceTemplate()
+		{
+			IO (Decode16, 0x20, 0x20, 0x01, 0x02)
+			IO (Decode16, 0x24, 0x24, 0x01, 0x02)
+			IO (Decode16, 0x28, 0x28, 0x01, 0x02)
+			IO (Decode16, 0x2c, 0x2c, 0x01, 0x02)
+			IO (Decode16, 0x30, 0x30, 0x01, 0x02)
+			IO (Decode16, 0x34, 0x34, 0x01, 0x02)
+			IO (Decode16, 0x38, 0x38, 0x01, 0x02)
+			IO (Decode16, 0x3c, 0x3c, 0x01, 0x02)
+			IO (Decode16, 0xa0, 0xa0, 0x01, 0x02)
+			IO (Decode16, 0xa4, 0xa4, 0x01, 0x02)
+			IO (Decode16, 0xa8, 0xa8, 0x01, 0x02)
+			IO (Decode16, 0xac, 0xac, 0x01, 0x02)
+			IO (Decode16, 0xb0, 0xb0, 0x01, 0x02)
+			IO (Decode16, 0xb4, 0xb4, 0x01, 0x02)
+			IO (Decode16, 0xb8, 0xb8, 0x01, 0x02)
+			IO (Decode16, 0xbc, 0xbc, 0x01, 0x02)
+			IO (Decode16, 0x4d0, 0x4d0, 0x01, 0x02)
+			IRQNoFlags () { 2 }
+		})
+	}
+
+	/* LPC device: Resource consumption */
+	Device (LDRC)
+	{
+		Name (_HID, EISAID ("PNP0C02"))
+		Name (_UID, 2)
+		Name (_DDN, "Legacy Device Resources")
+		Name (_CRS, ResourceTemplate ()
+		{
+			IO (Decode16, 0x2e, 0x2e, 0x1, 0x02) // First SuperIO
+			IO (Decode16, 0x4e, 0x4e, 0x1, 0x02) // Second SuperIO
+			IO (Decode16, 0x61, 0x61, 0x1, 0x01) // NMI Status
+			IO (Decode16, 0x63, 0x63, 0x1, 0x01) // CPU Reserved
+			IO (Decode16, 0x65, 0x65, 0x1, 0x01) // CPU Reserved
+			IO (Decode16, 0x67, 0x67, 0x1, 0x01) // CPU Reserved
+			IO (Decode16, 0x80, 0x80, 0x1, 0x01) // Port 80 Post
+			IO (Decode16, 0x92, 0x92, 0x1, 0x01) // CPU Reserved
+			IO (Decode16, 0xb2, 0xb2, 0x1, 0x02) // SWSMI
+			IO (Decode16, ACPI_BASE_ADDRESS, ACPI_BASE_ADDRESS,
+			    0x1, 0xff)
+		})
+	}
+
+	/* Real Time Clock Device */
+	Device (RTC)
+	{
+		Name (_HID, EISAID ("PNP0B00"))
+		Name (_DDN, "Real Time Clock")
+		Name (_CRS, ResourceTemplate ()
+		{
+			IO (Decode16, 0x70, 0x70, 1, 8)
+		})
+	}
+
+	/* Timer */
+	Device (TIMR)
+	{
+		Name (_HID, EISAID ("PNP0100"))
+		Name (_DDN, "8254 Timer")
+		Name (_CRS, ResourceTemplate ()
+		{
+			IO (Decode16, 0x40, 0x40, 0x01, 0x04)
+			IO (Decode16, 0x50, 0x50, 0x10, 0x04)
+			IRQNoFlags () {0}
+		})
+	}
+}

+ 21 - 0
arch/x86/include/asm/acpi/pci_osc.asl

@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corp.
+ */
+
+#define PCI_OSC_UUID "33DB4D5B-1FF7-401C-9657-7441C03DD766"
+
+Scope (\_SB.PCI0) {
+	Method (_OSC, 4) {
+		/* Check for proper GUID */
+		If (LEqual (Arg0, ToUUID (PCI_OSC_UUID))) {
+			/* Let OS control everything */
+			Return (Arg3)
+		} Else {
+			/* Unrecognized UUID */
+			CreateDWordField (Arg3, 0, CDW1)
+			Or (CDW1, 4, CDW1)
+			Return (Arg3)
+		}
+	}
+}

+ 80 - 0
arch/x86/include/asm/acpi/pcr.asl

@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2015 Google Inc.
+ * Copyright (C) 2018 Intel Corporation.
+ */
+
+#include <intelblocks/pcr.h>
+
+/*
+ * Calculate PCR register base at specified PID
+ * Arg0 - PCR Port ID
+ */
+Method (PCRB, 1, NotSerialized)
+{
+	Return (Add (IOMAP_P2SB_BAR,
+				ShiftLeft (Arg0, PCR_PORTID_SHIFT)))
+}
+
+/*
+ * Read a PCR register at specified PID and offset
+ * Arg0 - PCR Port ID
+ * Arg1 - Register Offset
+ */
+Method (PCRR, 2, Serialized)
+{
+	OperationRegion (PCRD, SystemMemory, Add (PCRB (Arg0), Arg1), 4)
+	Field (PCRD, DWordAcc, NoLock, Preserve)
+	{
+		DATA, 32
+	}
+	Return (DATA)
+}
+
+/*
+ * AND a value with PCR register at specified PID and offset
+ * Arg0 - PCR Port ID
+ * Arg1 - Register Offset
+ * Arg2 - Value to AND
+ */
+Method (PCRA, 3, Serialized)
+{
+	OperationRegion (PCRD, SystemMemory, Add (PCRB (Arg0), Arg1), 4)
+	Field (PCRD, DWordAcc, NoLock, Preserve)
+	{
+		DATA, 32
+	}
+	And (DATA, Arg2, DATA)
+
+	/*
+	 * After every write one needs to read an innocuous register
+	 * to ensure the writes are completed for certain ports. This is done
+	 * for all ports so that the callers don't need the per-port knowledge
+	 * for each transaction.
+	 */
+	PCRR (Arg0, Arg1)
+}
+
+/*
+ * OR a value with PCR register at specified PID and offset
+ * Arg0 - PCR Port ID
+ * Arg1 - Register Offset
+ * Arg2 - Value to OR
+ */
+Method (PCRO, 3, Serialized)
+{
+	OperationRegion (PCRD, SystemMemory, Add (PCRB (Arg0), Arg1), 4)
+	Field (PCRD, DWordAcc, NoLock, Preserve)
+	{
+		DATA, 32
+	}
+	Or (DATA, Arg2, DATA)
+
+	/*
+	 * After every write one needs to read an innocuous register
+	 * to ensure the writes are completed for certain ports. This is done
+	 * for all ports so that the callers don't need the per-port knowledge
+	 * for each transaction.
+	 */
+	PCRR (Arg0, Arg1)
+}

+ 32 - 0
arch/x86/include/asm/acpi/ramoops.asl

@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014 Google Inc.
+ */
+
+Scope (\_SB)
+{
+	Device(RMOP)
+	{
+		Name (_HID, "GOOG9999")
+		Name (_CID, "GOOG9999")
+		Name (_UID, 1)
+
+		Name (RBUF, ResourceTemplate()
+		{
+			Memory32Fixed (ReadWrite, 0, 0, MRES)
+		})
+
+		Method (_CRS)
+		{
+			CreateDwordField (^RBUF, ^MRES._BAS, RBAS)
+			CreateDwordField (^RBUF, ^MRES._LEN, RLEN)
+			Store (\RMOB, RBAS)
+			Store (\RMOL, RLEN)
+			Return (^RBUF)
+		}
+		Method(_STA, 0)
+		{
+			Return (0xB)
+		}
+	}
+}

+ 7 - 5
arch/x86/include/asm/acpi/sleepstates.asl

@@ -6,9 +6,11 @@
  * Modified from coreboot src/soc/intel/baytrail/acpi/sleepstates.asl
  */
 
-Name(\_S0, Package() {0x0, 0x0, 0x0, 0x0})
-#ifdef CONFIG_HAVE_ACPI_RESUME
-Name(\_S3, Package() {0x5, 0x0, 0x0, 0x0})
+Name(\_S0, Package(){0x0,0x0,0x0,0x0})
+#if !IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
+Name(\_S1, Package(){0x1,0x0,0x0,0x0})
+#else
+Name(\_S3, Package(){0x5,0x0,0x0,0x0})
 #endif
-Name(\_S4, Package() {0x6, 0x0, 0x0, 0x0})
-Name(\_S5, Package() {0x7, 0x0, 0x0, 0x0})
+Name(\_S4, Package(){0x6,0x0,0x0,0x0})
+Name(\_S5, Package(){0x7,0x0,0x0,0x0})

+ 162 - 0
arch/x86/include/asm/acpi_table.h

@@ -9,6 +9,8 @@
 #ifndef __ASM_ACPI_TABLE_H__
 #define __ASM_ACPI_TABLE_H__
 
+#ifndef __ACPI__
+
 struct acpi_facs;
 struct acpi_fadt;
 struct acpi_global_nvs;
@@ -36,6 +38,27 @@ int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
 u32 acpi_fill_mcfg(u32 current);
 u32 acpi_fill_csrt(u32 current);
 
+/**
+ * acpi_write_hpet() - Write out a HPET table
+ *
+ * Write out the table for High-Precision Event Timers
+ *
+ * @ctx: Current ACPI context
+ * @return 0 if OK, -ve on error
+ */
+int acpi_write_hpet(struct acpi_ctx *ctx);
+
+/**
+ * acpi_write_dbg2_pci_uart() - Write out a DBG2 table
+ *
+ * @ctx: Current ACPI context
+ * @dev: Debug UART device to describe
+ * @access_size: Access size for UART (e.g. ACPI_ACCESS_SIZE_DWORD_ACCESS)
+ * @return 0 if OK, -ve on error
+ */
+int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
+			     uint access_size);
+
 /**
  * acpi_create_gnvs() - Create a GNVS (Global Non Volatile Storage) table
  *
@@ -55,4 +78,143 @@ ulong write_acpi_tables(ulong start);
  */
 ulong acpi_get_rsdp_addr(void);
 
+/**
+ * arch_read_sci_irq_select() - Read the system-control interrupt number
+ *
+ * @returns value of IRQ register in the PMC
+ */
+int arch_read_sci_irq_select(void);
+
+/**
+ * arch_write_sci_irq_select() - Set the system-control interrupt number
+ *
+ * @scis: New value for IRQ register in the PMC
+ */
+int arch_write_sci_irq_select(uint scis);
+
+/**
+ * arch_madt_sci_irq_polarity() - Return the priority to use for the MADT
+ *
+ * @sci: System-control interrupt number
+ * @return priority to use (MP_IRQ_POLARITY_...)
+ */
+int arch_madt_sci_irq_polarity(int sci);
+
+/**
+ * acpi_create_dmar_drhd() - Create a table for DMA remapping with the IOMMU
+ *
+ * See here for the specification
+ * https://software.intel.com/sites/default/files/managed/c5/15/vt-directed-io-spec.pdf
+ *
+ * @ctx: ACPI context pointer
+ * @flags: (DRHD_INCLUDE_...)
+ * @segment: PCI segment asscociated with this unit
+ * @bar: Base address of remapping hardware register-set for this unit
+ */
+void acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
+			   u64 bar);
+
+/**
+ * acpi_create_dmar_rmrr() - Set up an RMRR
+ *
+ * This sets up a Reserved-Memory Region Reporting structure, used to allow
+ * DMA to regions used by devices that the BIOS controls.
+ *
+ * @ctx: ACPI context pointer
+ * @segment: PCI segment asscociated with this unit
+ * @bar: Base address of mapping
+ * @limit: End address of mapping
+ */
+void acpi_create_dmar_rmrr(struct acpi_ctx *ctx, uint segment, u64 bar,
+			   u64 limit);
+
+/**
+ * acpi_dmar_drhd_fixup() - Set the length of an DRHD
+ *
+ * This sets the DRHD length field based on the current ctx->current
+ *
+ * @ctx: ACPI context pointer
+ * @base: Address of the start of the DRHD
+ */
+void acpi_dmar_drhd_fixup(struct acpi_ctx *ctx, void *base);
+
+/**
+ * acpi_dmar_rmrr_fixup() - Set the length of an RMRR
+ *
+ * This sets the RMRR length field based on the current ctx->current
+ *
+ * @ctx: ACPI context pointer
+ * @base: Address of the start of the RMRR
+ */
+void acpi_dmar_rmrr_fixup(struct acpi_ctx *ctx, void *base);
+
+/**
+ * acpi_create_dmar_ds_pci() - Set up a DMAR scope for a PCI device
+ *
+ * @ctx: ACPI context pointer
+ * @bdf: PCI device to add
+ * @return length of mapping in bytes
+ */
+int acpi_create_dmar_ds_pci(struct acpi_ctx *ctx, pci_dev_t bdf);
+
+/**
+ * acpi_create_dmar_ds_pci_br() - Set up a DMAR scope for a PCI bridge
+ *
+ * This is used to provide a mapping for a PCI bridge
+ *
+ * @ctx: ACPI context pointer
+ * @bdf: PCI device to add
+ * @return length of mapping in bytes
+ */
+int acpi_create_dmar_ds_pci_br(struct acpi_ctx *ctx, pci_dev_t bdf);
+
+/**
+ * acpi_create_dmar_ds_ioapic() - Set up a DMAR scope for an IOAPIC device
+ *
+ * @ctx: ACPI context pointer
+ * @enumeration_id: Enumeration ID (typically 2)
+ * @bdf: PCI device to add
+ * @return length of mapping in bytes
+ */
+int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
+			       pci_dev_t bdf);
+
+/**
+ * acpi_create_dmar_ds_msi_hpet() - Set up a DMAR scope for an HPET
+ *
+ * Sets up a scope for a High-Precision Event Timer that supports
+ * Message-Signalled Interrupts
+ *
+ * @ctx: ACPI context pointer
+ * @enumeration_id: Enumeration ID (typically 0)
+ * @bdf: PCI device to add
+ * @return length of mapping in bytes
+ */
+int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
+				 pci_dev_t bdf);
+
+/**
+ * acpi_fadt_common() - Handle common parts of filling out an FADT
+ *
+ * This sets up the Fixed ACPI Description Table
+ *
+ * @fadt: Pointer to place to put FADT
+ * @facs: Pointer to the FACS
+ * @dsdt: Pointer to the DSDT
+ */
+void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
+		      void *dsdt);
+
+/**
+ * intel_acpi_fill_fadt() - Set up the contents of the FADT
+ *
+ * This sets up parts of the Fixed ACPI Description Table that are common to
+ * Intel chips
+ *
+ * @fadt: Pointer to place to put FADT
+ */
+void intel_acpi_fill_fadt(struct acpi_fadt *fadt);
+
+#endif /* !__ACPI__ */
+
 #endif /* __ASM_ACPI_TABLE_H__ */

+ 35 - 0
arch/x86/include/asm/acpigen.h

@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Generation of x86-specific ACPI tables
+ *
+ * Copyright 2020 Google LLC
+ */
+
+#ifndef __ASM_ACPIGEN_H__
+#define __ASM_ACPIGEN_H__
+
+struct acpi_ctx;
+
+/**
+ * acpigen_write_empty_pct() - Write an empty PCT
+ *
+ * See ACPI v6.3 section 8.4.6.1: _PCT (Performance Control)
+ *
+ * This writes an empty table so that CPU performance works as expected
+ *
+ * @ctx: ACPI context pointer
+ */
+void acpigen_write_empty_pct(struct acpi_ctx *ctx);
+
+/**
+ * acpigen_write_empty_ptc() - Write an empty PTC
+ *
+ * See ACPI v6.3 section 8.4.5.1: _PTC (Processor Throttling Control)
+ *
+ * This writes an empty table so that CPU performance works as expected
+ *
+ * @ctx: ACPI context pointer
+ */
+void acpigen_write_empty_ptc(struct acpi_ctx *ctx);
+
+#endif /* __ASM_ACPI_H__ */

+ 18 - 0
arch/x86/include/asm/arch-apollolake/acpi.h

@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef _ASM_ARCH_ACPI_H
+#define _ASM_ARCH_ACPI_H
+
+struct acpi_ctx;
+
+/**
+ * apl_acpi_fill_dmar() - Set up the DMAR for APL
+ *
+ * @ctx: ACPI context pointer
+ */
+int apl_acpi_fill_dmar(struct acpi_ctx *ctx);
+
+#endif /* _ASM_ARCH_CPU_H */

+ 35 - 0
arch/x86/include/asm/arch-apollolake/acpi/dptf.asl

@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+#define DPTF_CPU_DEVICE		TCPU
+#define DPTF_CPU_ADDR		0x00000001
+
+#ifndef DPTF_CPU_PASSIVE
+#define DPTF_CPU_PASSIVE	80
+#endif
+
+#ifndef DPTF_CPU_CRITICAL
+#define DPTF_CPU_CRITICAL	90
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC0
+#define DPTF_CPU_ACTIVE_AC0	90
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC1
+#define DPTF_CPU_ACTIVE_AC1	80
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC2
+#define DPTF_CPU_ACTIVE_AC2	70
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC3
+#define DPTF_CPU_ACTIVE_AC3	60
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC4
+#define DPTF_CPU_ACTIVE_AC4	50
+#endif

+ 41 - 0
arch/x86/include/asm/arch-apollolake/acpi/globalnvs.asl

@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
+ */
+
+/*
+ * NOTE: The layout of the GNVS structure below must match the layout in
+ * soc/intel/apollolake/include/soc/nvs.h !!!
+ *
+ */
+
+External (NVSA)
+
+OperationRegion (GNVS, SystemMemory, NVSA, ACPI_GNVS_SIZE)
+Field (GNVS, ByteAcc, NoLock, Preserve)
+{
+	/* Miscellaneous */
+	Offset (0x00),
+	PCNT,	8,      // 0x00 - Processor Count
+	PPCM,	8,      // 0x01 - Max PPC State
+	LIDS,	8,      // 0x02 - LID State
+	PWRS,	8,      // 0x03 - AC Power State
+	DPTE,	8,      // 0x04 - Enable DPTF
+	CBMC,	32,     // 0x05 - 0x08 - coreboot Memory Console
+	PM1I,	64,     // 0x09 - 0x10 - System Wake Source - PM1 Index
+	GPEI,	64,     // 0x11 - 0x18 - GPE Wake Source
+	NHLA,	64,     // 0x19 - 0x20 - NHLT Address
+	NHLL,	32,     // 0x21 - 0x24 - NHLT Length
+	PRT0,	32,     // 0x25 - 0x28 - PERST_0 Address
+	SCDP,	8,      // 0x29 - SD_CD GPIO portid
+	SCDO,	8,      // 0x2A - GPIO pad offset relative to the community
+	UIOR,	8,      // 0x2B - UART debug controller init on S3 resume
+	EPCS,   8,      // 0x2C - SGX Enabled status
+	EMNA,   64,     // 0x2D - 0x34 EPC base address
+	ELNG,   64,     // 0x35 - 0x3C EPC Length
+
+	/* ChromeOS stuff (0x100 -> 0xfff, size 0xeff) */
+	Offset (0x100),
+	#include <asm/acpi/cros_gnvs.asl>
+}

+ 191 - 0
arch/x86/include/asm/arch-apollolake/acpi/gpio.asl

@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ */
+#include <asm/arch/gpio.h>
+#include <asm/intel_pinctrl_defs.h>
+// #include <intelblocks/pcr.h>
+// #include <soc/pcr_ids.h>
+#include <asm/arch/iomap.h>
+#include <p2sb.h>
+#include "gpiolib.asl"
+
+scope (\_SB) {
+
+	Device (GPO0)
+	{
+		Name (_HID, GPIO_COMM_NAME)
+		Name (_CID, GPIO_COMM_NAME)
+		Name (_DDN, GPIO_COMM_0_DESC)
+		Name (_UID, 1)
+
+		Name (RBUF, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, 0, 0x4000, RMEM)
+			Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , )
+			{
+				GPIO_BANK_INT
+			}
+		})
+
+		Method (_CRS, 0x0, NotSerialized)
+		{
+			CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+			ShiftLeft (GPIO_COMM0_PID, PCR_PORTID_SHIFT, Local0)
+			Or (IOMAP_P2SB_BAR, Local0, RBAS)
+			Return (^RBUF)
+		}
+
+		Method (_STA, 0x0, NotSerialized)
+		{
+			Return(0xf)
+		}
+	}
+
+	Device (GPO1)
+	{
+		Name (_HID, GPIO_COMM_NAME)
+		Name (_CID, GPIO_COMM_NAME)
+		Name (_DDN, GPIO_COMM_1_DESC)
+		Name (_UID, 2)
+
+		Name (RBUF, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, 0, 0x4000, RMEM)
+			Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , )
+			{
+				GPIO_BANK_INT
+			}
+		})
+
+		Method (_CRS, 0x0, NotSerialized)
+		{
+			CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+			ShiftLeft (GPIO_COMM1_PID, PCR_PORTID_SHIFT, Local0)
+			Or (IOMAP_P2SB_BAR, Local0, RBAS)
+			Return (^RBUF)
+		}
+
+		Method (_STA, 0x0, NotSerialized)
+		{
+			Return(0xf)
+		}
+	}
+
+	Device (GPO2)
+	{
+		Name (_HID, GPIO_COMM_NAME)
+		Name (_CID, GPIO_COMM_NAME)
+		Name (_DDN, GPIO_COMM_2_DESC)
+		Name (_UID, 3)
+
+		Name (RBUF, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, 0, 0x4000, RMEM)
+			Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , )
+			{
+				GPIO_BANK_INT
+			}
+		})
+
+		Method (_CRS, 0x0, NotSerialized)
+		{
+			CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+			ShiftLeft (GPIO_COMM2_PID, PCR_PORTID_SHIFT, Local0)
+			Or (IOMAP_P2SB_BAR, Local0, RBAS)
+			Return (^RBUF)
+		}
+
+		Method (_STA, 0x0, NotSerialized)
+		{
+			Return(0xf)
+		}
+	}
+
+	Device (GPO3)
+	{
+		Name (_HID, GPIO_COMM_NAME)
+		Name (_CID, GPIO_COMM_NAME)
+		Name (_DDN, GPIO_COMM_3_DESC)
+		Name (_UID, 4)
+
+		Name (RBUF, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, 0, 0x4000, RMEM)
+			Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , )
+			{
+				GPIO_BANK_INT
+			}
+		})
+
+		Method (_CRS, 0x0, NotSerialized)
+		{
+			CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+			ShiftLeft (GPIO_COMM3_PID, PCR_PORTID_SHIFT, Local0)
+			Or (IOMAP_P2SB_BAR, Local0, RBAS)
+			Return (^RBUF)
+		}
+
+		Method (_STA, 0x0, NotSerialized)
+		{
+			Return(0xf)
+		}
+	}
+
+	Scope(\_SB.PCI0) {
+		/* PERST Assertion
+		 * Note: PERST is Active High
+		 */
+		Method (PRAS, 0x1, Serialized)
+		{
+			/*
+			 * Assert PERST
+			 * local1 - to toggle Tx pin of Dw0
+			 * local2 - Address of PERST
+			 */
+			Store (Arg0, Local2)
+			Store (\_SB.GPC0 (Local2), Local1)
+			Or (Local1, PAD_CFG0_TX_STATE, Local1)
+			\_SB.SPC0 (Local2, Local1)
+		}
+
+		/* PERST DE-Assertion */
+		Method (PRDA, 0x1, Serialized)
+		{
+			/*
+			 * De-assert PERST
+			 * local1 - to toggle Tx pin of Dw0
+			 * local2 - Address of PERST
+			 */
+			Store (Arg0, Local2)
+			Store (\_SB.GPC0 (Local2), Local1)
+			And (Local1, Not (PAD_CFG0_TX_STATE), Local1)
+			\_SB.SPC0 (Local2, Local1)
+		}
+	}
+
+	/*
+	 * Sleep button device ASL code. We are using this device to
+	 * add the _PRW method for a dummy wake event to kernel so that
+	 * before going to sleep kernel does not clear bit 15 in ACPI
+	 * gpe0a enable register which is actually the GPIO_TIER1_SCI_EN bit.
+	 */
+	Device (SLP)
+	{
+		Name (_HID, EisaId ("PNP0C0E"))
+
+		Name (_PRW, Package() { GPE0A_GPIO_TIER1_SCI_STS, 0x3 })
+	}
+}
+
+Scope(\_GPE)
+{
+	/*
+	 * Dummy method for the Tier 1 GPIO SCI enable bit. When kernel reads
+	 * _L0F in scope GPE it sets bit for gpio_tier1_sci_en in ACPI enable
+	 * register at 0x430. For APL ACPI enable register DW0 i.e., ACPI
+	 * GPE0a_EN at 0x430 is reserved.
+	 */
+	Method(_L0F, 0) {}
+}

+ 109 - 0
arch/x86/include/asm/arch-apollolake/acpi/gpiolib.asl

@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+Scope (\_SB)
+{
+	/* Get Pad Configuration DW0 register value */
+	Method (GPC0, 0x1, Serialized)
+	{
+		/* Arg0 - GPIO DW0 address */
+		Store (Arg0, Local0)
+		OperationRegion (PDW0, SystemMemory, Local0, 4)
+		Field (PDW0, AnyAcc, NoLock, Preserve) {
+			TEMP, 32
+		}
+		Return (TEMP)
+	}
+
+	/* Set Pad Configuration DW0 register value */
+	Method (SPC0, 0x2, Serialized)
+	{
+		/* Arg0 - GPIO DW0 address */
+		/* Arg1 - Value for DW0 register */
+		Store (Arg0, Local0)
+		OperationRegion (PDW0, SystemMemory, Local0, 4)
+		Field (PDW0, AnyAcc, NoLock, Preserve) {
+			TEMP,32
+		}
+		Store (Arg1, TEMP)
+	}
+
+	/* Get Pad Configuration DW1 register value */
+	Method (GPC1, 0x1, Serialized)
+	{
+		/* Arg0 - GPIO DW0 address */
+		Store (Add (Arg0, 0x4), Local0)
+		OperationRegion (PDW1, SystemMemory, Local0, 4)
+		Field (PDW1, AnyAcc, NoLock, Preserve) {
+			TEMP, 32
+		}
+		Return (TEMP)
+	}
+
+	/* Set Pad Configuration DW1 register value */
+	Method (SPC1, 0x2, Serialized)
+	{
+		/* Arg0 - GPIO DW0 address */
+		/* Arg1 - Value for DW1 register */
+		Store (Add (Arg0, 0x4), Local0)
+		OperationRegion (PDW1, SystemMemory, Local0, 4)
+		Field(PDW1, AnyAcc, NoLock, Preserve) {
+			TEMP,32
+		}
+		Store (Arg1, TEMP)
+	}
+
+	/* Get DW0 address of a given pad */
+	Method (GDW0, 0x2, Serialized)
+	{
+		/* Arg0 - GPIO portid */
+		/* Arg1 - GPIO pad offset relative to the community */
+		Store (0, Local1)
+		Or( Or (ShiftLeft (Arg0, 16), IOMAP_P2SB_BAR),
+					Local1, Local1)
+		Or( Add (PAD_CFG_BASE, Multiply (Arg1, Multiply (
+			GPIO_NUM_PAD_CFG_REGS, 4))), Local1, Local1)
+		Return (Local1)
+	}
+
+	/* Calculate HOSTSW_REG address */
+	Method (CHSA, 0x1, Serialized)
+	{
+		/* Arg0 - GPIO pad offset relative to the community */
+		Add (HOSTSW_OWN_REG_0, Multiply (Divide (Arg0, 32), 4), Local1)
+		Return (Local1)
+	}
+
+	/* Get Host ownership register of GPIO Community */
+	Method (GHO, 0x2, Serialized)
+	{
+		/* Arg0 - GPIO portid */
+		/* Arg1 - GPIO pad offset relative to the community */
+		Store (CHSA (Arg1), Local1)
+
+		OperationRegion (SHO0, SystemMemory, Or ( Or
+			(IOMAP_P2SB_BAR, ShiftLeft (Arg0, 16)), Local1), 4)
+		Field (SHO0, AnyAcc, NoLock, Preserve) {
+			TEMP, 32
+		}
+		Return (TEMP)
+	}
+
+	/* Set Host ownership register of GPIO Community */
+	Method (SHO, 0x3, Serialized)
+	{
+		/* Arg0 - GPIO portid */
+		/* Arg1 - GPIO pad offset relative to the community */
+		/* Arg2 - Value for Host own register */
+		Store (CHSA (Arg1), Local1)
+
+		OperationRegion (SHO0, SystemMemory, Or ( Or
+			(IOMAP_P2SB_BAR, ShiftLeft (Arg0, 16)), Local1), 4)
+		Field (SHO0, AnyAcc, NoLock, Preserve) {
+			TEMP, 32
+		}
+		Store (Arg2, TEMP)
+	}
+}

+ 105 - 0
arch/x86/include/asm/arch-apollolake/acpi/lpss.asl

@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ */
+
+scope (\_SB.PCI0) {
+
+	/* LPIO1 PWM */
+	Device(PWM) {
+		Name (_ADR, 0x001A0000)
+		Name (_DDN, "Intel(R) PWM Controller")
+	}
+
+	/* LPIO1 HS-UART #1 */
+	Device(URT1) {
+		Name (_ADR, 0x00180000)
+		Name (_DDN, "Intel(R) HS-UART Controller #1")
+	}
+
+	/* LPIO1 HS-UART #2 */
+	Device(URT2) {
+		Name (_ADR, 0x00180001)
+		Name (_DDN, "Intel(R) HS-UART Controller #2")
+	}
+
+	/* LPIO1 HS-UART #3 */
+	Device(URT3) {
+		Name (_ADR, 0x00180002)
+		Name (_DDN, "Intel(R) HS-UART Controller #3")
+	}
+
+	/* LPIO1 HS-UART #4 */
+	Device(URT4) {
+		Name (_ADR, 0x00180003)
+		Name (_DDN, "Intel(R) HS-UART Controller #4")
+	}
+
+	/* LPIO1 SPI */
+	Device(SPI1) {
+		Name (_ADR, 0x00190000)
+		Name (_DDN, "Intel(R) SPI Controller #1")
+	}
+
+	/* LPIO1 SPI #2 */
+	Device(SPI2) {
+		Name (_ADR, 0x00190001)
+		Name (_DDN, "Intel(R) SPI Controller #2")
+	}
+
+	/* LPIO1 SPI #3 */
+	Device(SPI3) {
+		Name (_ADR, 0x00190002)
+		Name (_DDN, "Intel(R) SPI Controller #3")
+	}
+
+
+	/* LPIO2 I2C #0 */
+	Device(I2C0) {
+		Name (_ADR, 0x00160000)
+		Name (_DDN, "Intel(R) I2C Controller #0")
+	}
+
+	/* LPIO2 I2C #1 */
+	Device(I2C1) {
+		Name (_ADR, 0x00160001)
+		Name (_DDN, "Intel(R) I2C Controller #1")
+	}
+
+	/* LPIO2 I2C #2 */
+	Device(I2C2) {
+		Name (_ADR, 0x00160002)
+		Name (_DDN, "Intel(R) I2C Controller #2")
+	}
+
+	/* LPIO2 I2C #3 */
+	Device(I2C3) {
+		Name (_ADR, 0x00160003)
+		Name (_DDN, "Intel(R) I2C Controller #3")
+	}
+
+	/* LPIO2 I2C #4 */
+	Device(I2C4) {
+		Name (_ADR, 0x00170000)
+		Name (_DDN, "Intel(R) I2C Controller #4")
+	}
+
+	/* LPIO2 I2C #5 */
+	Device(I2C5) {
+		Name (_ADR, 0x00170001)
+		Name (_DDN, "Intel(R) I2C Controller #5")
+	}
+
+	/* LPIO2 I2C #6 */
+	Device(I2C6) {
+		Name (_ADR, 0x00170002)
+		Name (_DDN, "Intel(R) I2C Controller #6")
+	}
+
+	/* LPIO2 I2C #7 */
+	Device(I2C7) {
+		Name (_ADR, 0x00170003)
+		Name (_DDN, "Intel(R) I2C Controller #7")
+	}
+}

+ 120 - 0
arch/x86/include/asm/arch-apollolake/acpi/northbridge.asl

@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ */
+
+	Name(_HID, EISAID("PNP0A08"))	/* PCIe */
+	Name(_CID, EISAID("PNP0A03"))	/* PCI */
+	Name(_BBN, 0)
+
+Device (MCHC)
+{
+	Name (_ADR, 0x00000000)		/*Dev0 Func0 */
+
+		OperationRegion (MCHP, PCI_Config, 0x00, 0x100)
+		Field (MCHP, DWordAcc, NoLock, Preserve)
+		{
+			Offset(0x60),
+			MCNF,	32,	/* PCI MMCONF base */
+			Offset (0xA8),
+			TUUD, 64,	/* Top of Upper Used Memory */
+			Offset(0xB4),
+			BGSM,   32,	/* Base of Graphics Stolen Memory */
+			Offset(0xBC),
+			TLUD,   32,	/* Top of Low Useable DRAM */
+		}
+}
+Name (MCRS, ResourceTemplate()
+{
+	/* Bus Numbers */
+	WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+			0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,,)
+
+	/* IO Region 0 */
+	DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+			0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,,)
+
+	/* PCI Config Space */
+	Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
+
+	/* IO Region 1 */
+	DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+			0x0000, 0x01000, 0xffff, 0x0000, 0xf000,,,)
+
+	/* VGA memory (0xa0000-0xbffff) */
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+			Cacheable, ReadWrite,
+			0x00000000, 0x000a0000, 0x000bffff, 0x00000000,
+			0x00020000,,,)
+
+	/* Data and GFX stolen memory */
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+			Cacheable, ReadWrite,
+			0x00000000, 0x3be00000, 0x3fffffff, 0x00000000,
+			0x04200000,,, STOM)
+
+	/*
+	 * PCI MMIO Region (TOLUD - PCI extended base MMCONF)
+	 * This assumes that MMCONF is placed after PCI config space,
+	 * and that no resources are allocated after the MMCONF region.
+	 * This works, sicne MMCONF is hardcoded to 0xe00000000.
+	 */
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+			NonCacheable, ReadWrite,
+			0x00000000, 0x00000000, 0x00000000, 0x00000000,
+			0x00000000,,, PM01)
+
+	/* PCI Memory Region (TOUUD - (TOUUD + ABOVE_4G_MMIO_SIZE)) */
+	QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+			NonCacheable, ReadWrite,
+			0x00000000, 0x10000, 0x1ffff, 0x00000000,
+			0x10000,,, PM02)
+})
+
+/* Current Resource Settings */
+Method (_CRS, 0, Serialized)
+{
+
+	/* Find PCI resource area in MCRS */
+	CreateDwordField (MCRS, ^PM01._MIN, PMIN)
+	CreateDwordField (MCRS, ^PM01._MAX, PMAX)
+	CreateDwordField (MCRS, ^PM01._LEN, PLEN)
+
+	/* Read C-Unit PCI CFG Reg. 0xBC for TOLUD (shadow from B-Unit) */
+	And(^MCHC.TLUD, 0xFFF00000, PMIN)
+	/* Read MMCONF base */
+	And(^MCHC.MCNF, 0xF0000000, PMAX)
+
+	/* Calculate PCI MMIO Length */
+	Add(Subtract(PMAX, PMIN), 1, PLEN)
+
+	/* Find GFX resource area in GCRS */
+	CreateDwordField(MCRS, ^STOM._MIN, GMIN)
+	CreateDwordField(MCRS, ^STOM._MAX, GMAX)
+	CreateDwordField(MCRS, ^STOM._LEN, GLEN)
+
+	/* Read BGSM */
+	And(^MCHC.BGSM, 0xFFF00000, GMIN)
+
+	/* Read TOLUD */
+	And(^MCHC.TLUD, 0xFFF00000, GMAX)
+	Decrement(GMAX)
+	Add(Subtract(GMAX, GMIN), 1, GLEN)
+
+	/* Patch PM02 range based on Memory Size */
+	CreateQwordField (MCRS, ^PM02._MIN, MMIN)
+	CreateQwordField (MCRS, ^PM02._MAX, MMAX)
+	CreateQwordField (MCRS, ^PM02._LEN, MLEN)
+
+	Store (^MCHC.TUUD, Local0)
+
+	If (LLessEqual (Local0, 0x1000000000))
+	{
+		Store (0, MMIN)
+		Store (0, MLEN)
+	}
+	Subtract (Add (MMIN, MLEN), 1, MMAX)
+
+	Return (MCRS)
+}

+ 77 - 0
arch/x86/include/asm/arch-apollolake/acpi/pch_hda.asl

@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corporation.
+ * Copyright (C) 2016 Google Inc.
+ *
+ */
+
+/* Audio Controller - Device 14, Function 0 */
+
+Device (HDAS)
+{
+	Name (_ADR, 0x000E0000)
+	Name (_DDN, "Audio Controller")
+	Name (UUID, ToUUID("A69F886E-6CEB-4594-A41F-7B5DCE24C553"))
+
+	/* Device is D3 wake capable */
+	Name (_S0W, 3)
+
+	/* NHLT Table Address populated from GNVS values */
+	Name (NBUF, ResourceTemplate() {
+		QWordMemory (ResourceConsumer, PosDecode, MinFixed,
+			MaxFixed, Cacheable, ReadOnly,
+			0, 0, 0, 0, 1,,, NHLT, AddressRangeACPI)
+		}
+	)
+
+	/* can wake up from S3 state */
+	Name (_PRW, Package() { GPE0A_AVS_PME_STS, 3 })
+
+	/*
+	 * Device Specific Method
+	 * Arg0 - UUID
+	 * Arg1 - Revision
+	 * Arg2 - Function Index
+	*/
+	Method (_DSM, 4) {
+		If (LEqual (Arg0, ^UUID)) {
+			/*
+			 * Function 0: Function Support Query
+			 * Returns a bitmask of functions supported.
+			 */
+			If (LEqual (Arg2, Zero)) {
+				/*
+				 * NHLT Query only supported for revision 1 and
+				 * if NHLT address and length are set in NVS.
+				 */
+				If (LAnd (LEqual (Arg1, One),
+					LAnd (LNotEqual (NHLA, Zero),
+					     LNotEqual (NHLL, Zero)))) {
+					Return (Buffer (One) { 0x03 })
+				}
+				Else {
+					Return (Buffer (One) { 0x01 })
+				}
+			}
+
+			/*
+			 * Function 1: Query NHLT memory address used by
+			 * Intel Offload Engine Driver to discover any non-HDA
+			 * devices that are supported by the DSP.
+			 *
+			 * Returns a pointer to NHLT table in memory.
+			 */
+			If (LEqual (Arg2, One)) {
+				CreateQWordField (NBUF, ^NHLT._MIN, NBAS)
+				CreateQWordField (NBUF, ^NHLT._MAX, NMAS)
+				CreateQWordField (NBUF, ^NHLT._LEN, NLEN)
+				Store (NHLA, NBAS)
+				Store (NHLA, NMAS)
+				Store (NHLL, NLEN)
+				Return (NBUF)
+			}
+		}
+
+		Return (Buffer (One) { 0x00 })
+	}
+}

+ 52 - 0
arch/x86/include/asm/arch-apollolake/acpi/pci_irqs.asl

@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ */
+
+#include "soc_int.asl"
+
+Method(_PRT)
+{
+	Return(Package() {
+
+		Package(){0x0000FFFF, 0, 0, NPK_INT},
+		Package(){0x0000FFFF, 1, 0, PUNIT_INT},
+		Package(){0x0002FFFF, 0, 0, GEN_INT},
+		Package(){0x0003FFFF, 0, 0, IUNIT_INT},
+		Package(){0x000DFFFF, 1, 0, PMC_INT},
+		Package(){0x000EFFFF, 0, 0, AUDIO_INT},
+		Package(){0x000FFFFF, 0, 0, CSE_INT},
+		Package(){0x0011FFFF, 0, 0, ISH_INT},
+		Package(){0x0012FFFF, 0, 0, SATA_INT},
+		Package(){0x0013FFFF, 0, 0, PIRQA_INT},
+		Package(){0x0013FFFF, 1, 0, PIRQB_INT},
+		Package(){0x0013FFFF, 2, 0, PIRQC_INT},
+		Package(){0x0013FFFF, 3, 0, PIRQD_INT},
+		Package(){0x0014FFFF, 0, 0, PIRQB_INT},
+		Package(){0x0014FFFF, 1, 0, PIRQC_INT},
+		Package(){0x0014FFFF, 2, 0, PIRQD_INT},
+		Package(){0x0014FFFF, 3, 0, PIRQA_INT},
+		Package(){0x0015FFFF, 0, 0, XHCI_INT},
+		Package(){0x0015FFFF, 1, 0, XDCI_INT},
+		Package(){0x0016FFFF, 0, 0, I2C0_INT},
+		Package(){0x0016FFFF, 1, 0, I2C1_INT},
+		Package(){0x0016FFFF, 2, 0, I2C2_INT},
+		Package(){0x0016FFFF, 3, 0, I2C3_INT},
+		Package(){0x0017FFFF, 0, 0, I2C4_INT},
+		Package(){0x0017FFFF, 1, 0, I2C5_INT},
+		Package(){0x0017FFFF, 2, 0, I2C6_INT},
+		Package(){0x0017FFFF, 3, 0, I2C7_INT},
+		Package(){0x0018FFFF, 0, 0, UART0_INT},
+		Package(){0x0018FFFF, 1, 0, UART1_INT},
+		Package(){0x0018FFFF, 2, 0, UART2_INT},
+		Package(){0x0018FFFF, 3, 0, UART3_INT},
+		Package(){0x0019FFFF, 0, 0, SPI0_INT},
+		Package(){0x0019FFFF, 1, 0, SPI1_INT},
+		Package(){0x0019FFFF, 2, 0, SPI2_INT},
+		Package(){0x001BFFFF, 0, 0, SDCARD_INT},
+		Package(){0x001CFFFF, 0, 0, EMMC_INT},
+		Package(){0x001EFFFF, 0, 0, SDIO_INT},
+		Package(){0x001FFFFF, 1, 0, SMBUS_INT},
+	})
+}

+ 22 - 0
arch/x86/include/asm/arch-apollolake/acpi/pcie.asl

@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corporation
+ */
+
+/* PCIe Ports */
+
+Device (RP01)
+{
+	Name (_ADR, 0x00140000)
+	Name (_DDN, "PCIe-B 0")
+
+	#include "pcie_port.asl"
+}
+
+Device (RP03)
+{
+	Name (_ADR, 0x00130000)
+	Name (_DDN, "PCIe-A 0")
+
+	#include "pcie_port.asl"
+}

+ 113 - 0
arch/x86/include/asm/arch-apollolake/acpi/pcie_port.asl

@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corporation
+ */
+
+/* Include in each PCIe Root Port device */
+
+/* lowest D-state supported by
+ * PCIe root port during S0 state
+ */
+Name (_S0W, 4)
+
+Name (PDST, 0) /* present Detect status */
+
+/* Dynamic Opregion needed to access registers
+ * when the controller is in D3 cold
+ */
+OperationRegion (PX01, PCI_Config, 0x00, 0xFF)
+Field (PX01, AnyAcc, NoLock, Preserve)
+{
+	Offset(0x5A),
+	, 6,
+	PDS, 1,		/* 6, Presence detect Change */
+	Offset(0xE2),	/* RPPGEN - Root Port Power Gating Enable */
+	, 2,
+	L23E, 1,	/* 2, L23_Rdy Entry Request (L23ER) */
+	L23R, 1,	/* 3, L23_Rdy to Detect Transition (L23R2DT) */
+	Offset(0xF4),	/* BLKPLLEN */
+	, 10,
+	BPLL, 1,
+}
+
+OperationRegion (PX02, PCI_Config, 0x338, 0x4)
+Field (PX02, AnyAcc, NoLock, Preserve)
+{
+	, 26,
+	BDQA, 1		/* BLKDQDA */
+}
+
+PowerResource (PXP, 0, 0)
+{
+	/* Define the PowerResource for PCIe slot */
+	Method (_STA, 0, Serialized)
+	{
+		Store (PDS, PDST)
+		If (LEqual (PDS, 1)) {
+			Return (0xf)
+		} Else {
+			Return (0)
+		}
+	}
+
+	Method (_ON, 0, Serialized)
+	{
+		If (LAnd (LEqual (PDST, 1), LNotEqual (\PRT0, 0))) {
+			/* Enter this condition if device
+			 * is connected
+			 */
+
+			/* De-assert PERST */
+			\_SB.PCI0.PRDA (\PRT0)
+
+			Store (0, BDQA) /* Set BLKDQDA to 0 */
+			Store (0, BPLL) /* Set BLKPLLEN to 0 */
+
+			/* Set L23_Rdy to Detect Transition
+			 * (L23R2DT)
+			 */
+			Store (1, L23R)
+			Sleep (16)
+			Store (0, Local0)
+
+			/* Delay for transition Detect
+			 * and link to train
+			 */
+			While (L23R) {
+				If (Lgreater (Local0, 4)) {
+					Break
+				}
+				Sleep (16)
+				Increment (Local0)
+			}
+		} /* End PDS condition check */
+	}
+
+	Method (_OFF, 0, Serialized)
+	{
+		/* Set L23_Rdy Entry Request (L23ER) */
+		If (LAnd (LEqual (PDST, 1), LNotEqual (\PRT0, 0))) {
+			/* enter this condition if device
+			 * is connected
+			 */
+			Store (1, L23E)
+			Sleep (16)
+			Store (0, Local0)
+			While (L23E) {
+				If (Lgreater (Local0, 4)) {
+					Break
+				}
+				Sleep (16)
+				Increment (Local0)
+			}
+			Store (1, BDQA) /* Set BLKDQDA to 1 */
+			Store (1, BPLL) /* Set BLKPLLEN to 1 */
+
+			/* Assert PERST */
+			\_SB.PCI0.PRAS (\PRT0)
+		} /* End PDS condition check */
+	} /* End of Method_OFF */
+} /* End PXP */
+
+Name(_PR0, Package() { PXP })
+Name(_PR3, Package() { PXP })

+ 10 - 0
arch/x86/include/asm/arch-apollolake/acpi/platform.asl

@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2012 Google Inc.
+ * Copyright (C) 2016 Intel Corp
+ */
+
+/* Enable ACPI _SWS methods */
+#include <soc/intel/common/acpi/acpi_wake_source.asl>
+#include <soc/intel/common/acpi/platform.asl>

+ 49 - 0
arch/x86/include/asm/arch-apollolake/acpi/pmc_ipc.asl

@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corp.
+ */
+
+#include <asm/arch/iomap.h>
+
+#define MAILBOX_DATA 0x7080
+#define MAILBOX_INTF 0x7084
+#define PMIO_LENGTH 0x80
+#define PMIO_LIMIT 0x480
+
+scope (\_SB) {
+	Device (IPC1)
+	{
+		Name (_HID, "INT34D2")
+		Name (_CID, "INT34D2")
+		Name (_DDN, "Intel(R) IPC1 Controller")
+		Name (RBUF, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, 0x0, 0x2000, IBAR)
+			Memory32Fixed (ReadWrite, 0x0, 0x4, MDAT)
+			Memory32Fixed (ReadWrite, 0x0, 0x4, MINF)
+			IO (Decode16, IOMAP_ACPI_BASE, PMIO_LIMIT,
+			      0x04, PMIO_LENGTH)
+			Memory32Fixed (ReadWrite, 0x0, 0x2000, SBAR)
+			Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , )
+			{
+			      PMC_INT
+			}
+		})
+
+		Method (_CRS, 0x0, NotSerialized)
+		{
+			CreateDwordField (^RBUF, ^IBAR._BAS, IBAS)
+			Store (PMC_BAR0, IBAS)
+
+			CreateDwordField (^RBUF, ^MDAT._BAS, MDBA)
+			Store (MCH_BASE_ADDRESS + MAILBOX_DATA, MDBA)
+			CreateDwordField (^RBUF, ^MINF._BAS, MIBA)
+			Store (MCH_BASE_ADDRESS + MAILBOX_INTF, MIBA)
+
+			CreateDwordField (^RBUF, ^SBAR._BAS, SBAS)
+			Store (SRAM_BASE_0, SBAS)
+
+			Return (^RBUF)
+		}
+	}
+}

+ 173 - 0
arch/x86/include/asm/arch-apollolake/acpi/scs.asl

@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+Scope (\_SB.PCI0) {
+	/* 0xD6- is the port address */
+	/* 0x600- is the dynamic clock gating control register offset (GENR) */
+	OperationRegion (SBMM, SystemMemory,
+		Or ( Or (IOMAP_P2SB_BAR,
+			ShiftLeft(0xD6, PCR_PORTID_SHIFT)), 0x0600), 0x18)
+	Field (SBMM, DWordAcc, NoLock, Preserve)
+	{
+		GENR, 32,
+		Offset (0x08),
+		,  5, /* bit[5] represents Force Card Detect SD Card */
+		GRR3,  1, /* GPPRVRW3 for SD Card detect Bypass. It's active high */
+	}
+
+	/* SCC power gate control method, this method must be serialized as
+	 * multiple device will control the GENR register
+	 *
+	 * Arguments: (2)
+	 * Arg0: 0-AND  1-OR
+	 * Arg1: Value
+	 */
+	Method (SCPG, 2, Serialized)
+	{
+		if (LEqual(Arg0, 0x1)) {
+			Or (^GENR, Arg1, ^GENR)
+		} ElseIf (LEqual(Arg0, 0x0)){
+			And (^GENR, Arg1, ^GENR)
+		}
+	}
+
+	/* eMMC */
+	Device (SDHA) {
+		Name (_ADR, 0x001C0000)
+		Name (_DDN, "Intel(R) eMMC Controller - 80865ACC")
+		Name (UUID, ToUUID ("E5C937D0-3553-4D7A-9117-EA4D19C3434D"))
+
+		/*
+		 * Device Specific Method
+		 * Arg0 - UUID
+		 * Arg1 - Revision
+		 * Arg2 - Function Index
+		 */
+		Method (_DSM, 4)
+		{
+			If (LEqual (Arg0, ^UUID)) {
+				/*
+				 * Function 9: Device Readiness Durations
+				 * Returns a package of five integers covering
+				 * various device related delays in PCIe Base Spec.
+				 */
+				If (LEqual (Arg2, 9)) {
+					/*
+					 * Function 9 support for revision 3.
+					 * ECN link for function definitions
+					 * [https://pcisig.com/sites/default/files/
+					 * specification_documents/
+					 * ECN_fw_latency_optimization_final.pdf]
+					 */
+					If (LEqual (Arg1, 3)) {
+						/*
+						 * Integer 0: FW reset time.
+						 * Integer 1: FW data link up time.
+						 * Integer 2: FW functional level reset
+						 * time.
+						 * Integer 3: FW D3 hot to D0 time.
+						 * Integer 4: FW VF enable time.
+						 * set ACPI constant Ones for elements
+						 * where overriding the default value
+						 * is not desired.
+						 */
+						Return (Package (5) {0, Ones, Ones,
+									    Ones, Ones})
+					}
+				}
+			}
+			Return (Buffer() { 0x00 })
+		}
+
+		Method (_PS0, 0, NotSerialized)
+		{
+			/* Clear clock gate
+			 * Clear bit 6 and 0
+			 */
+			^^SCPG(0,0xFFFFFFBE)
+			/* Sleep 2 ms */
+			Sleep (2)
+		}
+
+		Method (_PS3, 0, NotSerialized)
+		{
+			/* Enable power gate
+			 * Restore clock gate
+			 * Restore bit 6 and 0
+			 */
+			^^SCPG(1,0x00000041)
+		}
+
+		Device (CARD)
+		{
+			Name (_ADR, 0x00000008)
+			Method (_RMV, 0, NotSerialized)
+			{
+				Return (0)
+			}
+		}
+	} /* Device (SDHA) */
+
+	/* SD CARD */
+	Device (SDCD)
+	{
+		Name (_ADR, 0x001B0000)
+		Name (_S0W, 4) /* _S0W: S0 Device Wake State */
+		Name (SCD0, 0) /* Store SD_CD DW0 address */
+
+		/* Set the host ownership of sdcard cd during kernel boot */
+		Method (_INI, 0)
+		{
+			/* Check SDCard CD port is valid */
+			If (LAnd (LNotEqual (\SCDP, 0), LNotEqual (\SCDO, 0) ))
+			{
+				/* Store DW0 address of SD_CD */
+				Store (GDW0 (\SCDP, \SCDO), SCD0)
+				/* Get the current SD_CD ownership */
+				Store (\_SB.GHO (\SCDP, \SCDO), Local0)
+				/* Set host ownership as GPIO in HOSTSW_OWN reg */
+				Or (Local0, ShiftLeft (1,  Mod (\SCDO, 32)), Local0)
+				\_SB.SHO (\SCDP, \SCDO, Local0)
+			}
+		}
+
+		Method (_PS0, 0, NotSerialized)
+		{
+			/* Check SDCard CD port is valid */
+			If (LAnd (LNotEqual (\SCDP, 0), LNotEqual (\SCDO, 0) ))
+			{
+				/* Store DW0 into local0 to get rxstate of GPIO */
+				Store (\_SB.GPC0 (SCD0), Local0)
+				/* Extract rxstate [bit 1] of sdcard card detect pin */
+				And (Local0, PAD_CFG0_RX_STATE, Local0)
+				/* If the sdcard is present, rxstate is low.
+				 * If sdcard is not present, rxstate is High.
+				 * Write the inverted value of rxstate to GRR3.
+				 */
+				If (LEqual (Local0, 0)) {
+					Store (1, ^^GRR3)
+				} Else {
+					Store (0, ^^GRR3)
+				}
+				Sleep (2)
+			}
+		}
+
+		Method (_PS3, 0, NotSerialized)
+		{
+			/* Clear GRR3 to Power Gate SD Controller */
+			Store (0, ^^GRR3)
+		}
+
+		Device (CARD)
+		{
+			Name (_ADR, 0x00000008)
+			Method (_RMV, 0, NotSerialized)
+			{
+				Return (1)
+			}
+		}
+	} /* Device (SDCD) */
+}

+ 50 - 0
arch/x86/include/asm/arch-apollolake/acpi/soc_int.asl

@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ */
+
+#ifndef _SOC_INT_DEFINE_ASL_
+#define _SOC_INT_DEFINE_ASL_
+
+#define SDCARD_INT	3	/* Need to be shared by PMC and SCC only*/
+#define UART0_INT	4	/* Need to be shared by PMC and SCC only*/
+#define UART1_INT	5	/* Need to be shared by PMC and SCC only*/
+#define UART2_INT	6	/* Need to be shared by PMC and SCC only*/
+#define UART3_INT	7	/* Need to be shared by PMC and SCC only*/
+#define XDCI_INT	13	/* Need to be shared by PMC and SCC only*/
+#define GPIO_BANK_INT	14
+#define NPK_INT		16
+#define PIRQA_INT	16
+#define PIRQB_INT	17
+#define PIRQC_INT	18
+#define SATA_INT	19
+#define GEN_INT		19
+#define PIRQD_INT	19
+#define XHCI_INT	17	/* Need to be shared by PMC and SCC only*/
+#define SMBUS_INT	20	/* PIRQE */
+#define CSE_INT		20	/* PIRQE */
+#define IUNIT_INT	21	/* PIRQF */
+#define PIRQF_INT	21
+#define PIRQG_INT	22
+#define PUNIT_INT	24
+#define AUDIO_INT	25
+#define ISH_INT		26
+#define I2C0_INT	27
+#define I2C1_INT	28
+#define I2C2_INT	29
+#define I2C3_INT	30
+#define I2C4_INT	31
+#define I2C5_INT	32
+#define I2C6_INT	33
+#define I2C7_INT	34
+#define SPI0_INT	35
+#define SPI1_INT	36
+#define SPI2_INT	37
+#define UFS_INT		38
+#define EMMC_INT	39
+#define PMC_INT		40
+#define SDIO_INT	42
+#define CNVI_INT	44
+
+#endif	/* _SOC_INT_DEFINE_ASL_ */

+ 34 - 0
arch/x86/include/asm/arch-apollolake/acpi/southbridge.asl

@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ */
+
+#include <p2sb.h>
+#include <asm/arch/gpe.h>
+
+/* PCIE device */
+#include "pcie.asl"
+
+/* LPSS device */
+#include "lpss.asl"
+
+/* PCI IRQ assignment */
+#include "pci_irqs.asl"
+
+/* GPIO controller */
+#include "gpio.asl"
+
+#include "xhci.asl"
+
+/* LPC */
+#include <asm/acpi/lpc.asl>
+
+/* eMMC */
+#include "scs.asl"
+
+/* PMC IPC controller */
+#include "pmc_ipc.asl"
+
+/* PCI _OSC */
+#include <asm/acpi/pci_osc.asl>

+ 33 - 0
arch/x86/include/asm/arch-apollolake/acpi/xhci.asl

@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+/* XHCI Controller 0:15.0 */
+Device (XHCI) {
+	Name (_ADR, 0x00150000)  /* Device 21, Function 0 */
+
+	Name (_S3D, 3)  /* D3 supported in S3 */
+	Name (_S0W, 3)  /* D3 can wake device in S0 */
+	Name (_S3W, 3)  /* D3 can wake system from S3 */
+
+	/* Declare XHCI GPE status and enable bits are bit 13 */
+	Name (_PRW, Package() { GPE0A_XHCI_PME_STS, 3 })
+
+	Method (_STA, 0)
+	{
+		Return (0xF)
+	}
+
+	Device (RHUB)
+	{
+		/* Root Hub */
+		Name (_ADR, Zero)
+
+#if IS_ENABLED(CONFIG_SOC_INTEL_GLK)
+#include "xhci_glk_ports.asl"
+#else
+#include "xhci_apl_ports.asl"
+#endif
+	}
+}

+ 23 - 0
arch/x86/include/asm/arch-apollolake/acpi/xhci_apl_ports.asl

@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 Google LLC.
+ * Copyright 2019 Intel Corp.
+ */
+
+/* USB2 */
+Device (HS01) { Name (_ADR, 1) }
+Device (HS02) { Name (_ADR, 2) }
+Device (HS03) { Name (_ADR, 3) }
+Device (HS04) { Name (_ADR, 4) }
+Device (HS05) { Name (_ADR, 5) }
+Device (HS06) { Name (_ADR, 6) }
+Device (HS07) { Name (_ADR, 7) }
+Device (HS08) { Name (_ADR, 8) }
+
+/* USB3 */
+Device (SS01) { Name (_ADR, 9) }
+Device (SS02) { Name (_ADR, 10) }
+Device (SS03) { Name (_ADR, 11) }
+Device (SS04) { Name (_ADR, 12) }
+Device (SS05) { Name (_ADR, 13) }
+Device (SS06) { Name (_ADR, 14) }

+ 24 - 0
arch/x86/include/asm/arch-apollolake/acpi/xhci_glk_ports.asl

@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 Google LLC.
+ * Copyright 2019 Intel Corp.
+ */
+
+/* USB2 */
+Device (HS01) { Name (_ADR, 1) }
+Device (HS02) { Name (_ADR, 2) }
+Device (HS03) { Name (_ADR, 3) }
+Device (HS04) { Name (_ADR, 4) }
+Device (HS05) { Name (_ADR, 5) }
+Device (HS06) { Name (_ADR, 6) }
+Device (HS07) { Name (_ADR, 7) }
+Device (HS08) { Name (_ADR, 8) }
+Device (HS09) { Name (_ADR, 9) }
+
+/* USB3 */
+Device (SS01) { Name (_ADR, 10) }
+Device (SS02) { Name (_ADR, 11) }
+Device (SS03) { Name (_ADR, 12) }
+Device (SS04) { Name (_ADR, 13) }
+Device (SS05) { Name (_ADR, 14) }
+Device (SS06) { Name (_ADR, 15) }

+ 1 - 22
arch/x86/include/asm/arch-apollolake/global_nvs.h

@@ -10,27 +10,6 @@
 #ifndef _GLOBAL_NVS_H_
 #define _GLOBAL_NVS_H_
 
-struct __packed acpi_global_nvs {
-	/* Miscellaneous */
-	u8	pcnt; /* 0x00 - Processor Count */
-	u8	ppcm; /* 0x01 - Max PPC State */
-	u8	lids; /* 0x02 - LID State */
-	u8	pwrs; /* 0x03 - AC Power State */
-	u8	dpte; /* 0x04 - Enable DPTF */
-	u32	cbmc; /* 0x05 - 0x08 - U-Boot Console */
-	u64	pm1i; /* 0x09 - 0x10 - System Wake Source - PM1 Index */
-	u64	gpei; /* 0x11 - 0x18 - GPE Wake Source */
-	u64	nhla; /* 0x19 - 0x20 - NHLT Address */
-	u32	nhll; /* 0x21 - 0x24 - NHLT Length */
-	u32	prt0; /* 0x25 - 0x28 - PERST_0 Address */
-	u8	scdp; /* 0x29 - SD_CD GPIO portid */
-	u8	scdo; /* 0x2a - GPIO pad offset relative to the community */
-	u8	uior; /* 0x2b - UART debug controller init on S3 resume */
-	u8	ecps; /* 0x2c - SGX Enabled status */
-	u64	emna; /* 0x2d - 0x34 EPC base address */
-	u64	elng; /* 0x35 - 0x3c EPC Length */
-	u8	unused1[0x100 - 0x3d];		/* Pad out to 256 bytes */
-	u8	unused2[0x1000 - 0x100];	/* Pad out to 4096 bytes */
-};
+#include <asm/intel_gnvs.h>
 
 #endif /* _GLOBAL_NVS_H_ */

+ 135 - 0
arch/x86/include/asm/arch-apollolake/gpe.h

@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Intel Corporation
+ * Copyright 2020 Google LLC
+ *
+ * Taken from coreboot apl gpe.h
+ */
+
+#ifndef _ASM_ARCH_GPE_H_
+#define _ASM_ARCH_GPE_H_
+
+/* bit position in GPE0a_STS register */
+#define GPE0A_PCIE_SCI_STS		0
+#define GPE0A_SWGPE_STS			2
+#define GPE0A_PCIE_WAKE0_STS		3
+#define GPE0A_PUNIT_SCI_STS		4
+#define GPE0A_PCIE_WAKE1_STS		6
+#define GPE0A_PCIE_WAKE2_STS		7
+#define GPE0A_PCIE_WAKE3_STS		8
+#define GPE0A_PCIE_GPE_STS		9
+#define GPE0A_BATLOW_STS		10
+#define GPE0A_CSE_PME_STS		11
+#define GPE0A_XDCI_PME_STS		12
+#define GPE0A_XHCI_PME_STS		13
+#define GPE0A_AVS_PME_STS		14
+#define GPE0A_GPIO_TIER1_SCI_STS	15
+#define GPE0A_SMB_WAK_STS		16
+#define GPE0A_SATA_PME_STS		17
+#define GPE0A_CNVI_PME_STS	        18
+
+/* Group DW0 is reserved in Apollolake */
+
+/* GPE_63_32 */
+#define GPE0_DW1_00		32
+#define GPE0_DW1_01		33
+#define GPE0_DW1_02		34
+#define GPE0_DW1_03		36
+#define GPE0_DW1_04		36
+#define GPE0_DW1_05		37
+#define GPE0_DW1_06		38
+#define GPE0_DW1_07		39
+#define GPE0_DW1_08		40
+#define GPE0_DW1_09		41
+#define GPE0_DW1_10		42
+#define GPE0_DW1_11		43
+#define GPE0_DW1_12		44
+#define GPE0_DW1_13		45
+#define GPE0_DW1_14		46
+#define GPE0_DW1_15		47
+#define GPE0_DW1_16		48
+#define GPE0_DW1_17		49
+#define GPE0_DW1_18		50
+#define GPE0_DW1_19		51
+#define GPE0_DW1_20		52
+#define GPE0_DW1_21		53
+#define GPE0_DW1_22		54
+#define GPE0_DW1_23		55
+#define GPE0_DW1_24		56
+#define GPE0_DW1_25		57
+#define GPE0_DW1_26		58
+#define GPE0_DW1_27		59
+#define GPE0_DW1_28		60
+#define GPE0_DW1_29		61
+#define GPE0_DW1_30		62
+#define GPE0_DW1_31		63
+/* GPE_95_64 */
+#define GPE0_DW2_00		64
+#define GPE0_DW2_01		65
+#define GPE0_DW2_02		66
+#define GPE0_DW2_03		67
+#define GPE0_DW2_04		68
+#define GPE0_DW2_05		69
+#define GPE0_DW2_06		70
+#define GPE0_DW2_07		71
+#define GPE0_DW2_08		72
+#define GPE0_DW2_09		73
+#define GPE0_DW2_10		74
+#define GPE0_DW2_11		75
+#define GPE0_DW2_12		76
+#define GPE0_DW2_13		77
+#define GPE0_DW2_14		78
+#define GPE0_DW2_15		79
+#define GPE0_DW2_16		80
+#define GPE0_DW2_17		81
+#define GPE0_DW2_18		82
+#define GPE0_DW2_19		83
+#define GPE0_DW2_20		84
+#define GPE0_DW2_21		85
+#define GPE0_DW2_22		86
+#define GPE0_DW2_23		87
+#define GPE0_DW2_24		88
+#define GPE0_DW2_25		89
+#define GPE0_DW2_26		90
+#define GPE0_DW2_27		91
+#define GPE0_DW2_28		92
+#define GPE0_DW2_29		93
+#define GPE0_DW2_30		94
+#define GPE0_DW2_31		95
+/* GPE_127_96 */
+#define GPE0_DW3_00		96
+#define GPE0_DW3_01		97
+#define GPE0_DW3_02		98
+#define GPE0_DW3_03		99
+#define GPE0_DW3_04		100
+#define GPE0_DW3_05		101
+#define GPE0_DW3_06		102
+#define GPE0_DW3_07		103
+#define GPE0_DW3_08		104
+#define GPE0_DW3_09		105
+#define GPE0_DW3_10		106
+#define GPE0_DW3_11		107
+#define GPE0_DW3_12		108
+#define GPE0_DW3_13		109
+#define GPE0_DW3_14		110
+#define GPE0_DW3_15		111
+#define GPE0_DW3_16		112
+#define GPE0_DW3_17		113
+#define GPE0_DW3_18		114
+#define GPE0_DW3_19		115
+#define GPE0_DW3_20		116
+#define GPE0_DW3_21		117
+#define GPE0_DW3_22		118
+#define GPE0_DW3_23		119
+#define GPE0_DW3_24		120
+#define GPE0_DW3_25		121
+#define GPE0_DW3_26		122
+#define GPE0_DW3_27		123
+#define GPE0_DW3_28		124
+#define GPE0_DW3_29		125
+#define GPE0_DW3_30		126
+#define GPE0_DW3_31		127
+
+#define GPE_MAX			GPE0_DW3_31
+
+#endif

+ 3 - 0
arch/x86/include/asm/arch-apollolake/gpio.h

@@ -482,4 +482,7 @@
 #define GPIO_72_IRQ			0x65
 #define GPIO_73_IRQ			0x66
 
+/* This is needed by ACPI */
+#define GPIO_NUM_PAD_CFG_REGS   2 /* DW0, DW1 */
+
 #endif /* _ASM_ARCH_GPIO_H_ */

+ 16 - 0
arch/x86/include/asm/arch-apollolake/iomap.h

@@ -11,11 +11,27 @@
 
 /* Put p2sb at 0xd0000000 in TPL */
 #define IOMAP_P2SB_BAR		0xd0000000
+#define IOMAP_P2SB_SIZE		0x10000000
 
 #define IOMAP_SPI_BASE		0xfe010000
 
 #define IOMAP_ACPI_BASE		0x400
 #define IOMAP_ACPI_SIZE		0x100
+#define ACPI_BASE_ADDRESS	IOMAP_ACPI_BASE
+
+#define PMC_BAR0		0xfe042000
+
+#define MCH_BASE_ADDRESS	0xfed10000
+#define MCH_SIZE		0x8000
+
+#ifdef __ACPI__
+#define HPET_BASE_ADDRESS	0xfed00000
+
+#define SRAM_BASE_0		0xfe900000
+#define SRAM_SIZE_0		(8 * KiB)
+#define SRAM_BASE_2		0xfe902000
+#define SRAM_SIZE_2		(4 * KiB)
+#endif
 
 /*
  * Use UART2. To use UART1 you need to set '2' to '1', change device tree serial

+ 39 - 1
arch/x86/include/asm/arch-apollolake/pm.h

@@ -1,12 +1,15 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2015-2016 Intel Corp.
  * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
+ * Copyright 2019 Google LLC
  */
 
 #ifndef _ASM_ARCH_PM_H
 #define _ASM_ARCH_PM_H
 
+#include <power/acpi_pmc.h>
+
 #define PMC_GPE_SW_31_0	0
 #define PMC_GPE_SW_63_32	1
 #define PMC_GPE_NW_31_0	3
@@ -16,4 +19,39 @@
 #define PMC_GPE_N_63_32	7
 #define PMC_GPE_W_31_0		9
 
+#define IRQ_REG			0x106c
+#define SCI_IRQ_SHIFT		24
+#define SCI_IRQ_MASK		(0xff << SCI_IRQ_SHIFT)
+#define SCIS_IRQ9		9
+#define SCIS_IRQ10		10
+#define SCIS_IRQ11		11
+#define SCIS_IRQ20		20
+#define SCIS_IRQ21		21
+#define SCIS_IRQ22		22
+#define SCIS_IRQ23		23
+
+/* P-state configuration */
+#define PSS_MAX_ENTRIES		8
+#define PSS_RATIO_STEP		2
+#define PSS_LATENCY_TRANSITION	10
+#define PSS_LATENCY_BUSMASTER	10
+
+#ifndef __ASSEMBLY__
+/* Track power state from reset to log events */
+struct __packed chipset_power_state {
+	u16 pm1_sts;
+	u16 pm1_en;
+	u32 pm1_cnt;
+	u32 gpe0_sts[GPE0_REG_MAX];
+	u32 gpe0_en[GPE0_REG_MAX];
+	u16 tco1_sts;
+	u16 tco2_sts;
+	u32 prsts;
+	u32 gen_pmcon1;
+	u32 gen_pmcon2;
+	u32 gen_pmcon3;
+	u32 prev_sleep_state;
+};
+#endif /* !__ASSEMBLY__ */
+
 #endif

+ 31 - 0
arch/x86/include/asm/arch-apollolake/systemagent.h

@@ -35,4 +35,35 @@
  */
 void enable_bios_reset_cpl(void);
 
+/**
+ * sa_get_tolud_base() - Get the TOLUD base address
+ *
+ * This returns the Top Of Low Useable DRAM, marking the top of usable DRAM
+ * below 4GB
+ *
+ * @dev: hostbridge device
+ * @return TOLUD address
+ */
+ulong sa_get_tolud_base(struct udevice *dev);
+
+/**
+ * sa_get_gsm_base() - Get the GSM base address
+ *
+ * This returns the base of GTT Stolen Memory, marking the start of memory used
+ * for Graphics Translation Tables.
+ *
+ * @dev: hostbridge device
+ * @return GSM address
+ */
+ulong sa_get_gsm_base(struct udevice *dev);
+
+/**
+ * sa_get_tseg_base() - Get the TSEG base address
+ *
+ * This returns the top address of DRAM available below 4GB
+ *
+ * @return TSEG base
+ */
+ulong sa_get_tseg_base(struct udevice *dev);
+
 #endif

+ 19 - 6
arch/x86/include/asm/bootparam.h

@@ -24,6 +24,11 @@ struct setup_data {
 	__u8 data[0];
 };
 
+/**
+ * struct setup_header - Information needed by Linux to boot
+ *
+ * See https://www.kernel.org/doc/html/latest/x86/boot.html
+ */
 struct setup_header {
 	__u8	setup_sects;
 	__u16	root_flags;
@@ -43,15 +48,16 @@ struct setup_header {
 	__u16	kernel_version;
 	__u8	type_of_loader;
 	__u8	loadflags;
-#define LOADED_HIGH	(1<<0)
-#define QUIET_FLAG	(1<<5)
-#define KEEP_SEGMENTS	(1<<6)
-#define CAN_USE_HEAP	(1<<7)
+#define LOADED_HIGH	BIT(0)
+#define KASLR_FLAG	BIT(1)
+#define QUIET_FLAG	BIT(5)
+#define KEEP_SEGMENTS	BIT(6)		/* Obsolete */
+#define CAN_USE_HEAP	BIT(7)
 	__u16	setup_move_size;
 	__u32	code32_start;
 	__u32	ramdisk_image;
 	__u32	ramdisk_size;
-	__u32	bootsect_kludge;
+	__u32	bootsect_kludge;	/* Obsolete */
 	__u16	heap_end_ptr;
 	__u8	ext_loader_ver;
 	__u8	ext_loader_type;
@@ -59,7 +65,13 @@ struct setup_header {
 	__u32	initrd_addr_max;
 	__u32	kernel_alignment;
 	__u8	relocatable_kernel;
-	__u8	_pad2[3];
+	u8	min_alignment;
+#define XLF_KERNEL_64			BIT(0)
+#define XLF_CAN_BE_LOADED_ABOVE_4G	BIT(1)
+#define XLF_EFI_HANDOVER_32		BIT(2)
+#define XLF_EFI_HANDOVER_64		BIT(3)
+#define XLF_EFI_KEXEC			BIT(4)
+	u16	xloadflags;
 	__u32	cmdline_size;
 	__u32	hardware_subarch;
 	__u64	hardware_subarch_data;
@@ -69,6 +81,7 @@ struct setup_header {
 	__u64	pref_address;
 	__u32	init_size;
 	__u32	handover_offset;
+	u32	kernel_info_offset;
 } __attribute__((packed));
 
 struct sys_desc_table {

+ 9 - 0
arch/x86/include/asm/cpu.h

@@ -288,4 +288,13 @@ u32 cpu_get_family_model(void);
  */
 u32 cpu_get_stepping(void);
 
+/**
+ * cpu_phys_address_size() - Get the physical address size in bits
+ *
+ * This is 32 for older CPUs but newer ones may support 36.
+ *
+ * @return address size (typically 32 or 36)
+ */
+int cpu_phys_address_size(void);
+
 #endif

+ 56 - 0
arch/x86/include/asm/cpu_common.h

@@ -128,4 +128,60 @@ void cpu_set_eist(bool eist_status);
  */
 void cpu_set_p_state_to_turbo_ratio(void);
 
+/**
+ * cpu_get_coord_type() - Get the type of coordination for P-State transition
+ *
+ * See ACPI spec v6.3 section 8.4.6.5 _PSD (P-State Dependency)
+ *
+ * @return HW_ALL (always)
+ */
+int cpu_get_coord_type(void);
+
+/**
+ * cpu_get_min_ratio() - get minimum support frequency ratio for CPU
+ *
+ * @return minimum ratio
+ */
+int cpu_get_min_ratio(void);
+
+/**
+ * cpu_get_max_ratio() - get nominal TDP ration or max non-turbo ratio
+ *
+ * If a nominal TDP ratio is available, it is returned. Otherwise this returns
+ * the  maximum non-turbo frequency ratio for this processor
+ *
+ * @return max ratio
+ */
+int cpu_get_max_ratio(void);
+
+/**
+ * cpu_get_bus_clock_khz() - Get the bus clock frequency in KHz
+ *
+ * This is the value the clock ratio is multiplied with
+ *
+ * @return bus-block frequency in KHz
+ */
+int cpu_get_bus_clock_khz(void);
+
+/**
+ * cpu_get_power_max() - Get maximum CPU TDP
+ *
+ * @return maximum CPU TDP (Thermal-design power) in mW
+ */
+int cpu_get_power_max(void);
+
+/**
+ * cpu_get_max_turbo_ratio() - Get maximum turbo ratio
+ *
+ * @return maximum ratio
+ */
+int cpu_get_max_turbo_ratio(void);
+
+/**
+ * cpu_get_cores_per_package() - Get the number of CPU cores in each package
+ *
+ * @return number of cores
+ */
+int cpu_get_cores_per_package(void);
+
 #endif

+ 2 - 2
arch/x86/include/asm/e820.h

@@ -8,6 +8,7 @@
 #define E820_ACPI	3
 #define E820_NVS	4
 #define E820_UNUSABLE	5
+#define E820_COUNT	6	/* Number of types */
 
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
@@ -21,10 +22,9 @@ struct e820_entry {
 #define ISA_START_ADDRESS	0xa0000
 #define ISA_END_ADDRESS		0x100000
 
-#endif /* __ASSEMBLY__ */
-
 /* Implementation defined function to install an e820 map */
 unsigned int install_e820_map(unsigned int max_entries,
 			      struct e820_entry *);
+#endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_E820_H */

+ 12 - 3
arch/x86/include/asm/fsp/fsp_api.h

@@ -10,9 +10,18 @@
 
 enum fsp_phase {
 	/* Notification code for post PCI enuermation */
-	INIT_PHASE_PCI	= 0x20,
-	/* Notification code before transferring control to the payload */
-	INIT_PHASE_BOOT	= 0x40
+	INIT_PHASE_PCI		= 0x20,
+	/*
+	 * Notification code before transferring control to the payload.
+	 * This is issued at the end of init before starting main(), i.e.
+	 * the command line / boot script.
+	 */
+	INIT_PHASE_BOOT		= 0x40,
+	/*
+	 * Notification code before existing boot services. This is issued
+	 * just before removing devices and booting the kernel.
+	 */
+	INIT_PHASE_END_FIRMWARE	= 0xf0,
 };
 
 struct fsp_notify_params {

+ 25 - 0
arch/x86/include/asm/fsp/fsp_hob.h

@@ -99,4 +99,29 @@ struct __packed hob_graphics_info {
 	EFI_GUID(0x39f62cce, 0x6825, 0x4669, \
 		0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07)
 
+/* The following GUIDs are observed with FSP 2.1 / Apollo Lake */
+#define FSP_HOB_RESOURCE_OWNER_SMM_PEI_SMRAM_GUID \
+	EFI_GUID(0x6dadf1d1, 0xd4cc, 0x4910, \
+		0xbb, 0x6e, 0x82, 0xb1, 0xfd, 0x80, 0xff, 0x3d)
+
+#define FSP_HOB_RESOURCE_OWNER_PCD_DATABASE_GUID1 \
+	EFI_GUID(0xea296d92, 0x0b69, 0x423c, \
+		0x8c, 0x28, 0x33, 0xb4, 0xe0, 0xa9, 0x12, 0x68)
+
+#define FSP_HOB_RESOURCE_OWNER_PCD_DATABASE_GUID2 \
+	EFI_GUID(0x9b3ada4f, 0xae56, 0x4c24, \
+		0x8d, 0xea, 0xf0, 0x3b, 0x75, 0x58, 0xae, 0x50)
+
+#define FSP_HOB_RESOURCE_OWNER_PEIM_DXE_GUID \
+	EFI_GUID(0x86d70125, 0xbaa3, 0x4296, \
+		0xa6, 0x2f, 0x60, 0x2b, 0xeb, 0xbb, 0x90, 0x81)
+
+#define FSP_HOB_RESOURCE_OWNER_ALLOC_STACK_GUID \
+	EFI_GUID(0x4ed4bf27, 0x4092, 0x42e9, \
+		0x80, 0x7d, 0x52, 0x7b, 0x1d, 0x00, 0xc9, 0xbd)
+
+#define FSP_HOB_RESOURCE_OWNER_SMBIOS_MEMORY_GUID \
+	EFI_GUID(0x01a1108c, 0x9dee, 0x4984, \
+		0x88, 0xc3, 0xee, 0xe8, 0xc4, 0x9e, 0xfb, 0x89)
+
 #endif

+ 52 - 0
arch/x86/include/asm/intel_acpi.h

@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#ifndef __ASM_INTEL_ACPI_H__
+#define __ASM_INTEL_ACPI_H__
+
+struct acpi_cstate;
+struct acpi_ctx;
+struct acpi_tstate;
+struct udevice;
+
+/**
+ * acpi_generate_cpu_header() - Start generating an ACPI CPU entry
+ *
+ * Generates the ACPI information for a CPU. After this, the caller should
+ * generate_p_state_entries(), generate_t_state_entries and then
+ * acpigen_pop_len() to close off this package.
+ *
+ * @ctx: ACPI context pointer
+ * @core_id: CPU core number, as numbered by the SoC
+ * @c_state_map: Information about each C state
+ * @num_cstates: Number of entries in @c_state_map
+ * @return 0 if OK, -ve on error
+ */
+int acpi_generate_cpu_header(struct acpi_ctx *ctx, int core_id,
+			     const struct acpi_cstate *c_state_map,
+			     int num_cstates);
+
+/**
+ * acpi_generate_cpu_package_final() - Write out the CPU PPKG entry
+ *
+ * This writes information about the CPUs in the package
+ *
+ * @ctx: ACPI context pointer
+ * @cores_per_package: Number of CPU cores in each package in the SoC
+ */
+int acpi_generate_cpu_package_final(struct acpi_ctx *ctx,
+				    int cores_per_package);
+
+void generate_p_state_entries(struct acpi_ctx *ctx, int core,
+			      int cores_per_package);
+void generate_t_state_entries(struct acpi_ctx *ctx, int core,
+			      int cores_per_package, struct acpi_tstate *entry,
+			      int nentries);
+int southbridge_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx);
+
+int intel_southbridge_write_acpi_tables(const struct udevice *dev,
+					struct acpi_ctx *ctx);
+
+#endif /* __ASM_INTEL_ACPI_H__ */

+ 44 - 0
arch/x86/include/asm/intel_gnvs.h

@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ *
+ * Taken from coreboot intelblocks/nvs.h
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef _INTEL_GNVS_H_
+#define _INTEL_GNVS_H_
+
+struct __packed acpi_global_nvs {
+	/* Miscellaneous */
+	u8	pcnt; /* 0x00 - Processor Count */
+	u8	ppcm; /* 0x01 - Max PPC State */
+	u8	lids; /* 0x02 - LID State */
+	u8	pwrs; /* 0x03 - AC Power State */
+	u8	dpte; /* 0x04 - Enable DPTF */
+	u32	cbmc; /* 0x05 - 0x08 - coreboot Memory Console */
+	u64	pm1i; /* 0x09 - 0x10 - System Wake Source - PM1 Index */
+	u64	gpei; /* 0x11 - 0x18 - GPE Wake Source */
+	u64	nhla; /* 0x19 - 0x20 - NHLT Address */
+	u32	nhll; /* 0x21 - 0x24 - NHLT Length */
+	u32	prt0; /* 0x25 - 0x28 - PERST_0 Address */
+	u8	scdp; /* 0x29 - SD_CD GPIO portid */
+	u8	scdo; /* 0x2a - GPIO pad offset relative to the community */
+	u8	uior; /* 0x2b - UART debug controller init on S3 resume */
+	u8	ecps; /* 0x2c - SGX Enabled status */
+	u64	emna; /* 0x2d - 0x34 EPC base address */
+	u64	elng; /* 0x35 - 0x3C EPC Length */
+	u8	unused1[0x100 - 0x3d];		/* Pad out to 256 bytes */
+#ifdef CONFIG_CHROMEOS
+	/* ChromeOS-specific (0x100 - 0xfff) */
+	struct chromeos_acpi chromeos;
+#else
+	u8	unused2[0x1000 - 0x100];	/* Pad out to 4096 bytes */
+#endif
+};
+
+#ifdef CONFIG_CHROMEOS
+check_member(acpi_global_nvs, chromeos, GNVS_CHROMEOS_ACPI_OFFSET);
+#endif
+
+#endif /* _INTEL_GNVS_H_ */

+ 247 - 0
arch/x86/include/asm/intel_opregion.h

@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Writing IntelGraphicsMem table for ACPI
+ *
+ * Copyright 2019 Google LLC
+ * Modified from coreboot src/soc/intel/gma/opregion.h
+ */
+
+#ifndef _ASM_INTEL_OPREGION_H_
+#define _ASM_INTEL_OPREGION_H_
+
+#define VBT_SIGNATURE		0x54425624
+
+/* IGD PCI Configuration register */
+#define ASLS		0xfc		/* OpRegion Base */
+#define SWSCI		0xe8		/* SWSCI Register */
+#define SWSMISCI	0xe0		/* SWSMISCI Register */
+#define GSSCIE		BIT(0)		/* SCI Event trigger */
+#define SMISCISEL	BIT(15)		/* Select SMI or SCI event source */
+
+/* mailbox 0: header */
+struct __packed opregion_header {
+	u8	signature[16];	    /* Offset 0    OpRegion signature */
+	u32	size;		    /* Offset 16   OpRegion size */
+	u32	version;	    /* Offset 20   OpRegion structure version */
+	u8	sbios_version[32];  /* Offset 24   System BIOS build version */
+	u8	vbios_version[16];  /* Offset 56   Video BIOS build version */
+	u8	driver_version[16]; /* Offset 72   Graphic drvr build version */
+	u32	mailboxes;	    /* Offset 88   Mailboxes supported */
+	u32	dmod;		    /* Offset 92   Driver Model */
+	u32	pcon;		    /* Offset 96   Platform Capabilities */
+	u16	dver[16];	    /* Offset 100  GOP Version */
+	u8	reserved[124];	    /* Offset 132  Reserved */
+};
+
+#define IGD_OPREGION_SIGNATURE "IntelGraphicsMem"
+#define IGD_OPREGION_VERSION  2
+
+#define IGD_MBOX1	BIT(0)
+#define IGD_MBOX2	BIT(1)
+#define IGD_MBOX3	BIT(2)
+#define IGD_MBOX4	BIT(3)
+#define IGD_MBOX5	BIT(4)
+
+#define MAILBOXES_MOBILE  (IGD_MBOX1 | IGD_MBOX2 | IGD_MBOX3 | \
+			   IGD_MBOX4 | IGD_MBOX5)
+#define MAILBOXES_DESKTOP (IGD_MBOX2 | IGD_MBOX4)
+
+#define SBIOS_VERSION_SIZE 32
+
+/* mailbox 1: public ACPI methods */
+struct __packed opregion_mailbox1 {
+	u32	drdy;	/* Offset 0    Driver readiness */
+	u32	csts;	/* Offset 4    Status */
+	u32	cevt;	/* Offset 8    Current event */
+	u8	reserved[20];	/* Offset 12   Reserved */
+	u32	didl;	/* Offset 32   Supported display device 1 */
+	u32	ddl2;	/* Offset 36   Supported display device 2 */
+	u32	ddl3;	/* Offset 40   Supported display device 3 */
+	u32	ddl4;	/* Offset 44   Supported display device 4 */
+	u32	ddl5;	/* Offset 48   Supported display device 5 */
+	u32	ddl6;	/* Offset 52   Supported display device 6 */
+	u32	ddl7;	/* Offset 56   Supported display device 7 */
+	u32	ddl8;	/* Offset 60   Supported display device 8 */
+	u32	cpdl;	/* Offset 64   Currently present display device 1 */
+	u32	cpl2;	/* Offset 68   Currently present display device 2 */
+	u32	cpl3;	/* Offset 72   Currently present display device 3 */
+	u32	cpl4;	/* Offset 76   Currently present display device 4 */
+	u32	cpl5;	/* Offset 80   Currently present display device 5 */
+	u32	cpl6;	/* Offset 84   Currently present display device 6 */
+	u32	cpl7;	/* Offset 88   Currently present display device 7 */
+	u32	cpl8;	/* Offset 92   Currently present display device 8 */
+	u32	cadl;	/* Offset 96   Currently active display device 1 */
+	u32	cal2;	/* Offset 100  Currently active display device 2 */
+	u32	cal3;	/* Offset 104  Currently active display device 3 */
+	u32	cal4;	/* Offset 108  Currently active display device 4 */
+	u32	cal5;	/* Offset 112  Currently active display device 5 */
+	u32	cal6;	/* Offset 116  Currently active display device 6 */
+	u32	cal7;	/* Offset 120  Currently active display device 7 */
+	u32	cal8;	/* Offset 124  Currently active display device 8 */
+	u32	nadl;	/* Offset 128  Next active device 1 */
+	u32	ndl2;	/* Offset 132  Next active device 2 */
+	u32	ndl3;	/* Offset 136  Next active device 3 */
+	u32	ndl4;	/* Offset 140  Next active device 4 */
+	u32	ndl5;	/* Offset 144  Next active device 5 */
+	u32	ndl6;	/* Offset 148  Next active device 6 */
+	u32	ndl7;	/* Offset 152  Next active device 7 */
+	u32	ndl8;	/* Offset 156  Next active device 8 */
+	u32	aslp;	/* Offset 160  ASL sleep timeout */
+	u32	tidx;	/* Offset 164  Toggle table index */
+	u32	chpd;	/* Offset 168  Current hot plug enable indicator */
+	u32	clid;	/* Offset 172  Current lid state indicator */
+	u32	cdck;	/* Offset 176  Current docking state indicator */
+	u32	sxsw;	/* Offset 180  Display Switch notification on Sx State
+			 * resume
+			 */
+	u32	evts;	/* Offset 184  Events supported by ASL */
+	u32	cnot;	/* Offset 188  Current OS Notification */
+	u32	nrdy;	/* Offset 192  Reasons for DRDY = 0 */
+	u32	ddl9;	/* Offset 196  Extended Supported display device 1 */
+	u32	dd10;	/* Offset 200  Extended Supported display device 2 */
+	u32	dd11;	/* Offset 204  Extended Supported display device 3 */
+	u32	dd12;	/* Offset 208  Extended Supported display device 4 */
+	u32	dd13;	/* Offset 212  Extended Supported display device 5 */
+	u32	dd14;	/* Offset 216  Extended Supported display device 6 */
+	u32	dd15;	/* Offset 220  Extended Supported display device 7 */
+	u32	cpl9;	/* Offset 224  Extended Currently present device 1 */
+	u32	cp10;	/* Offset 228  Extended Currently present device 2 */
+	u32	cp11;	/* Offset 232  Extended Currently present device 3 */
+	u32	cp12;	/* Offset 236  Extended Currently present device 4 */
+	u32	cp13;	/* Offset 240  Extended Currently present device 5 */
+	u32	cp14;	/* Offset 244  Extended Currently present device 6 */
+	u32	cp15;	/* Offset 248  Extended Currently present device 7 */
+	u8	reserved2[4];	/* Offset 252  Reserved 4 bytes */
+};
+
+/* mailbox 2: software sci interface */
+struct __packed opregion_mailbox2 {
+	u32	scic;	/* Offset 0  Software SCI function number parameters */
+	u32	parm;	/* Offset 4  Software SCI function number parameters */
+	u32	dslp;	/* Offset 8  Driver sleep timeout */
+	u8	reserved[244];	/* Offset 12   Reserved */
+};
+
+/* mailbox 3: power conservation */
+struct __packed opregion_mailbox3 {
+	u32	ardy;		/* Offset 0   Driver readiness */
+	u32	aslc;		/* Offset 4   ASLE interrupt command / status */
+	u32	tche;		/* Offset 8   Technology enabled indicator */
+	u32	alsi;		/* Offset 12  Current ALS illuminance reading */
+	u32	bclp;		/* Offset 16  Backlight britness to set */
+	u32	pfit;		/* Offset 20  Panel fitting Request */
+	u32	cblv;		/* Offset 24  Brightness Current State */
+	/* Offset 28  Backlight Brightness Level Duty Cycle Mapping Table */
+	u16	bclm[20];
+	u32	cpfm;		/* Offset 68  Panel Fitting Current Mode */
+	u32	epfm;		/* Offset 72  Enabled Panel Fitting Modes */
+	u8	plut[74];	/* Offset 76  Panel Look Up Table */
+	/* Offset 150 PWM Frequency and Minimum Brightness */
+	u32	pfmb;
+	u32	ccdv;		/* Offset 154 Color Correction Default Values */
+	u32	pcft;		/* Offset 158 Power Conservation Features */
+	u32	srot;		/* Offset 162 Supported Rotation angle */
+	u32	iuer;		/* Offset 166 Intel Ultrabook Event Register */
+	u64	fdsp;		/* Offset 170 FFS Display Physical address */
+	u32	fdss;		/* Offset 178 FFS Display Size */
+	u32	stat;		/* Offset 182 State Indicator */
+	/*
+	 * Offset 186 (Igd opregion offset 0x3BAh)
+	 * Physical address of Raw VBT data
+	 */
+	u64	rvda;
+	/* Offset 194 (Igd opregion offset 0x3C2h) Size of Raw VBT data */
+	u32	rvds;
+	u8	reserved[58];	/* Offset 198 Reserved */
+};
+
+#define IGD_BACKLIGHT_BRIGHTNESS 0xff
+#define IGD_INITIAL_BRIGHTNESS 0x64
+
+#define IGD_FIELD_VALID		BIT(31)
+#define IGD_WORD_FIELD_VALID	BIT(15)
+#define IGD_PFIT_STRETCH 6
+
+/* mailbox 4: vbt */
+struct __packed opregion_vbt {
+	u8 gvd1[6 << 10];
+};
+
+/* Mailbox 5: BIOS to Driver Notification Extension */
+struct __packed opregion_mailbox5 {
+	u32	phed;		/* Offset 7168 Panel Header */
+	u8	bddc[256];	/* Offset 7172 Panel EDID */
+	u8	reserved[764];	/* Offset 7428 764 bytes */
+};
+
+/* IGD OpRegion */
+struct __packed igd_opregion {
+	struct opregion_header header;
+	struct opregion_mailbox1 mailbox1;
+	struct opregion_mailbox2 mailbox2;
+	struct opregion_mailbox3 mailbox3;
+	struct opregion_vbt vbt;
+	struct opregion_mailbox5 mailbox5;
+};
+
+/* Intel Video BIOS (Option ROM) */
+struct __packed optionrom_header {
+	u16	signature;
+	u8	size;
+	u8	reserved[21];
+	u16	pcir_offset;
+	u16	vbt_offset;
+};
+
+#define OPROM_SIGNATURE 0xaa55
+
+struct __packed optionrom_pcir {
+	u32	signature;
+	u16	vendor;
+	u16	device;
+	u16	reserved1;
+	u16	length;
+	u8	revision;
+	u8	classcode[3];
+	u16	imagelength;
+	u16	coderevision;
+	u8	codetype;
+	u8	indicator;
+	u16	reserved2;
+};
+
+struct __packed optionrom_vbt {
+	u8	hdr_signature[20];
+	u16	hdr_version;
+	u16	hdr_size;
+	u16	hdr_vbt_size;
+	u8	hdr_vbt_checksum;
+	u8	hdr_reserved;
+	u32	hdr_vbt_datablock;
+	u32	hdr_aim[4];
+	u8	datahdr_signature[16];
+	u16	datahdr_version;
+	u16	datahdr_size;
+	u16	datahdr_datablocksize;
+	u8	coreblock_id;
+	u16	coreblock_size;
+	u16	coreblock_biossize;
+	u8	coreblock_biostype;
+	u8	coreblock_releasestatus;
+	u8	coreblock_hwsupported;
+	u8	coreblock_integratedhw;
+	u8	coreblock_biosbuild[4];
+	u8	coreblock_biossignon[155];
+};
+
+/**
+ * intel_gma_init_igd_opregion() - Initialise IGD OpRegion
+ *
+ * This is called from ACPI code and OS drivers
+ *
+ * @return 0 if OK, -ve on error
+ */
+int intel_gma_init_igd_opregion(struct udevice *dev,
+				struct igd_opregion *opregion);
+
+#endif /* _ASM_INTEL_OPREGION_H_ */

+ 12 - 3
arch/x86/include/asm/mtrr.h

@@ -36,8 +36,8 @@
 
 #define MTRR_BASE_TYPE_MASK	0x7
 
-/* Number of MTRRs supported */
-#define MTRR_COUNT		8
+/* Maximum number of MTRRs supported - see also mtrr_get_var_count() */
+#define MTRR_MAX_COUNT		10
 
 #define NUM_FIXED_MTRRS		11
 #define RANGES_PER_FIXED_MTRR	8
@@ -87,7 +87,7 @@ struct mtrr {
  * @mtrr: Information about each mtrr
  */
 struct mtrr_info {
-	struct mtrr mtrr[MTRR_COUNT];
+	struct mtrr mtrr[MTRR_MAX_COUNT];
 };
 
 /**
@@ -180,6 +180,15 @@ int mtrr_set_valid(int cpu_select, int reg, bool valid);
  */
 int mtrr_set(int cpu_select, int reg, u64 base, u64 mask);
 
+/**
+ * mtrr_get_var_count() - Get the number of variable MTRRs
+ *
+ * Some CPUs have more than 8 MTRRs. This function returns the actual number
+ *
+ * @return number of variable MTRRs
+ */
+int mtrr_get_var_count(void);
+
 #endif
 
 #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0)

+ 27 - 0
arch/x86/include/asm/smm.h

@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * SMM definitions (U-Boot does not support SMM itself)
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright 2019 Google LLC
+ *
+ * Modified from coreboot smm.h
+ */
+
+#ifndef _ASM_SMM_H
+#define _ASM_SMM_H
+
+#define APM_CNT			0xb2
+#define APM_CNT_CST_CONTROL	0x85
+#define APM_CNT_PST_CONTROL	0x80
+#define APM_CNT_ACPI_DISABLE	0x1e
+#define APM_CNT_ACPI_ENABLE	0xe1
+#define APM_CNT_MBI_UPDATE	0xeb
+#define APM_CNT_GNVS_UPDATE	0xea
+#define APM_CNT_FINALIZE	0xcb
+#define APM_CNT_LEGACY		0xcc
+#define APM_CNT_SMMSTORE	0xed
+#define APM_CNT_ELOG_GSMI	0xef
+#define APM_STS			0xb3
+
+#endif /* _ASM_SMM_H */

+ 29 - 1
arch/x86/include/asm/zimage.h

@@ -30,10 +30,38 @@
 #define BZIMAGE_LOAD_ADDR  0x100000
 #define ZIMAGE_LOAD_ADDR   0x10000
 
+/**
+ * load_zimage() - Load a zImage or bzImage
+ *
+ * This copies an image into the standard location ready for setup
+ *
+ * @image: Address of image to load
+ * @kernel_size: Size of kernel including setup block (or 0 if the kernel is
+ *	new enough to have a 'syssize' value)
+ * @load_addressp: Returns the address where the kernel has been loaded
+ * @return address of setup block, or NULL if something went wrong
+ */
 struct boot_params *load_zimage(char *image, unsigned long kernel_size,
 				ulong *load_addressp);
+
+/**
+ * setup_zimage() - Set up a loaded zImage or bzImage ready for booting
+ *
+ * @setup_base: Pointer to the boot parameters, typically at address
+ *	DEFAULT_SETUP_BASE
+ * @cmd_line: Place to put the command line, or NULL to use the one in the setup
+ *	block
+ * @initrd_addr: Address of the initial ramdisk, or 0 if none
+ * @initrd_size: Size of the initial ramdisk, or 0 if none
+ * @load_address: Address where the bzImage is moved before booting, either
+ *	BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR
+ * @cmdline_force: Address of 'override' command line, or 0 to use the one in
+ *	the *	setup block
+ * @return 0 (always)
+ */
 int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
-		 unsigned long initrd_addr, unsigned long initrd_size);
+		 ulong initrd_addr, ulong initrd_size, ulong cmdline_force);
+
 void setup_video(struct screen_info *screen_info);
 void setup_efi_info(struct efi_info *efi_info);
 

+ 1 - 0
arch/x86/lib/Makefile

@@ -38,6 +38,7 @@ obj-y += sfi.o
 obj-y	+= acpi.o
 obj-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.o
 ifndef CONFIG_QEMU
+obj-y += acpigen.o
 obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
 endif
 obj-y	+= tables.o

+ 368 - 15
arch/x86/lib/acpi_table.c

@@ -6,7 +6,10 @@
  * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
  */
 
+#define LOG_CATEGORY LOGC_ACPI
+
 #include <common.h>
+#include <bloblist.h>
 #include <cpu.h>
 #include <dm.h>
 #include <log.h>
@@ -15,6 +18,7 @@
 #include <serial.h>
 #include <version.h>
 #include <acpi/acpigen.h>
+#include <acpi/acpi_device.h>
 #include <acpi/acpi_table.h>
 #include <asm/acpi/global_nvs.h>
 #include <asm/ioapic.h>
@@ -65,14 +69,17 @@ int acpi_create_madt_lapics(u32 current)
 {
 	struct udevice *dev;
 	int total_length = 0;
+	int cpu_num = 0;
 
 	for (uclass_find_first_device(UCLASS_CPU, &dev);
 	     dev;
 	     uclass_find_next_device(&dev)) {
 		struct cpu_platdata *plat = dev_get_parent_platdata(dev);
-		int length = acpi_create_madt_lapic(
-				(struct acpi_madt_lapic *)current,
-				plat->cpu_id, plat->cpu_id);
+		int length;
+
+		length = acpi_create_madt_lapic(
+			(struct acpi_madt_lapic *)current, cpu_num++,
+			plat->cpu_id);
 		current += length;
 		total_length += length;
 	}
@@ -210,6 +217,105 @@ static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
 	header->checksum = table_compute_checksum((void *)mcfg, header->length);
 }
 
+/**
+ * acpi_create_tcpa() - Create a TCPA table
+ *
+ * @tcpa: Pointer to place to put table
+ *
+ * Trusted Computing Platform Alliance Capabilities Table
+ * TCPA PC Specific Implementation SpecificationTCPA is defined in the PCI
+ * Firmware Specification 3.0
+ */
+static int acpi_create_tcpa(struct acpi_tcpa *tcpa)
+{
+	struct acpi_table_header *header = &tcpa->header;
+	u32 current = (u32)tcpa + sizeof(struct acpi_tcpa);
+	int size = 0x10000;	/* Use this as the default size */
+	void *log;
+	int ret;
+
+	if (!CONFIG_IS_ENABLED(BLOBLIST))
+		return -ENXIO;
+	memset(tcpa, '\0', sizeof(struct acpi_tcpa));
+
+	/* Fill out header fields */
+	acpi_fill_header(header, "TCPA");
+	header->length = sizeof(struct acpi_tcpa);
+	header->revision = 1;
+
+	ret = bloblist_ensure_size_ret(BLOBLISTT_TCPA_LOG, &size, &log);
+	if (ret)
+		return log_msg_ret("blob", ret);
+
+	tcpa->platform_class = 0;
+	tcpa->laml = size;
+	tcpa->lasa = (ulong)log;
+
+	/* (Re)calculate length and checksum */
+	header->length = current - (u32)tcpa;
+	header->checksum = table_compute_checksum((void *)tcpa, header->length);
+
+	return 0;
+}
+
+static int get_tpm2_log(void **ptrp, int *sizep)
+{
+	const int tpm2_default_log_len = 0x10000;
+	int size;
+	int ret;
+
+	*sizep = 0;
+	size = tpm2_default_log_len;
+	ret = bloblist_ensure_size_ret(BLOBLISTT_TPM2_TCG_LOG, &size, ptrp);
+	if (ret)
+		return log_msg_ret("blob", ret);
+	*sizep = size;
+
+	return 0;
+}
+
+static int acpi_create_tpm2(struct acpi_tpm2 *tpm2)
+{
+	struct acpi_table_header *header = &tpm2->header;
+	int tpm2_log_len;
+	void *lasa;
+	int ret;
+
+	memset((void *)tpm2, 0, sizeof(struct acpi_tpm2));
+
+	/*
+	 * Some payloads like SeaBIOS depend on log area to use TPM2.
+	 * Get the memory size and address of TPM2 log area or initialize it.
+	 */
+	ret = get_tpm2_log(&lasa, &tpm2_log_len);
+	if (ret)
+		return ret;
+
+	/* Fill out header fields. */
+	acpi_fill_header(header, "TPM2");
+	memcpy(header->aslc_id, ASLC_ID, 4);
+
+	header->length = sizeof(struct acpi_tpm2);
+	header->revision = acpi_get_table_revision(ACPITAB_TPM2);
+
+	/* Hard to detect for coreboot. Just set it to 0 */
+	tpm2->platform_class = 0;
+
+	/* Must be set to 0 for FIFO-interface support */
+	tpm2->control_area = 0;
+	tpm2->start_method = 6;
+	memset(tpm2->msp, 0, sizeof(tpm2->msp));
+
+	/* Fill the log area size and start address fields. */
+	tpm2->laml = tpm2_log_len;
+	tpm2->lasa = (uintptr_t)lasa;
+
+	/* Calculate checksum. */
+	header->checksum = table_compute_checksum((void *)tpm2, header->length);
+
+	return 0;
+}
+
 __weak u32 acpi_fill_csrt(u32 current)
 {
 	return 0;
@@ -394,11 +500,13 @@ ulong write_acpi_tables(ulong start_addr)
 	struct acpi_fadt *fadt;
 	struct acpi_table_header *ssdt;
 	struct acpi_mcfg *mcfg;
+	struct acpi_tcpa *tcpa;
 	struct acpi_madt *madt;
 	struct acpi_csrt *csrt;
 	struct acpi_spcr *spcr;
 	void *start;
 	ulong addr;
+	int ret;
 	int i;
 
 	start = map_sysmem(start_addr, 0);
@@ -430,17 +538,31 @@ ulong write_acpi_tables(ulong start_addr)
 	       dsdt->length - sizeof(struct acpi_table_header));
 
 	acpi_inc(ctx, dsdt->length - sizeof(struct acpi_table_header));
+	dsdt->length = ctx->current - (void *)dsdt;
+	acpi_align(ctx);
 
-	/* Pack GNVS into the ACPI table area */
-	for (i = 0; i < dsdt->length; i++) {
-		u32 *gnvs = (u32 *)((u32)dsdt + i);
-		if (*gnvs == ACPI_GNVS_ADDR) {
-			ulong addr = (ulong)map_to_sysmem(ctx->current);
-
-			debug("Fix up global NVS in DSDT to %#08lx\n", addr);
-			*gnvs = addr;
-			break;
+	if (!IS_ENABLED(CONFIG_ACPI_GNVS_EXTERNAL)) {
+		/* Pack GNVS into the ACPI table area */
+		for (i = 0; i < dsdt->length; i++) {
+			u32 *gnvs = (u32 *)((u32)dsdt + i);
+
+			if (*gnvs == ACPI_GNVS_ADDR) {
+				*gnvs = map_to_sysmem(ctx->current);
+				debug("Fix up global NVS in DSDT to %#08x\n",
+				      *gnvs);
+				break;
+			}
 		}
+
+		/*
+		 * Fill in platform-specific global NVS variables. If this fails
+		 * we cannot return the error but this should only happen while
+		 * debugging.
+		 */
+		addr = acpi_create_gnvs(ctx->current);
+		if (IS_ERR_VALUE(addr))
+			printf("Error: Gailed to create GNVS\n");
+		acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
 	}
 
 	/*
@@ -448,12 +570,9 @@ ulong write_acpi_tables(ulong start_addr)
 	 * the GNVS address. Set the checksum to zero since it is part of the
 	 * region being checksummed.
 	 */
-	dsdt->length = ctx->current - (void *)dsdt;
 	dsdt->checksum = 0;
 	dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
 
-	acpi_align(ctx);
-
 	/*
 	 * Fill in platform-specific global NVS variables. If this fails we
 	 * cannot return the error but this should only happen while debugging.
@@ -484,12 +603,36 @@ ulong write_acpi_tables(ulong start_addr)
 	acpi_inc_align(ctx, mcfg->header.length);
 	acpi_add_table(ctx, mcfg);
 
+	if (IS_ENABLED(CONFIG_TPM_V2)) {
+		struct acpi_tpm2 *tpm2;
+
+		debug("ACPI:    * TPM2\n");
+		tpm2 = (struct acpi_tpm2 *)ctx->current;
+		ret = acpi_create_tpm2(tpm2);
+		if (!ret) {
+			acpi_inc_align(ctx, tpm2->header.length);
+			acpi_add_table(ctx, tpm2);
+		} else {
+			log_warning("TPM2 table creation failed\n");
+		}
+	}
+
 	debug("ACPI:    * MADT\n");
 	madt = ctx->current;
 	acpi_create_madt(madt);
 	acpi_inc_align(ctx, madt->header.length);
 	acpi_add_table(ctx, madt);
 
+	debug("ACPI:    * TCPA\n");
+	tcpa = (struct acpi_tcpa *)ctx->current;
+	ret = acpi_create_tcpa(tcpa);
+	if (ret) {
+		log_warning("Failed to create TCPA table (err=%d)\n", ret);
+	} else {
+		acpi_inc_align(ctx, tcpa->header.length);
+		acpi_add_table(ctx, tcpa);
+	}
+
 	debug("ACPI:    * CSRT\n");
 	csrt = ctx->current;
 	if (!acpi_create_csrt(csrt)) {
@@ -518,3 +661,213 @@ ulong acpi_get_rsdp_addr(void)
 {
 	return acpi_rsdp_addr;
 }
+
+/**
+ * acpi_write_hpet() - Write out a HPET table
+ *
+ * Write out the table for High-Precision Event Timers
+ *
+ * @hpet: Place to put HPET table
+ */
+static int acpi_create_hpet(struct acpi_hpet *hpet)
+{
+	struct acpi_table_header *header = &hpet->header;
+	struct acpi_gen_regaddr *addr = &hpet->addr;
+
+	/*
+	 * See IA-PC HPET (High Precision Event Timers) Specification v1.0a
+	 * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf
+	 */
+	memset((void *)hpet, '\0', sizeof(struct acpi_hpet));
+
+	/* Fill out header fields. */
+	acpi_fill_header(header, "HPET");
+
+	header->aslc_revision = ASL_REVISION;
+	header->length = sizeof(struct acpi_hpet);
+	header->revision = acpi_get_table_revision(ACPITAB_HPET);
+
+	/* Fill out HPET address */
+	addr->space_id = 0;  /* Memory */
+	addr->bit_width = 64;
+	addr->bit_offset = 0;
+	addr->addrl = CONFIG_HPET_ADDRESS & 0xffffffff;
+	addr->addrh = ((unsigned long long)CONFIG_HPET_ADDRESS) >> 32;
+
+	hpet->id = *(u32 *)CONFIG_HPET_ADDRESS;
+	hpet->number = 0;
+	hpet->min_tick = 0; /* HPET_MIN_TICKS */
+
+	header->checksum = table_compute_checksum(hpet,
+						  sizeof(struct acpi_hpet));
+
+	return 0;
+}
+
+int acpi_write_hpet(struct acpi_ctx *ctx)
+{
+	struct acpi_hpet *hpet;
+	int ret;
+
+	log_debug("ACPI:    * HPET\n");
+
+	hpet = ctx->current;
+	acpi_inc_align(ctx, sizeof(struct acpi_hpet));
+	acpi_create_hpet(hpet);
+	ret = acpi_add_table(ctx, hpet);
+	if (ret)
+		return log_msg_ret("add", ret);
+
+	return 0;
+}
+
+int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
+			     uint access_size)
+{
+	struct acpi_dbg2_header *dbg2 = ctx->current;
+	char path[ACPI_PATH_MAX];
+	struct acpi_gen_regaddr address;
+	phys_addr_t addr;
+	int ret;
+
+	if (!device_active(dev)) {
+		log_info("Device not enabled\n");
+		return -EACCES;
+	}
+	/*
+	 * PCI devices don't remember their resource allocation information in
+	 * U-Boot at present. We assume that MMIO is used for the UART and that
+	 * the address space is 32 bytes: ns16550 uses 8 registers of up to
+	 * 32-bits each. This is only for debugging so it is not a big deal.
+	 */
+	addr = dm_pci_read_bar32(dev, 0);
+	printf("UART addr %lx\n", (ulong)addr);
+
+	memset(&address, '\0', sizeof(address));
+	address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
+	address.addrl = (uint32_t)addr;
+	address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
+	address.access_size = access_size;
+
+	ret = acpi_device_path(dev, path, sizeof(path));
+	if (ret)
+		return log_msg_ret("path", ret);
+	acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
+			 ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
+
+	acpi_inc_align(ctx, dbg2->header.length);
+	acpi_add_table(ctx, dbg2);
+
+	return 0;
+}
+
+void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
+		      void *dsdt)
+{
+	struct acpi_table_header *header = &fadt->header;
+
+	memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
+
+	acpi_fill_header(header, "FACP");
+	header->length = sizeof(struct acpi_fadt);
+	header->revision = 4;
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
+	memcpy(header->aslc_id, ASLC_ID, 4);
+	header->aslc_revision = 1;
+
+	fadt->firmware_ctrl = (unsigned long)facs;
+	fadt->dsdt = (unsigned long)dsdt;
+
+	fadt->x_firmware_ctl_l = (unsigned long)facs;
+	fadt->x_firmware_ctl_h = 0;
+	fadt->x_dsdt_l = (unsigned long)dsdt;
+	fadt->x_dsdt_h = 0;
+
+	fadt->preferred_pm_profile = ACPI_PM_MOBILE;
+
+	/* Use ACPI 3.0 revision */
+	fadt->header.revision = 4;
+}
+
+void acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
+			   u64 bar)
+{
+	struct dmar_entry *drhd = ctx->current;
+
+	memset(drhd, '\0', sizeof(*drhd));
+	drhd->type = DMAR_DRHD;
+	drhd->length = sizeof(*drhd); /* will be fixed up later */
+	drhd->flags = flags;
+	drhd->segment = segment;
+	drhd->bar = bar;
+	acpi_inc(ctx, drhd->length);
+}
+
+void acpi_create_dmar_rmrr(struct acpi_ctx *ctx, uint segment, u64 bar,
+			   u64 limit)
+{
+	struct dmar_rmrr_entry *rmrr = ctx->current;
+
+	memset(rmrr, '\0', sizeof(*rmrr));
+	rmrr->type = DMAR_RMRR;
+	rmrr->length = sizeof(*rmrr); /* will be fixed up later */
+	rmrr->segment = segment;
+	rmrr->bar = bar;
+	rmrr->limit = limit;
+	acpi_inc(ctx, rmrr->length);
+}
+
+void acpi_dmar_drhd_fixup(struct acpi_ctx *ctx, void *base)
+{
+	struct dmar_entry *drhd = base;
+
+	drhd->length = ctx->current - base;
+}
+
+void acpi_dmar_rmrr_fixup(struct acpi_ctx *ctx, void *base)
+{
+	struct dmar_rmrr_entry *rmrr = base;
+
+	rmrr->length = ctx->current - base;
+}
+
+static int acpi_create_dmar_ds(struct acpi_ctx *ctx, enum dev_scope_type type,
+			       uint enumeration_id, pci_dev_t bdf)
+{
+	/* we don't support longer paths yet */
+	const size_t dev_scope_length = sizeof(struct dev_scope) + 2;
+	struct dev_scope *ds = ctx->current;
+
+	memset(ds, '\0', dev_scope_length);
+	ds->type = type;
+	ds->length = dev_scope_length;
+	ds->enumeration = enumeration_id;
+	ds->start_bus = PCI_BUS(bdf);
+	ds->path[0].dev = PCI_DEV(bdf);
+	ds->path[0].fn = PCI_FUNC(bdf);
+
+	return ds->length;
+}
+
+int acpi_create_dmar_ds_pci_br(struct acpi_ctx *ctx, pci_dev_t bdf)
+{
+	return acpi_create_dmar_ds(ctx, SCOPE_PCI_SUB, 0, bdf);
+}
+
+int acpi_create_dmar_ds_pci(struct acpi_ctx *ctx, pci_dev_t bdf)
+{
+	return acpi_create_dmar_ds(ctx, SCOPE_PCI_ENDPOINT, 0, bdf);
+}
+
+int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
+			       pci_dev_t bdf)
+{
+	return acpi_create_dmar_ds(ctx, SCOPE_IOAPIC, enumeration_id, bdf);
+}
+
+int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
+				 pci_dev_t bdf)
+{
+	return acpi_create_dmar_ds(ctx, SCOPE_MSI_HPET, enumeration_id, bdf);
+}

+ 96 - 0
arch/x86/lib/acpigen.c

@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Google LLC
+ */
+
+#include <common.h>
+#include <acpi/acpigen.h>
+#include <acpi/acpi_table.h>
+#include <asm/acpigen.h>
+
+void acpigen_write_empty_pct(struct acpi_ctx *ctx)
+{
+	/*
+	 * Name (_PCT, Package (0x02)
+	 * {
+	 *	ResourceTemplate ()
+	 *	{
+	 *		Register (FFixedHW,
+	 *			0x00,               // Bit Width
+	 *			0x00,               // Bit Offset
+	 *			0x0000000000000000, // Address
+	 *			,)
+	 *	},
+	 *
+	 *	ResourceTemplate ()
+	 *	{
+	 *		Register (FFixedHW,
+	 *			0x00,               // Bit Width
+	 *			0x00,               // Bit Offset
+	 *			0x0000000000000000, // Address
+	 *			,)
+	 *	}
+	 * })
+	 */
+	static char stream[] = {
+		/* 00000030    "0._PCT.," */
+		0x08, 0x5f, 0x50, 0x43, 0x54, 0x12, 0x2c,
+		/* 00000038    "........" */
+		0x02, 0x11, 0x14, 0x0a, 0x11, 0x82, 0x0c, 0x00,
+		/* 00000040    "........" */
+		0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		/* 00000048    "....y..." */
+		0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14,
+		/* 00000050    "........" */
+		0x0a, 0x11, 0x82, 0x0c, 0x00, 0x7f, 0x00, 0x00,
+		/* 00000058    "........" */
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x79, 0x00
+	};
+	acpigen_emit_stream(ctx, stream, ARRAY_SIZE(stream));
+}
+
+void acpigen_write_empty_ptc(struct acpi_ctx *ctx)
+{
+	/*
+	 * Name (_PTC, Package (0x02)
+	 * {
+	 *	ResourceTemplate ()
+	 *	{
+	 *		Register (FFixedHW,
+	 *			0x00,               // Bit Width
+	 *			0x00,               // Bit Offset
+	 *			0x0000000000000000, // Address
+	 *			,)
+	 *	},
+	 *
+	 *	ResourceTemplate ()
+	 *	{
+	 *		Register (FFixedHW,
+	 *			0x00,               // Bit Width
+	 *			0x00,               // Bit Offset
+	 *			0x0000000000000000, // Address
+	 *			,)
+	 *	}
+	 * })
+	 */
+	struct acpi_gen_regaddr addr = {
+		.space_id    = ACPI_ADDRESS_SPACE_FIXED,
+		.bit_width   = 0,
+		.bit_offset  = 0,
+		.access_size = 0,
+		.addrl       = 0,
+		.addrh       = 0,
+	};
+
+	acpigen_write_name(ctx, "_PTC");
+	acpigen_write_package(ctx, 2);
+
+	/* ControlRegister */
+	acpigen_write_register_resource(ctx, &addr);
+
+	/* StatusRegister */
+	acpigen_write_register_resource(ctx, &addr);
+
+	acpigen_pop_len(ctx);
+}

+ 1 - 1
arch/x86/lib/bootm.c

@@ -136,7 +136,7 @@ static int boot_prep_linux(bootm_headers_t *images)
 	printf("Setup at %#08lx\n", images->ep);
 	ret = setup_zimage((void *)images->ep, cmd_line_dest,
 			0, images->rd_start,
-			images->rd_end - images->rd_start);
+			images->rd_end - images->rd_start, 0);
 
 	if (ret) {
 		printf("## Setting up boot parameters failed ...\n");

+ 16 - 0
arch/x86/lib/fsp/fsp_common.c

@@ -60,6 +60,22 @@ void board_final_init(void)
 		debug("OK\n");
 }
 
+void board_final_cleanup(void)
+{
+	u32 status;
+
+	/* TODO(sjg@chromium.org): This causes Linux to crash */
+	return;
+
+	/* call into FspNotify */
+	debug("Calling into FSP (notify phase INIT_PHASE_END_FIRMWARE): ");
+	status = fsp_notify(NULL, INIT_PHASE_END_FIRMWARE);
+	if (status)
+		debug("fail, error code %x\n", status);
+	else
+		debug("OK\n");
+}
+
 int fsp_save_s3_stack(void)
 {
 	struct udevice *dev;

+ 17 - 0
arch/x86/lib/fsp/fsp_dram.c

@@ -12,6 +12,7 @@
 #include <asm/mrccache.h>
 #include <asm/mtrr.h>
 #include <asm/post.h>
+#include <dm/ofnode.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -92,6 +93,8 @@ unsigned int install_e820_map(unsigned int max_entries,
 	unsigned int num_entries = 0;
 	const struct hob_header *hdr;
 	struct hob_res_desc *res_desc;
+	const fdt64_t *prop;
+	int size;
 
 	hdr = gd->arch.hob_list;
 
@@ -133,6 +136,20 @@ unsigned int install_e820_map(unsigned int max_entries,
 		num_entries++;
 	}
 
+	prop = ofnode_read_chosen_prop("e820-entries", &size);
+	if (prop) {
+		int count = size / (sizeof(u64) * 3);
+		int i;
+
+		if (num_entries + count >= max_entries)
+			return -ENOSPC;
+		for (i = 0; i < count; i++, num_entries++, prop += 3) {
+			entries[num_entries].addr = fdt64_to_cpu(prop[0]);
+			entries[num_entries].size = fdt64_to_cpu(prop[1]);
+			entries[num_entries].type = fdt64_to_cpu(prop[2]);
+		}
+	}
+
 	return num_entries;
 }
 

+ 32 - 0
arch/x86/lib/fsp/fsp_graphics.c

@@ -3,14 +3,19 @@
  * Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
  */
 
+#define LOG_CATEGORY UCLASS_VIDEO
+
 #include <common.h>
 #include <dm.h>
 #include <init.h>
 #include <log.h>
 #include <vbe.h>
 #include <video.h>
+#include <acpi/acpi_table.h>
 #include <asm/fsp/fsp_support.h>
+#include <asm/intel_opregion.h>
 #include <asm/mtrr.h>
+#include <dm/acpi.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -127,6 +132,32 @@ static int fsp_video_bind(struct udevice *dev)
 	return 0;
 }
 
+#ifdef CONFIG_INTEL_GMA_ACPI
+static int fsp_video_acpi_write_tables(const struct udevice *dev,
+				       struct acpi_ctx *ctx)
+{
+	struct igd_opregion *opregion;
+	int ret;
+
+	printf("ACPI:    * IGD OpRegion\n");
+	opregion = (struct igd_opregion *)ctx->current;
+
+	ret = intel_gma_init_igd_opregion((struct udevice *)dev, opregion);
+	if (ret)
+		return ret;
+
+	acpi_inc_align(ctx, sizeof(struct igd_opregion));
+
+	return 0;
+}
+#endif
+
+struct acpi_ops fsp_video_acpi_ops = {
+#ifdef CONFIG_INTEL_GMA_ACPI
+	.write_tables	= fsp_video_acpi_write_tables,
+#endif
+};
+
 static const struct udevice_id fsp_video_ids[] = {
 	{ .compatible = "fsp-fb" },
 	{ }
@@ -139,6 +170,7 @@ U_BOOT_DRIVER(fsp_video) = {
 	.bind	= fsp_video_bind,
 	.probe	= fsp_video_probe,
 	.flags	= DM_FLAG_PRE_RELOC,
+	ACPI_OPS_PTR(&fsp_video_acpi_ops)
 };
 
 static struct pci_device_id fsp_video_supported[] = {

+ 3 - 1
arch/x86/lib/fsp2/fsp_silicon_init.c

@@ -26,8 +26,10 @@ int fsp_silicon_init(bool s3wake, bool use_spi_flash)
 	struct binman_entry entry;
 	struct udevice *dev;
 	ulong rom_offset = 0;
+	u32 init_addr;
 	int ret;
 
+	log_debug("Locating FSP\n");
 	ret = fsp_locate_fsp(FSP_S, &entry, use_spi_flash, &dev, &hdr,
 			     &rom_offset);
 	if (ret)
@@ -44,7 +46,7 @@ int fsp_silicon_init(bool s3wake, bool use_spi_flash)
 	ret = fsps_update_config(dev, rom_offset, &upd);
 	if (ret)
 		return log_msg_ret("Could not setup config", ret);
-	log_debug("Silicon init...");
+	log_debug("Silicon init @ %x...", init_addr);
 	bootstage_start(BOOTSTAGE_ID_ACCUM_FSP_S, "fsp-s");
 	func = (fsp_silicon_init_func)(hdr->img_base + hdr->fsp_silicon_init);
 	ret = func(&upd);

+ 14 - 8
arch/x86/lib/fsp2/fsp_support.c

@@ -35,7 +35,8 @@ int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
 	 *
 	 * You are in a maze of twisty little headers all alike.
 	 */
-	debug("offset=%x buf=%x\n", (uint)offset, (uint)buf);
+	log_debug("offset=%x buf=%x, use_spi_flash=%d\n", (uint)offset,
+		  (uint)buf, use_spi_flash);
 	if (use_spi_flash) {
 		ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
 		if (ret)
@@ -52,16 +53,16 @@ int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
 	fv = ptr;
 
 	/* Check the FV signature, _FVH */
-	debug("offset=%x sign=%x\n", (uint)offset, (uint)fv->sign);
+	log_debug("offset=%x sign=%x\n", (uint)offset, (uint)fv->sign);
 	if (fv->sign != EFI_FVH_SIGNATURE)
 		return log_msg_ret("Base FV signature", -EINVAL);
 
 	/* Go to the end of the FV header and align the address */
-	debug("fv->ext_hdr_off = %x\n", fv->ext_hdr_off);
+	log_debug("fv->ext_hdr_off = %x\n", fv->ext_hdr_off);
 	ptr += fv->ext_hdr_off;
 	exhdr = ptr;
 	ptr += ALIGN(exhdr->ext_hdr_size, 8);
-	debug("ptr=%x\n", ptr - (void *)buf);
+	log_debug("ptr=%x\n", ptr - (void *)buf);
 
 	/* Check the FFS GUID */
 	file_hdr = ptr;
@@ -71,7 +72,7 @@ int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
 	ptr = file_hdr + 1;
 
 	raw = ptr;
-	debug("raw->type = %x\n", raw->type);
+	log_debug("raw->type = %x\n", raw->type);
 	if (raw->type != EFI_SECTION_RAW)
 		return log_msg_ret("Section type not RAW", -ENOEXEC);
 
@@ -80,13 +81,18 @@ int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
 	fsp = ptr;
 
 	/* Check the FSPH header */
-	debug("fsp %x\n", (uint)fsp);
+	log_debug("fsp %x, fsp-buf=%x, si=%x\n", (uint)fsp, ptr - (void *)buf,
+		  (void *)&fsp->fsp_silicon_init - (void *)buf);
 	if (fsp->sign != EFI_FSPH_SIGNATURE)
 		return log_msg_ret("Base FSPH signature", -EACCES);
 
 	base = (void *)fsp->img_base;
-	debug("Image base %x\n", (uint)base);
-	debug("Image addr %x\n", (uint)fsp->fsp_mem_init);
+	log_debug("image base %x\n", (uint)base);
+	if (fsp->fsp_mem_init)
+		log_debug("mem_init offset %x\n", (uint)fsp->fsp_mem_init);
+	else if (fsp->fsp_silicon_init)
+		log_debug("silicon_init offset %x\n",
+			  (uint)fsp->fsp_silicon_init);
 	if (use_spi_flash) {
 		ret = spi_flash_read_dm(dev, offset, size, base);
 		if (ret)

+ 429 - 55
arch/x86/lib/zimage.c

@@ -45,6 +45,42 @@
 
 #define COMMAND_LINE_SIZE	2048
 
+/**
+ * struct zboot_state - Current state of the boot
+ *
+ * @bzimage_addr: Address of the bzImage to boot
+ * @bzimage_size: Size of the bzImage, or 0 to detect this
+ * @initrd_addr: Address of the initial ramdisk, or 0 if none
+ * @initrd_size: Size of the initial ramdisk, or 0 if none
+ * @load_address: Address where the bzImage is moved before booting, either
+ *	BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR
+ * @base_ptr: Pointer to the boot parameters, typically at address
+ *	DEFAULT_SETUP_BASE
+ * @cmdline: Address of 'override' command line, or 0 to use the one in the
+ *	setup block
+ */
+struct zboot_state {
+	ulong bzimage_addr;
+	ulong bzimage_size;
+	ulong initrd_addr;
+	ulong initrd_size;
+	ulong load_address;
+	struct boot_params *base_ptr;
+	ulong cmdline;
+} state;
+
+enum {
+	ZBOOT_STATE_START	= BIT(0),
+	ZBOOT_STATE_LOAD	= BIT(1),
+	ZBOOT_STATE_SETUP	= BIT(2),
+	ZBOOT_STATE_INFO	= BIT(3),
+	ZBOOT_STATE_GO		= BIT(4),
+
+	/* This one doesn't execute automatically, so stop the count before 5 */
+	ZBOOT_STATE_DUMP	= BIT(5),
+	ZBOOT_STATE_COUNT	= 5,
+};
+
 static void build_command_line(char *command_line, int auto_boot)
 {
 	char *env_command_line;
@@ -85,21 +121,23 @@ static int kernel_magic_ok(struct setup_header *hdr)
 	}
 }
 
-static int get_boot_protocol(struct setup_header *hdr)
+static int get_boot_protocol(struct setup_header *hdr, bool verbose)
 {
 	if (hdr->header == KERNEL_V2_MAGIC) {
-		printf("Magic signature found\n");
+		if (verbose)
+			printf("Magic signature found\n");
 		return hdr->version;
 	} else {
 		/* Very old kernel */
-		printf("Magic signature not found\n");
+		if (verbose)
+			printf("Magic signature not found\n");
 		return 0x0100;
 	}
 }
 
 static int setup_device_tree(struct setup_header *hdr, const void *fdt_blob)
 {
-	int bootproto = get_boot_protocol(hdr);
+	int bootproto = get_boot_protocol(hdr, false);
 	struct setup_data *sd;
 	int size;
 
@@ -129,10 +167,24 @@ static int setup_device_tree(struct setup_header *hdr, const void *fdt_blob)
 	return 0;
 }
 
+static const char *get_kernel_version(struct boot_params *params,
+				      void *kernel_base)
+{
+	struct setup_header *hdr = &params->hdr;
+	int bootproto;
+
+	bootproto = get_boot_protocol(hdr, false);
+	if (bootproto < 0x0200 || hdr->setup_sects < 15)
+		return NULL;
+
+	return kernel_base + hdr->kernel_version + 0x200;
+}
+
 struct boot_params *load_zimage(char *image, unsigned long kernel_size,
 				ulong *load_addressp)
 {
 	struct boot_params *setup_base;
+	const char *version;
 	int setup_size;
 	int bootproto;
 	int big_image;
@@ -160,21 +212,16 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
 		printf("Error: Setup is too large (%d bytes)\n", setup_size);
 
 	/* determine boot protocol version */
-	bootproto = get_boot_protocol(hdr);
+	bootproto = get_boot_protocol(hdr, true);
 
 	printf("Using boot protocol version %x.%02x\n",
 	       (bootproto & 0xff00) >> 8, bootproto & 0xff);
 
-	if (bootproto >= 0x0200) {
-		if (hdr->setup_sects >= 15) {
-			printf("Linux kernel version %s\n",
-				(char *)params +
-				hdr->kernel_version + 0x200);
-		} else {
-			printf("Setup Sectors < 15 - "
-				"Cannot print kernel version.\n");
-		}
-	}
+	version = get_kernel_version(params, image);
+	if (version)
+		printf("Linux kernel version %s\n", version);
+	else
+		printf("Setup Sectors < 15 - Cannot print kernel version\n");
 
 	/* Determine image type */
 	big_image = (bootproto >= 0x0200) &&
@@ -240,10 +287,10 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
 }
 
 int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
-		 unsigned long initrd_addr, unsigned long initrd_size)
+		 ulong initrd_addr, ulong initrd_size, ulong cmdline_force)
 {
 	struct setup_header *hdr = &setup_base->hdr;
-	int bootproto = get_boot_protocol(hdr);
+	int bootproto = get_boot_protocol(hdr, false);
 
 	setup_base->e820_entries = install_e820_map(
 		ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
@@ -253,8 +300,7 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
 		setup_base->screen_info.cl_offset = COMMAND_LINE_OFFSET;
 	}
 	if (bootproto >= 0x0200) {
-		hdr->type_of_loader = 8;
-
+		hdr->type_of_loader = 0x80;	/* U-Boot version 0 */
 		if (initrd_addr) {
 			printf("Initial RAM disk at linear address "
 			       "0x%08lx, size %ld bytes\n",
@@ -282,40 +328,33 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
 		}
 
 		/* build command line at COMMAND_LINE_OFFSET */
-		build_command_line(cmd_line, auto_boot);
+		if (cmdline_force)
+			strcpy(cmd_line, (char *)cmdline_force);
+		else
+			build_command_line(cmd_line, auto_boot);
 	}
 
-#ifdef CONFIG_INTEL_MID
-	if (bootproto >= 0x0207)
+	if (IS_ENABLED(CONFIG_INTEL_MID) && bootproto >= 0x0207)
 		hdr->hardware_subarch = X86_SUBARCH_INTEL_MID;
-#endif
 
-#ifdef CONFIG_GENERATE_ACPI_TABLE
-	setup_base->acpi_rsdp_addr = acpi_get_rsdp_addr();
-#endif
+	if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE))
+		setup_base->acpi_rsdp_addr = acpi_get_rsdp_addr();
 
 	setup_device_tree(hdr, (const void *)env_get_hex("fdtaddr", 0));
 	setup_video(&setup_base->screen_info);
 
-#ifdef CONFIG_EFI_STUB
-	setup_efi_info(&setup_base->efi_info);
-#endif
+	if (IS_ENABLED(CONFIG_EFI_STUB))
+		setup_efi_info(&setup_base->efi_info);
 
 	return 0;
 }
 
-int do_zboot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
 {
-	struct boot_params *base_ptr;
-	void *bzImage_addr = NULL;
-	ulong load_address;
-	char *s;
-	ulong bzImage_size = 0;
-	ulong initrd_addr = 0;
-	ulong initrd_size = 0;
-
-	disable_interrupts();
+	const char *s;
 
+	memset(&state, '\0', sizeof(state));
 	if (argc >= 2) {
 		/* argv[1] holds the address of the bzImage */
 		s = argv[1];
@@ -324,39 +363,361 @@ int do_zboot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	}
 
 	if (s)
-		bzImage_addr = (void *)simple_strtoul(s, NULL, 16);
+		state.bzimage_addr = simple_strtoul(s, NULL, 16);
 
 	if (argc >= 3) {
 		/* argv[2] holds the size of the bzImage */
-		bzImage_size = simple_strtoul(argv[2], NULL, 16);
+		state.bzimage_size = simple_strtoul(argv[2], NULL, 16);
 	}
 
 	if (argc >= 4)
-		initrd_addr = simple_strtoul(argv[3], NULL, 16);
+		state.initrd_addr = simple_strtoul(argv[3], NULL, 16);
 	if (argc >= 5)
-		initrd_size = simple_strtoul(argv[4], NULL, 16);
+		state.initrd_size = simple_strtoul(argv[4], NULL, 16);
+	if (argc >= 6) {
+		/*
+		 * When the base_ptr is passed in, we assume that the image is
+		 * already loaded at the address given by argv[1] and therefore
+		 * the original bzImage is somewhere else, or not accessible.
+		 * In any case, we don't need access to the bzImage since all
+		 * the processing is assumed to be done.
+		 *
+		 * So set the base_ptr to the given address, use this arg as the
+		 * load address and set bzimage_addr to 0 so we know that it
+		 * cannot be proceesed (or processed again).
+		 */
+		state.base_ptr = (void *)simple_strtoul(argv[5], NULL, 16);
+		state.load_address = state.bzimage_addr;
+		state.bzimage_addr = 0;
+	}
+	if (argc >= 7)
+		state.cmdline = simple_strtoul(argv[6], NULL, 16);
+
+	return 0;
+}
+
+static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
+			 char *const argv[])
+{
+	struct boot_params *base_ptr;
+
+	if (state.base_ptr) {
+		struct boot_params *from = (struct boot_params *)state.base_ptr;
+
+		base_ptr = (struct boot_params *)DEFAULT_SETUP_BASE;
+		printf("Building boot_params at 0x%8.8lx\n", (ulong)base_ptr);
+		memset(base_ptr, '\0', sizeof(*base_ptr));
+		base_ptr->hdr = from->hdr;
+	} else {
+		base_ptr = load_zimage((void *)state.bzimage_addr, state.bzimage_size,
+				       &state.load_address);
+		if (!base_ptr) {
+			puts("## Kernel loading failed ...\n");
+			return CMD_RET_FAILURE;
+		}
+	}
+	state.base_ptr = base_ptr;
+	if (env_set_hex("zbootbase", (ulong)base_ptr) ||
+	    env_set_hex("zbootaddr", state.load_address))
+		return CMD_RET_FAILURE;
 
-	/* Lets look for */
-	base_ptr = load_zimage(bzImage_addr, bzImage_size, &load_address);
+	return 0;
+}
+
+static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	struct boot_params *base_ptr = state.base_ptr;
+	int ret;
 
 	if (!base_ptr) {
-		puts("## Kernel loading failed ...\n");
-		return -1;
+		printf("base is not set: use 'zboot load' first\n");
+		return CMD_RET_FAILURE;
 	}
-	if (setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET,
-			0, initrd_addr, initrd_size)) {
+	ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET,
+			   0, state.initrd_addr, state.initrd_size,
+			   state.cmdline);
+	if (ret) {
 		puts("Setting up boot parameters failed ...\n");
-		return -1;
+		return CMD_RET_FAILURE;
 	}
 
+	return 0;
+}
+
+static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc,
+			 char *const argv[])
+{
+	printf("Kernel loaded at %08lx, setup_base=%p\n",
+	       state.load_address, state.base_ptr);
+
+	return 0;
+}
+
+static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
+		       char *const argv[])
+{
+	int ret;
+
+	disable_interrupts();
+
 	/* we assume that the kernel is in place */
-	return boot_linux_kernel((ulong)base_ptr, load_address, false);
+	ret = boot_linux_kernel((ulong)state.base_ptr, state.load_address,
+				false);
+	printf("Kernel returned! (err=%d)\n", ret);
+
+	return CMD_RET_FAILURE;
+}
+
+static void print_num(const char *name, ulong value)
+{
+	printf("%-20s: %lx\n", name, value);
+}
+
+static void print_num64(const char *name, u64 value)
+{
+	printf("%-20s: %llx\n", name, value);
+}
+
+static const char *const e820_type_name[E820_COUNT] = {
+	[E820_RAM] = "RAM",
+	[E820_RESERVED] = "Reserved",
+	[E820_ACPI] = "ACPI",
+	[E820_NVS] = "ACPI NVS",
+	[E820_UNUSABLE] = "Unusable",
+};
+
+static const char *const bootloader_id[] = {
+	"LILO",
+	"Loadlin",
+	"bootsect-loader",
+	"Syslinux",
+	"Etherboot/gPXE/iPXE",
+	"ELILO",
+	"undefined",
+	"GRUB",
+	"U-Boot",
+	"Xen",
+	"Gujin",
+	"Qemu",
+	"Arcturus Networks uCbootloader",
+	"kexec-tools",
+	"Extended",
+	"Special",
+	"Reserved",
+	"Minimal Linux Bootloader",
+	"OVMF UEFI virtualization stack",
+};
+
+struct flag_info {
+	uint bit;
+	const char *name;
+};
+
+static struct flag_info load_flags[] = {
+	{ LOADED_HIGH, "loaded-high" },
+	{ QUIET_FLAG, "quiet" },
+	{ KEEP_SEGMENTS, "keep-segments" },
+	{ CAN_USE_HEAP, "can-use-heap" },
+};
+
+static struct flag_info xload_flags[] = {
+	{ XLF_KERNEL_64, "64-bit-entry" },
+	{ XLF_CAN_BE_LOADED_ABOVE_4G, "can-load-above-4gb" },
+	{ XLF_EFI_HANDOVER_32, "32-efi-handoff" },
+	{ XLF_EFI_HANDOVER_64, "64-efi-handoff" },
+	{ XLF_EFI_KEXEC, "kexec-efi-runtime" },
+};
+
+static void print_flags(struct flag_info *flags, int count, uint value)
+{
+	int i;
+
+	printf("%-20s:", "");
+	for (i = 0; i < count; i++) {
+		uint mask = flags[i].bit;
+
+		if (value & mask)
+			printf(" %s", flags[i].name);
+	}
+	printf("\n");
+}
+
+static void show_loader(struct setup_header *hdr)
+{
+	bool version_valid = false;
+	int type, version;
+	const char *name;
+
+	type = hdr->type_of_loader >> 4;
+	version = hdr->type_of_loader & 0xf;
+	if (type == 0xe)
+		type = 0x10 + hdr->ext_loader_type;
+	version |= hdr->ext_loader_ver << 4;
+	if (!hdr->type_of_loader) {
+		name = "pre-2.00 bootloader";
+	} else if (hdr->type_of_loader == 0xff) {
+		name = "unknown";
+	} else if (type < ARRAY_SIZE(bootloader_id)) {
+		name = bootloader_id[type];
+		version_valid = true;
+	} else {
+		name = "undefined";
+	}
+	printf("%20s  %s", "", name);
+	if (version_valid)
+		printf(", version %x", version);
+	printf("\n");
+}
+
+int do_zboot_dump(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct boot_params *base_ptr = state.base_ptr;
+	struct setup_header *hdr;
+	const char *version;
+	int i;
+
+	if (argc > 1)
+		base_ptr = (void *)simple_strtoul(argv[1], NULL, 16);
+	if (!base_ptr) {
+		printf("No zboot setup_base\n");
+		return CMD_RET_FAILURE;
+	}
+	printf("Setup located at %p:\n\n", base_ptr);
+	print_num64("ACPI RSDP addr", base_ptr->acpi_rsdp_addr);
+
+	printf("E820: %d entries\n", base_ptr->e820_entries);
+	if (base_ptr->e820_entries) {
+		printf("%18s  %16s  %s\n", "Addr", "Size", "Type");
+		for (i = 0; i < base_ptr->e820_entries; i++) {
+			struct e820_entry *entry = &base_ptr->e820_map[i];
+
+			printf("%12llx  %10llx  %s\n", entry->addr, entry->size,
+			       entry->type < E820_COUNT ?
+			       e820_type_name[entry->type] :
+			       simple_itoa(entry->type));
+		}
+	}
+
+	hdr = &base_ptr->hdr;
+	print_num("Setup sectors", hdr->setup_sects);
+	print_num("Root flags", hdr->root_flags);
+	print_num("Sys size", hdr->syssize);
+	print_num("RAM size", hdr->ram_size);
+	print_num("Video mode", hdr->vid_mode);
+	print_num("Root dev", hdr->root_dev);
+	print_num("Boot flag", hdr->boot_flag);
+	print_num("Jump", hdr->jump);
+	print_num("Header", hdr->header);
+	if (hdr->header == KERNEL_V2_MAGIC)
+		printf("%-20s  %s\n", "", "Kernel V2");
+	else
+		printf("%-20s  %s\n", "", "Ancient kernel, using version 100");
+	print_num("Version", hdr->version);
+	print_num("Real mode switch", hdr->realmode_swtch);
+	print_num("Start sys", hdr->start_sys);
+	print_num("Kernel version", hdr->kernel_version);
+	version = get_kernel_version(base_ptr, (void *)state.bzimage_addr);
+	if (version)
+		printf("   @%p: %s\n", version, version);
+	print_num("Type of loader", hdr->type_of_loader);
+	show_loader(hdr);
+	print_num("Load flags", hdr->loadflags);
+	print_flags(load_flags, ARRAY_SIZE(load_flags), hdr->loadflags);
+	print_num("Setup move size", hdr->setup_move_size);
+	print_num("Code32 start", hdr->code32_start);
+	print_num("Ramdisk image", hdr->ramdisk_image);
+	print_num("Ramdisk size", hdr->ramdisk_size);
+	print_num("Bootsect kludge", hdr->bootsect_kludge);
+	print_num("Heap end ptr", hdr->heap_end_ptr);
+	print_num("Ext loader ver", hdr->ext_loader_ver);
+	print_num("Ext loader type", hdr->ext_loader_type);
+	print_num("Command line ptr", hdr->cmd_line_ptr);
+	if (hdr->cmd_line_ptr) {
+		printf("   ");
+		/* Use puts() to avoid limits from CONFIG_SYS_PBSIZE */
+		puts((char *)(ulong)hdr->cmd_line_ptr);
+		printf("\n");
+	}
+	print_num("Initrd addr max", hdr->initrd_addr_max);
+	print_num("Kernel alignment", hdr->kernel_alignment);
+	print_num("Relocatable kernel", hdr->relocatable_kernel);
+	print_num("Min alignment", hdr->min_alignment);
+	if (hdr->min_alignment)
+		printf("%-20s: %x\n", "", 1 << hdr->min_alignment);
+	print_num("Xload flags", hdr->xloadflags);
+	print_flags(xload_flags, ARRAY_SIZE(xload_flags), hdr->xloadflags);
+	print_num("Cmdline size", hdr->cmdline_size);
+	print_num("Hardware subarch", hdr->hardware_subarch);
+	print_num64("HW subarch data", hdr->hardware_subarch_data);
+	print_num("Payload offset", hdr->payload_offset);
+	print_num("Payload length", hdr->payload_length);
+	print_num64("Setup data", hdr->setup_data);
+	print_num64("Pref address", hdr->pref_address);
+	print_num("Init size", hdr->init_size);
+	print_num("Handover offset", hdr->handover_offset);
+	if (get_boot_protocol(hdr, false) >= 0x215)
+		print_num("Kernel info offset", hdr->kernel_info_offset);
+
+	return 0;
+}
+
+/* Note: This defines the complete_zboot() function */
+U_BOOT_SUBCMDS(zboot,
+	U_BOOT_CMD_MKENT(start, 8, 1, do_zboot_start, "", ""),
+	U_BOOT_CMD_MKENT(load, 1, 1, do_zboot_load, "", ""),
+	U_BOOT_CMD_MKENT(setup, 1, 1, do_zboot_setup, "", ""),
+	U_BOOT_CMD_MKENT(info, 1, 1, do_zboot_info, "", ""),
+	U_BOOT_CMD_MKENT(go, 1, 1, do_zboot_go, "", ""),
+	U_BOOT_CMD_MKENT(dump, 2, 1, do_zboot_dump, "", ""),
+)
+
+int do_zboot_states(struct cmd_tbl *cmdtp, int flag, int argc,
+		    char *const argv[], int state_mask)
+{
+	int i;
+
+	for (i = 0; i < ZBOOT_STATE_COUNT; i++) {
+		struct cmd_tbl *cmd = &zboot_subcmds[i];
+		int mask = 1 << i;
+		int ret;
+
+		if (mask & state_mask) {
+			ret = cmd->cmd(cmd, flag, argc, argv);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+int do_zboot_parent(struct cmd_tbl *cmdtp, int flag, int argc,
+		    char *const argv[], int *repeatable)
+{
+	/* determine if we have a sub command */
+	if (argc > 1) {
+		char *endp;
+
+		simple_strtoul(argv[1], &endp, 16);
+		/*
+		 * endp pointing to nul means that argv[1] was just a valid
+		 * number, so pass it along to the normal processing
+		 */
+		if (*endp)
+			return do_zboot(cmdtp, flag, argc, argv, repeatable);
+	}
+
+	do_zboot_states(cmdtp, flag, argc, argv, ZBOOT_STATE_START |
+			ZBOOT_STATE_LOAD | ZBOOT_STATE_SETUP |
+			ZBOOT_STATE_INFO | ZBOOT_STATE_GO);
+
+	return CMD_RET_FAILURE;
 }
 
-U_BOOT_CMD(
-	zboot, 5, 0,	do_zboot,
-	"Boot bzImage",
-	"[addr] [size] [initrd addr] [initrd size]\n"
+U_BOOT_CMDREP_COMPLETE(
+	zboot, 8, do_zboot_parent, "Boot bzImage",
+	"[addr] [size] [initrd addr] [initrd size] [setup] [cmdline]\n"
 	"      addr -        The optional starting address of the bzimage.\n"
 	"                    If not set it defaults to the environment\n"
 	"                    variable \"fileaddr\".\n"
@@ -364,4 +725,17 @@ U_BOOT_CMD(
 	"                    zero.\n"
 	"      initrd addr - The address of the initrd image to use, if any.\n"
 	"      initrd size - The size of the initrd image to use, if any.\n"
+	"      setup -       The address of the kernel setup region, if this\n"
+	"                    is not at addr\n"
+	"      cmdline -     The address of the kernel command line, to\n"
+	"                    override U-Boot's normal cmdline generation\n"
+	"\n"
+	"Sub-commands to do part of the zboot sequence:\n"
+	"\tstart [addr [arg ...]] - specify arguments\n"
+	"\tload   - load OS image\n"
+	"\tsetup  - set up table\n"
+	"\tinfo   - show summary info\n"
+	"\tgo     - start OS\n"
+	"\tdump [addr]    - dump info (optional address of boot params)",
+	complete_zboot
 );

+ 1 - 1
board/google/chromebook_coral/Kconfig

@@ -23,7 +23,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select BOARD_ROMSIZE_KB_16384
 
 config PCIE_ECAM_BASE
-	default 0xf0000000
+	default 0xe0000000
 
 config EARLY_POST_CROS_EC
 	bool "Enable early post to Chrome OS EC"

+ 1 - 0
board/google/chromebook_coral/Makefile

@@ -3,3 +3,4 @@
 # Copyright 2019 Google LLC
 
 obj-y	+= coral.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt.o

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä