soc/intel/apollolake: Make SCI configurable

The System Control Interrupt is routed per default to IRQ 9. Some
mainboards use IRQ 9 for different purpose. Therefore it is necessary to
make the SCI configurable on Apollo Lake.

Change-Id: Ib4a7ce7d68a6f1f16f27d0902d83dc8774e785b1
Signed-off-by: Mario Scheithauer <mario.scheithauer@siemens.com>
Reviewed-on: https://review.coreboot.org/21584
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
diff --git a/src/soc/intel/apollolake/acpi.c b/src/soc/intel/apollolake/acpi.c
index e4846e4..df4e630 100644
--- a/src/soc/intel/apollolake/acpi.c
+++ b/src/soc/intel/apollolake/acpi.c
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2016 Intel Corp.
+ * Copyright 2017 Siemens AG.
  * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -69,6 +70,12 @@
 	return read32((void *)pmc_bar + IRQ_REG);
 }
 
+void soc_write_sci_irq_select(uint32_t scis)
+{
+	uintptr_t pmc_bar = soc_read_pmc_base();
+	write32((void *)pmc_bar + IRQ_REG, scis);
+}
+
 acpi_cstate_t *soc_get_cstate_map(size_t *entries)
 {
 	*entries = ARRAY_SIZE(cstate_map);
diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c
index cfc4b6f..5759fb6 100644
--- a/src/soc/intel/apollolake/chip.c
+++ b/src/soc/intel/apollolake/chip.c
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2015 - 2017 Intel Corp.
+ * Copyright 2017 Siemens AG.
  * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
  * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
  *
@@ -25,6 +26,7 @@
 #include <cpu/x86/msr.h>
 #include <device/device.h>
 #include <device/pci.h>
+#include <intelblocks/acpi.h>
 #include <intelblocks/fast_spi.h>
 #include <intelblocks/msr.h>
 #include <fsp/api.h>
@@ -287,6 +289,29 @@
 	MCHBAR32(MCHBAR_RAPL_PPL + 4) =  limit.hi & ~PKG_POWER_LIMIT_EN;
 }
 
+/* Overwrites the SCI IRQ if another IRQ number is given by device tree. */
+static void set_sci_irq(void)
+{
+	static struct soc_intel_apollolake_config *cfg;
+	struct device *dev = SA_DEV_ROOT;
+	uint32_t scis;
+
+	if (!dev || !dev->chip_info) {
+		printk(BIOS_ERR, "BUG! Could not find SOC devicetree config\n");
+		return;
+	}
+
+	cfg = dev->chip_info;
+
+	/* Change only if a device tree entry exists. */
+	if (cfg->sci_irq) {
+		scis = soc_read_sci_irq_select();
+		scis &= ~SCI_IRQ_SEL;
+		scis |= (cfg->sci_irq << SCI_IRQ_ADJUST) & SCI_IRQ_SEL;
+		soc_write_sci_irq_select(scis);
+	}
+}
+
 static void soc_init(void *data)
 {
 	struct global_nvs_t *gnvs;
@@ -319,6 +344,12 @@
 
 	/* Set RAPL MSR for Package power limits*/
 	set_power_limits();
+
+	/*
+	* FSP-S routes SCI to IRQ 9. With the help of this function you can
+	* select another IRQ for SCI.
+	*/
+	set_sci_irq();
 }
 
 static void soc_final(void *data)
diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h
index 33e2dad..882e481 100644
--- a/src/soc/intel/apollolake/chip.h
+++ b/src/soc/intel/apollolake/chip.h
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2015 Intel Corp.
+ * Copyright 2017 Siemens AG.
  * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -78,6 +79,9 @@
 	 */
 	uint32_t emmc_rx_cmd_data_cntl2;
 
+	/* Specifies on which IRQ the SCI will internally appear. */
+	uint8_t sci_irq;
+
 	/* Configure serial IRQ (SERIRQ) line. */
 	enum serirq_mode serirq_mode;
 
diff --git a/src/soc/intel/common/block/include/intelblocks/acpi.h b/src/soc/intel/common/block/include/intelblocks/acpi.h
index 010773b..85e6ca3 100644
--- a/src/soc/intel/common/block/include/intelblocks/acpi.h
+++ b/src/soc/intel/common/block/include/intelblocks/acpi.h
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2017 Intel Corp.
+ * Copyright 2017 Siemens AG.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,6 +32,9 @@
 /* Read the scis from soc specific register. Returns int scis value */
 uint32_t soc_read_sci_irq_select(void);
 
+/* Write the scis from soc specific register. */
+void soc_write_sci_irq_select(uint32_t scis);
+
 /*
  * Calls acpi_write_hpet which creates and fills HPET table and
  * adds it to the RSDT (and XSDT) structure.